Changes in / [be567e9:69bafd2]


Ignore:
Location:
src
Files:
3 added
13 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Decl.hpp

    rbe567e9 r69bafd2  
    2626#include "ParseNode.hpp"
    2727#include "StorageClasses.hpp"
    28 #include "Type.hpp"            // for Type, ptr<Type>
     28#include "TypeVar.hpp"
    2929#include "Visitor.hpp"
    3030#include "Parser/ParseNode.h"  // for DeclarationNode::Aggregate
     
    140140class TypeDecl final : public NamedTypeDecl {
    141141public:
    142         /// type variable variants. otype is a specialized dtype
    143         enum Kind { Dtype, Ftype, Ttype, NUMBER_OF_KINDS } kind;
     142        TypeVar::Kind kind;
    144143        bool sized;
    145144        ptr<Type> init;
     
    147146        /// Data extracted from a type decl
    148147        struct Data {
    149                 Kind kind;
     148                TypeVar::Kind kind;
    150149                bool isComplete;
    151150
    152                 Data() : kind( (Kind)-1 ), isComplete( false ) {}
     151                Data() : kind( (TypeVar::Kind)-1 ), isComplete( false ) {}
    153152                Data( TypeDecl* d ) : kind( d->kind ), isComplete( d->sized ) {}
    154                 Data( Kind k, bool c ) : kind( k ), isComplete( c ) {}
     153                Data( TypeVar::Kind k, bool c ) : kind( k ), isComplete( c ) {}
    155154                Data( const Data& d1, const Data& d2 )
    156155                : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {}
     
    163162
    164163        TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b,
    165                 Kind k, bool s, Type* i = nullptr )
    166         : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ), init( i ) {}
     164                TypeVar::Kind k, bool s, Type* i = nullptr )
     165        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
     166          init( i ) {}
    167167
    168168        std::string typeString() const override;
    169169        /// Produces a name for generated code
    170170        std::string genTypeString() const;
     171
     172        /// convenience accessor to match Type::isComplete()
     173        bool isComplete() { return sized; }
    171174
    172175        virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Expr.hpp

    rbe567e9 r69bafd2  
    2323#include "Fwd.hpp"        // for UniqueId
    2424#include "ParseNode.hpp"
    25 #include "Type.hpp"       // for ptr<Type>
     25#include "Visitor.hpp"
    2626
    2727namespace ast {
     
    117117        bool extension = false;
    118118
    119         Expr(const CodeLocation& loc ) : ParseNode( loc ), result(), env(), inferred() {}
    120 
    121         Expr* set_extension( bool ex ) { extension = ex; return this; }
    122 
    123         virtual const Expr * accept( Visitor& v ) const override = 0;
     119        Expr(const CodeLocation & loc ) : ParseNode( loc ), result(), env(), inferred() {}
     120
     121        Expr * set_extension( bool ex ) { extension = ex; return this; }
     122
     123        virtual const Expr * accept( Visitor & v ) const override = 0;
    124124private:
    125125        virtual Expr * clone() const override = 0;
     126};
     127
     128/// A type used as an expression (e.g. a type generator parameter)
     129class TypeExpr final : public Expr {
     130public:
     131        ptr<Type> type;
     132
     133        TypeExpr( const CodeLocation & loc, const Type * t ) : Expr(loc), type(t) {}
     134
     135        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     136private:
     137        TypeExpr * clone() const override { return new TypeExpr{ *this }; }
    126138};
    127139
  • src/AST/FunctionSpec.hpp

    rbe567e9 r69bafd2  
    4343                };
    4444
    45                 constexpr spec_flags( unsigned int val ) : val(val) {}
     45                constexpr spec_flags( unsigned int val = 0 ) : val(val) {}
    4646        };
    4747
  • src/AST/Fwd.hpp

    rbe567e9 r69bafd2  
    118118class TupleType;
    119119class TypeofType;
    120 class AttrType;
    121120class VarArgsType;
    122121class ZeroType;
     
    335334inline void increment( const class TypeofType *, Node::ref_type );
    336335inline void decrement( const class TypeofType *, Node::ref_type );
    337 inline void increment( const class AttrType *, Node::ref_type );
    338 inline void decrement( const class AttrType *, Node::ref_type );
    339336inline void increment( const class VarArgsType *, Node::ref_type );
    340337inline void decrement( const class VarArgsType *, Node::ref_type );
  • src/AST/Init.hpp

    rbe567e9 r69bafd2  
    4242};
    4343
     44/// Flag for whether to construct from initialzier
     45enum ConstructFlag { DoConstruct, MaybeConstruct };
     46
    4447/// Object initializer base class
    4548class Init : public ParseNode {
    4649public:
    47         bool maybeConstructed;
     50        ConstructFlag maybeConstructed;
    4851
    49         Init( const CodeLocation& loc, bool mc ) : ParseNode( loc ), maybeConstructed( mc ) {}
     52        Init( const CodeLocation& loc, ConstructFlag mc ) : ParseNode( loc ), maybeConstructed( mc ) {}
    5053
    5154        virtual const Init * accept( Visitor& v ) const override = 0;
     
    6063        ptr<Expr> value;
    6164
    62         SingleInit( const CodeLocation& loc, Expr* val, bool mc = false )
     65        SingleInit( const CodeLocation& loc, Expr* val, ConstructFlag mc = DoConstruct )
    6366        : Init( loc, mc ), value( val ) {}
    6467
     
    8285
    8386        ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is,
    84                 std::vector<ptr<Designation>>&& ds = {}, bool mc = false );
     87                std::vector<ptr<Designation>>&& ds = {}, ConstructFlag mc = DoConstruct );
    8588
    8689        using iterator = std::vector<ptr<Init>>::iterator;
     
    112115
    113116        ConstructorInit( const CodeLocation& loc, Stmt* ctor, Stmt* dtor, Init* init )
    114         : Init( loc, true ), ctor( ctor ), dtor( dtor ), init( init ) {}
     117        : Init( loc, DoConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
    115118
    116119        virtual const Init * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Node.hpp

    rbe567e9 r69bafd2  
    9494std::ostream& operator<< ( std::ostream& out, const Node* node );
    9595
    96 // Base class for the smart pointer types
    97 // should never really be used.
    98 template< typename node_t, enum Node::ref_type ref_t>
     96/// Base class for the smart pointer types
     97/// should never really be used.
     98template< typename node_t, enum Node::ref_type ref_t >
    9999class ptr_base {
    100100public:
    101101        ptr_base() : node(nullptr) {}
    102         ptr_base( const node_t * n ) : node(n) { if( !node ) increment(node, ref_t); }
     102        ptr_base( const node_t * n ) : node(n) { if( node ) increment(node, ref_t); }
    103103        ~ptr_base() { if( node ) decrement(node, ref_t); }
    104104
    105         template< enum  Node::ref_type o_ref_t >
     105        template< enum Node::ref_type o_ref_t >
    106106        ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
    107                 if( !node ) return;
    108                 increment(node, ref_t);
     107                if( node ) increment(node, ref_t);
    109108        }
    110109
    111         template< enum  Node::ref_type o_ref_t >
     110        template< enum Node::ref_type o_ref_t >
    112111        ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.node) {
    113112                if( node ) increment(node, ref_t);
     
    120119        }
    121120
    122         template< enum  Node::ref_type o_ref_t >
     121        template< enum Node::ref_type o_ref_t >
    123122        ptr_base & operator=( const ptr_base<node_t, o_ref_t> & o ) {
    124123                assign(o.node);
     
    126125        }
    127126
    128         template< enum  Node::ref_type o_ref_t >
     127        template< enum Node::ref_type o_ref_t >
    129128        ptr_base & operator=( ptr_base<node_t, o_ref_t> && o ) {
    130                 if(o.node == node) return *this;
    131129                assign(o.node);
    132130                return *this;
     
    140138
    141139        template<typename o_node_t>
    142         const o_node_t * as() const { return dynamic_cast<o_node_t *>(node); }
     140        const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); }
    143141
    144142        using ptr = const node_t *;
    145143
    146144private:
    147         void assign(const node_t * other ) {
     145        void assign( const node_t * other ) {
    148146                if( other ) increment(other, ref_t);
    149147                if( node  ) decrement(node , ref_t);
  • src/AST/Pass.hpp

    rbe567e9 r69bafd2  
    167167        virtual const ast::Type *             visit( const ast::TupleType            * ) override final;
    168168        virtual const ast::Type *             visit( const ast::TypeofType           * ) override final;
    169         virtual const ast::Type *             visit( const ast::AttrType             * ) override final;
    170169        virtual const ast::Type *             visit( const ast::VarArgsType          * ) override final;
    171170        virtual const ast::Type *             visit( const ast::ZeroType             * ) override final;
  • src/AST/StorageClasses.hpp

    rbe567e9 r69bafd2  
    4747                };
    4848
    49                 constexpr class_flags( unsigned int val ) : val(val) {}
     49                constexpr class_flags( unsigned int val = 0 ) : val(val) {}
    5050        };
    5151
  • src/AST/Type.hpp

    rbe567e9 r69bafd2  
    1616#pragma once
    1717
    18 #include "Node.hpp"
     18#include <cassert>
     19#include <cstddef>           // for nullptr_t
     20#include <cstdint>           // for uintptr_t
     21#include <utility>           // for move
     22#include <vector>
     23
     24#include "CVQualifiers.hpp"
     25#include "Fwd.hpp"
     26#include "Node.hpp"          // for Node, ptr
     27#include "TypeVar.hpp"
     28#include "Visitor.hpp"
    1929
    2030namespace ast {
    2131
    2232class Type : public Node {
    23 public:
    24 virtual const Type * accept( Visitor & v) const = 0;
    25 };
    26 
    27 
     33        CV::Qualifiers tq;
     34public:
     35        Type( CV::Qualifiers q = {} ) : tq(q) {}
     36
     37        CV::Qualifiers qualifiers() const { return tq; }
     38        bool is_const() const { return tq.is_const; }
     39        bool is_volatile() const { return tq.is_volatile; }
     40        bool is_restrict() const { return tq.is_restrict; }
     41        bool is_lvalue() const { return tq.is_lvalue; }
     42        bool is_mutex() const { return tq.is_mutex; }
     43        bool is_atomic() const { return tq.is_atomic; }
     44
     45        void set_qualifiers( CV::Qualifiers q ) { tq = q; }
     46        void set_const( bool v ) { tq.is_const = v; }
     47        void set_restrict( bool v ) { tq.is_restrict = v; }
     48        void set_lvalue( bool v ) { tq.is_lvalue = v; }
     49        void set_mutex( bool v ) { tq.is_mutex = v; }
     50        void set_atomic( bool v ) { tq.is_atomic = v; }
     51
     52        /// How many elemental types are represented by this type
     53        virtual unsigned size() const { return 1; }
     54        /// Is this a void type?
     55        virtual bool isVoid() const { return size() == 0; }
     56        /// Get the i'th component of this type
     57        virtual const Type * getComponent( unsigned i );
     58
     59        /// type without outer pointers and arrays
     60        const Type * stripDeclarator();
     61        /// type without outer references
     62        const Type * stripReferences();
     63        /// number of reference occuring consecutively on the outermost layer of this type
     64        /// (i.e. do not count references nested within other types)
     65        virtual unsigned referenceDepth() const { return 0; }
     66        /// true iff type is complete type (i.e. compiler knows the size, alignment, and layout)
     67        virtual bool isComplete() const { return true; }
     68
     69        virtual const Type * accept( Visitor & v ) const override = 0;
     70private:
     71        virtual Type * clone() const override = 0;
     72};
     73
     74/// `void`
     75class VoidType final : public Type {
     76public:
     77        VoidType( CV::Qualifiers q = {} ) : Type( q ) {}
     78       
     79        unsigned size() const override { return 0; }
     80        bool isVoid() const override { return true; }
     81        bool isComplete() const override { return false; }
     82
     83        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     84private:
     85        VoidType * clone() const override { return new VoidType{ *this }; }
     86};
     87
     88/// Built-in arithmetic type
     89class BasicType final : public Type {
     90public:
     91        // GENERATED START, DO NOT EDIT
     92        // GENERATED BY BasicTypes-gen.cc
     93        enum Kind {
     94                Bool,
     95                Char,
     96                SignedChar,
     97                UnsignedChar,
     98                ShortSignedInt,
     99                ShortUnsignedInt,
     100                SignedInt,
     101                UnsignedInt,
     102                LongSignedInt,
     103                LongUnsignedInt,
     104                LongLongSignedInt,
     105                LongLongUnsignedInt,
     106                SignedInt128,
     107                UnsignedInt128,
     108                uFloat16,
     109                uFloat16Complex,
     110                uFloat32,
     111                uFloat32Complex,
     112                Float,
     113                FloatComplex,
     114                uFloat32x,
     115                uFloat32xComplex,
     116                uFloat64,
     117                uFloat64Complex,
     118                Double,
     119                DoubleComplex,
     120                uFloat64x,
     121                uFloat64xComplex,
     122                uuFloat80,
     123                uFloat128,
     124                uFloat128Complex,
     125                uuFloat128,
     126                LongDouble,
     127                LongDoubleComplex,
     128                uFloat128x,
     129                uFloat128xComplex,
     130                NUMBER_OF_BASIC_TYPES
     131        } kind;
     132        // GENERATED END
     133
     134        /// xxx -- MAX_INTEGER_TYPE should probably be in BasicTypes-gen.cc, rather than hardcoded here
     135        enum { MAX_INTEGER_TYPE = UnsignedInt128 };
     136
     137        /// string names of basic types; generated to match with Kind
     138        static const char *typeNames[];
     139
     140        BasicType( Kind k, CV::Qualifiers q = {} ) : Type(q), kind(k) {}
     141
     142        /// Check if this type represents an integer type
     143        bool isInteger() const { return kind <= MAX_INTEGER_TYPE; }
     144
     145        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     146private:
     147        BasicType * clone() const override { return new BasicType{ *this }; }
     148};
     149
     150/// Pointer/array variable length?
     151enum LengthFlag { FixedLen, VariableLen };
     152
     153/// Pointer/array static dimension?
     154enum DimensionFlag { DynamicDim, StaticDim };
     155
     156/// Pointer type `T*`
     157class PointerType final : public Type {
     158public:
     159        ptr<Type> base;
     160
     161        // In C99, pointer types can be qualified in many ways, e.g. `int a[ static 3 ]`
     162        ptr<Expr> dimension;
     163        LengthFlag isVarLen = FixedLen;
     164        DimensionFlag isStatic = DynamicDim;
     165
     166        PointerType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b), dimension() {}
     167        PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
     168                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
     169
     170        // true if this pointer is actually an array
     171        bool isArray() const { return isVarLen || isStatic || dimension; }
     172
     173        bool isComplete() const override { return ! isVarLen; }
     174
     175        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     176private:
     177        PointerType * clone() const override { return new PointerType{ *this }; }
     178};
     179
     180/// Array type `T[]`
     181class ArrayType final : public Type {
     182public:
     183        ptr<Type> base;
     184        ptr<Expr> dimension;
     185        LengthFlag isVarLen;
     186        DimensionFlag isStatic;
     187
     188        ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
     189                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
     190
     191        // array types are complete if they have a dimension expression or are
     192        // VLAs ('*' in parameter declaration), and incomplete otherwise.
     193        // See 6.7.6.2
     194        bool isComplete() const override { return dimension || isVarLen; }
     195
     196        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     197private:
     198        ArrayType * clone() const override { return new ArrayType{ *this }; }
     199};
     200
     201/// Reference type `T&`
     202class ReferenceType final : public Type {
     203public:
     204        ptr<Type> base;
     205
     206        ReferenceType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
     207
     208        unsigned referenceDepth() const override { return base->referenceDepth() + 1; }
     209
     210        // Since reference types act like value types, their size is the size of the base.
     211        // This makes it simple to cast the empty tuple to a reference type, since casts that increase
     212        // the number of values are disallowed.
     213        unsigned size() const override { return base->size(); }
     214
     215        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     216private:
     217        ReferenceType * clone() const override { return new ReferenceType{ *this }; }
     218};
     219
     220/// Qualified type `P.C`
     221class QualifiedType final : public Type {
     222public:
     223        ptr<Type> parent;
     224        ptr<Type> child;
     225
     226        QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} )
     227        : Type(q), parent(p), child(c) {}
     228
     229        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     230private:
     231        QualifiedType * clone() const override { return new QualifiedType{ *this }; }
     232};
     233
     234/// Base type for potentially forall-qualified types
     235class ParameterizedType : public Type {
     236public:
     237        using ForallList = std::vector<ptr<TypeDecl>>;
     238
     239        ForallList forall;
     240
     241        ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {} )
     242        : Type(q), forall(std::move(fs)) {}
     243        ParameterizedType( CV::Qualifiers q ) : Type(q), forall() {}
     244
     245private:
     246        virtual ParameterizedType * clone() const override = 0;
     247};
     248
     249/// Function variable arguments flag
     250enum ArgumentFlag { FixedArgs, VariableArgs };
     251
     252/// Type of a function `[R1, R2](*)(P1, P2, P3)`
     253class FunctionType final : public ParameterizedType {
     254public:
     255        std::vector<ptr<DeclWithType>> returnVals;
     256        std::vector<ptr<DeclWithType>> parameters;
     257
     258        /// Does the function accept a variable number of arguments following the arguments specified
     259        /// in the parameters list.
     260        /// This could be because of
     261        /// - an ellipsis in a prototype declaration
     262        /// - an unprototyped declaration
     263        ArgumentFlag isVarArgs;
     264
     265        FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
     266        : ParameterizedType(q), returnVals(), parameters(), isVarArgs(va) {}
     267
     268        /// true if either the parameters or return values contain a tttype
     269        bool isTtype() const;
     270        /// true if function parameters are unconstrained by prototype
     271        bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; }
     272
     273        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     274private:
     275        FunctionType * clone() const override { return new FunctionType{ *this }; }
     276};
     277
     278/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
     279class ReferenceToType : public ParameterizedType {
     280public:
     281        std::vector<ptr<Expr>> parameters;
     282        std::vector<ptr<Attribute>> attributes;
     283        std::string name;
     284        bool hoistType = false;
     285
     286        ReferenceToType( const std::string& n, CV::Qualifiers q = {},
     287                std::vector<ptr<Attribute>> && as = {} )
     288        : ParameterizedType(q), parameters(), attributes(std::move(as)), name(n) {}
     289
     290        /// Gets aggregate declaration this type refers to
     291        virtual const AggregateDecl * aggr() const = 0;
     292        /// Looks up member declarations with given name
     293        std::vector<readonly<Decl>> lookup( const std::string & name ) const;
     294
     295private:
     296        virtual ReferenceToType * clone() const override = 0;
     297
     298protected:
     299        /// Name for the kind of type this is
     300        virtual std::string typeString() const = 0;
     301};
     302
     303/// instance of struct type
     304class StructInstType final : public ReferenceToType {
     305public:
     306        readonly<StructDecl> base;
     307
     308        StructInstType( const std::string& n, CV::Qualifiers q = {},
     309                std::vector<ptr<Attribute>> && as = {} )
     310        : ReferenceToType( n, q, std::move(as) ), base() {}
     311        StructInstType( const StructDecl * b, CV::Qualifiers q = {},
     312                std::vector<ptr<Attribute>> && as = {} );
     313       
     314        bool isComplete() const override;
     315
     316        const StructDecl * aggr() const override { return base; }
     317
     318        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     319private:
     320        StructInstType * clone() const override { return new StructInstType{ *this }; }
     321
     322        std::string typeString() const override { return "struct"; }
     323};
     324
     325/// instance of union type
     326class UnionInstType final : public ReferenceToType {
     327public:
     328        readonly<UnionDecl> base;
     329
     330        UnionInstType( const std::string& n, CV::Qualifiers q = {},
     331                std::vector<ptr<Attribute>> && as = {} )
     332        : ReferenceToType( n, q, std::move(as) ), base() {}
     333        UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
     334                std::vector<ptr<Attribute>> && as = {} );
     335       
     336        bool isComplete() const override;
     337
     338        const UnionDecl * aggr() const override { return base; }
     339
     340        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     341private:
     342        UnionInstType * clone() const override { return new UnionInstType{ *this }; }
     343
     344        std::string typeString() const override { return "union"; }
     345};
     346
     347/// instance of enum type
     348class EnumInstType final : public ReferenceToType {
     349public:
     350        readonly<EnumDecl> base;
     351
     352        EnumInstType( const std::string& n, CV::Qualifiers q = {},
     353                std::vector<ptr<Attribute>> && as = {} )
     354        : ReferenceToType( n, q, std::move(as) ), base() {}
     355        EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
     356                std::vector<ptr<Attribute>> && as = {} );
     357       
     358        bool isComplete() const override;
     359
     360        const EnumDecl * aggr() const override { return base; }
     361
     362        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     363private:
     364        EnumInstType * clone() const override { return new EnumInstType{ *this }; }
     365
     366        std::string typeString() const override { return "enum"; }
     367};
     368
     369/// instance of trait type
     370class TraitInstType final : public ReferenceToType {
     371public:
     372        readonly<TraitDecl> base;
     373
     374        TraitInstType( const std::string& n, CV::Qualifiers q = {},
     375                std::vector<ptr<Attribute>> && as = {} )
     376        : ReferenceToType( n, q, std::move(as) ), base() {}
     377        TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
     378                std::vector<ptr<Attribute>> && as = {} );
     379       
     380        // not meaningful for TraitInstType
     381        bool isComplete() const override { assert(false); }
     382
     383        const TraitDecl * aggr() const override { return base; }
     384
     385        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     386private:
     387        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
     388
     389        std::string typeString() const override { return "trait"; }
     390};
     391
     392/// instance of named type alias (typedef or variable)
     393class TypeInstType final : public ReferenceToType {
     394public:
     395        readonly<TypeDecl> base;
     396        TypeVar::Kind kind;
     397
     398        TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     399                std::vector<ptr<Attribute>> && as = {} )
     400        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     401        TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
     402                std::vector<ptr<Attribute>> && as = {} )
     403        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
     404
     405        /// sets `base`, updating `kind` correctly
     406        void set_base( const TypeDecl * );
     407
     408        bool isComplete() const override;
     409
     410        // not meaningful for TypeInstType
     411        const AggregateDecl * aggr() const override { assert(false); }
     412
     413        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     414private:
     415        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
     416
     417        std::string typeString() const override { return "type"; }
     418};
     419
     420/// tuple type e.g. `[int, char]`
     421class TupleType final : public Type {
     422public:
     423        std::vector<ptr<Type>> types;
     424        std::vector<ptr<Decl>> members;
     425
     426        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
     427
     428        // collection simulation
     429        using iterator = std::vector<ptr<Type>>::const_iterator;
     430        iterator begin() const { return types.begin(); }
     431        iterator end() const { return types.end(); }
     432       
     433        unsigned size() const override { return types.size(); }
     434
     435        const Type * getComponent( unsigned i ) override {
     436                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
     437                        i, size() );
     438                return *(begin()+i);
     439        }
     440
     441        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     442private:
     443        TupleType * clone() const override { return new TupleType{ *this }; }
     444};
     445
     446/// Type of unresolved `typeof()` expression
     447class TypeofType : public Type {
     448public:
     449        ptr<Expr> expr;
     450        enum Kind { Typeof, Basetypeof } kind;
     451
     452        TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
     453        : Type(q), expr(e), kind(k) {}
     454
     455        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     456private:
     457        TypeofType * clone() const override { return new TypeofType{ *this }; }
     458};
     459
     460/// GCC built-in varargs type
     461class VarArgsType final : public Type {
     462public:
     463        VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
     464       
     465        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     466private:
     467        VarArgsType * clone() const override { return new VarArgsType{ *this }; }
     468};
     469
     470/// Type of zero constant `0`
     471class ZeroType final : public Type {
     472public:
     473        ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
     474       
     475        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     476private:
     477        ZeroType * clone() const override { return new ZeroType{ *this }; }     
     478};
     479
     480/// Type of one constant `1`
     481class OneType final : public Type {
     482public:
     483        OneType( CV::Qualifiers q = {} ) : Type( q ) {}
     484
     485        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     486private:
     487        OneType * clone() const override { return new OneType{ *this }; }
     488};
     489
     490/// Parent type for scope-qualified types at global scope
     491class GlobalScopeType final : public Type {
     492public:
     493        GlobalScopeType( CV::Qualifiers q = {} ) : Type( q ) {}
     494
     495        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     496private:
     497        GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
     498};
    28499
    29500//=================================================================================================
    30501/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
    31 /// remove only if there is a better solution
     502/// remove only if there is a better solution.
    32503/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
    33504/// forward declarations
    34 inline void increment( const class Type * /*node*/, Node::ref_type /*ref*/ ) { /*node->increment( ref );*/ }
    35 inline void decrement( const class Type * /*node*/, Node::ref_type /*ref*/ ) { /*node->decrement( ref );*/ }
    36 // inline void increment( const class VoidType * node, Node::ref_type ref ) { node->increment( ref ); }
    37 // inline void decrement( const class VoidType * node, Node::ref_type ref ) { node->decrement( ref ); }
    38 // inline void increment( const class BasicType * node, Node::ref_type ref ) { node->increment( ref ); }
    39 // inline void decrement( const class BasicType * node, Node::ref_type ref ) { node->decrement( ref ); }
    40 // inline void increment( const class PointerType * node, Node::ref_type ref ) { node->increment( ref ); }
    41 // inline void decrement( const class PointerType * node, Node::ref_type ref ) { node->decrement( ref ); }
    42 // inline void increment( const class ArrayType * node, Node::ref_type ref ) { node->increment( ref ); }
    43 // inline void decrement( const class ArrayType * node, Node::ref_type ref ) { node->decrement( ref ); }
    44 // inline void increment( const class ReferenceType * node, Node::ref_type ref ) { node->increment( ref ); }
    45 // inline void decrement( const class ReferenceType * node, Node::ref_type ref ) { node->decrement( ref ); }
    46 // inline void increment( const class QualifiedType * node, Node::ref_type ref ) { node->increment( ref ); }
    47 // inline void decrement( const class QualifiedType * node, Node::ref_type ref ) { node->decrement( ref ); }
    48 // inline void increment( const class FunctionType * node, Node::ref_type ref ) { node->increment( ref ); }
    49 // inline void decrement( const class FunctionType * node, Node::ref_type ref ) { node->decrement( ref ); }
    50 // inline void increment( const class ReferenceToType * node, Node::ref_type ref ) { node->increment( ref ); }
    51 // inline void decrement( const class ReferenceToType * node, Node::ref_type ref ) { node->decrement( ref ); }
    52 // inline void increment( const class StructInstType * node, Node::ref_type ref ) { node->increment( ref ); }
    53 // inline void decrement( const class StructInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
    54 // inline void increment( const class UnionInstType * node, Node::ref_type ref ) { node->increment( ref ); }
    55 // inline void decrement( const class UnionInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
    56 // inline void increment( const class EnumInstType * node, Node::ref_type ref ) { node->increment( ref ); }
    57 // inline void decrement( const class EnumInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
    58 // inline void increment( const class TraitInstType * node, Node::ref_type ref ) { node->increment( ref ); }
    59 // inline void decrement( const class TraitInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
    60 // inline void increment( const class TypeInstType * node, Node::ref_type ref ) { node->increment( ref ); }
    61 // inline void decrement( const class TypeInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
    62 // inline void increment( const class TupleType * node, Node::ref_type ref ) { node->increment( ref ); }
    63 // inline void decrement( const class TupleType * node, Node::ref_type ref ) { node->decrement( ref ); }
    64 // inline void increment( const class TypeofType * node, Node::ref_type ref ) { node->increment( ref ); }
    65 // inline void decrement( const class TypeofType * node, Node::ref_type ref ) { node->decrement( ref ); }
    66 // inline void increment( const class AttrType * node, Node::ref_type ref ) { node->increment( ref ); }
    67 // inline void decrement( const class AttrType * node, Node::ref_type ref ) { node->decrement( ref ); }
    68 // inline void increment( const class VarArgsType * node, Node::ref_type ref ) { node->increment( ref ); }
    69 // inline void decrement( const class VarArgsType * node, Node::ref_type ref ) { node->decrement( ref ); }
    70 // inline void increment( const class ZeroType * node, Node::ref_type ref ) { node->increment( ref ); }
    71 // inline void decrement( const class ZeroType * node, Node::ref_type ref ) { node->decrement( ref ); }
    72 // inline void increment( const class OneType * node, Node::ref_type ref ) { node->increment( ref ); }
    73 // inline void decrement( const class OneType * node, Node::ref_type ref ) { node->decrement( ref ); }
    74 // inline void increment( const class GlobalScopeType * node, Node::ref_type ref ) { node->increment( ref ); }
    75 // inline void decrement( const class GlobalScopeType * node, Node::ref_type ref ) { node->decrement( ref ); }
     505inline void increment( const class Type * node, Node::ref_type ref ) { node->increment( ref ); }
     506inline void decrement( const class Type * node, Node::ref_type ref ) { node->decrement( ref ); }
     507inline void increment( const class VoidType * node, Node::ref_type ref ) { node->increment( ref ); }
     508inline void decrement( const class VoidType * node, Node::ref_type ref ) { node->decrement( ref ); }
     509inline void increment( const class BasicType * node, Node::ref_type ref ) { node->increment( ref ); }
     510inline void decrement( const class BasicType * node, Node::ref_type ref ) { node->decrement( ref ); }
     511inline void increment( const class PointerType * node, Node::ref_type ref ) { node->increment( ref ); }
     512inline void decrement( const class PointerType * node, Node::ref_type ref ) { node->decrement( ref ); }
     513inline void increment( const class ArrayType * node, Node::ref_type ref ) { node->increment( ref ); }
     514inline void decrement( const class ArrayType * node, Node::ref_type ref ) { node->decrement( ref ); }
     515inline void increment( const class ReferenceType * node, Node::ref_type ref ) { node->increment( ref ); }
     516inline void decrement( const class ReferenceType * node, Node::ref_type ref ) { node->decrement( ref ); }
     517inline void increment( const class QualifiedType * node, Node::ref_type ref ) { node->increment( ref ); }
     518inline void decrement( const class QualifiedType * node, Node::ref_type ref ) { node->decrement( ref ); }
     519inline void increment( const class FunctionType * node, Node::ref_type ref ) { node->increment( ref ); }
     520inline void decrement( const class FunctionType * node, Node::ref_type ref ) { node->decrement( ref ); }
     521inline void increment( const class ReferenceToType * node, Node::ref_type ref ) { node->increment( ref ); }
     522inline void decrement( const class ReferenceToType * node, Node::ref_type ref ) { node->decrement( ref ); }
     523inline void increment( const class StructInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     524inline void decrement( const class StructInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     525inline void increment( const class UnionInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     526inline void decrement( const class UnionInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     527inline void increment( const class EnumInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     528inline void decrement( const class EnumInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     529inline void increment( const class TraitInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     530inline void decrement( const class TraitInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     531inline void increment( const class TypeInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     532inline void decrement( const class TypeInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     533inline void increment( const class TupleType * node, Node::ref_type ref ) { node->increment( ref ); }
     534inline void decrement( const class TupleType * node, Node::ref_type ref ) { node->decrement( ref ); }
     535inline void increment( const class TypeofType * node, Node::ref_type ref ) { node->increment( ref ); }
     536inline void decrement( const class TypeofType * node, Node::ref_type ref ) { node->decrement( ref ); }
     537inline void increment( const class VarArgsType * node, Node::ref_type ref ) { node->increment( ref ); }
     538inline void decrement( const class VarArgsType * node, Node::ref_type ref ) { node->decrement( ref ); }
     539inline void increment( const class ZeroType * node, Node::ref_type ref ) { node->increment( ref ); }
     540inline void decrement( const class ZeroType * node, Node::ref_type ref ) { node->decrement( ref ); }
     541inline void increment( const class OneType * node, Node::ref_type ref ) { node->increment( ref ); }
     542inline void decrement( const class OneType * node, Node::ref_type ref ) { node->decrement( ref ); }
     543inline void increment( const class GlobalScopeType * node, Node::ref_type ref ) { node->increment( ref ); }
     544inline void decrement( const class GlobalScopeType * node, Node::ref_type ref ) { node->decrement( ref ); }
    76545
    77546}
  • src/AST/Visitor.hpp

    rbe567e9 r69bafd2  
    104104    virtual const ast::Type *             visit( const ast::TupleType            * ) = 0;
    105105    virtual const ast::Type *             visit( const ast::TypeofType           * ) = 0;
    106     virtual const ast::Type *             visit( const ast::AttrType             * ) = 0;
    107106    virtual const ast::Type *             visit( const ast::VarArgsType          * ) = 0;
    108107    virtual const ast::Type *             visit( const ast::ZeroType             * ) = 0;
  • src/AST/porting.md

    rbe567e9 r69bafd2  
    3636* allows compiler to optimize virtual calls to static calls if given static type
    3737
    38 Pulled `FuncSpecifiers` and `StorageClasses` out of `Type` into their own headers
     38Pulled `FuncSpecifiers`, `StorageClasses`, `CVQualifiers` out of `Type` into their own headers
    3939* Made `BFCommon` a `MakeBitfield` macro in its own header
    4040  * added default and field-init constructors to macro
     
    7070        * `Initializer` => `ast::Init`
    7171    * `Statement` => `ast::Stmt`
     72        * any field names should follow a similar renaming
    7273  * because they don't really belong to `Type` (and for consistency with `Linkage::Spec`):
    7374    * `Type::StorageClasses` => `ast::Storage::Classes`
    7475          * `Type::Extern` etc. => `ast::Storage::Extern` etc.
     76        * `Type::FuncSpecifiers` => `ast::Function::Specs`
     77          * `Type::Inline` etc. => `ast::Function::Inline` etc.
     78        * `Type::Qualifiers` => `ast::CV::Qualifiers`
     79          * `Type::Const` etc. => `ast::CV::Const`
     80          * couldn't break name-dependency loop without pulling `Qualifiers` out of `Type`
    7581        * `LinkageSpec::Spec` => `ast::Linkage::Spec`
    7682          * `LinkageSpec::Mangle` etc. => `ast::Linkage::Mangle` etc.
     
    7985          * `LinkageSpec::isMangled(Spec)` etc. => `Spec.is_mangled` etc.
    8086          * `LinkageSpec::Intrinsic` etc. => `ast::Linkage::Intrinsic` etc.
     87* Boolean constructor parameters get replaced with a dedicated flag enum:
     88  * e.g. `bool isVarLen;` => `enum LengthFlag { FixedLen, VariableLen };` `LengthFlag isVarLen;`
     89  * field can be *read* in the existing boolean contexts, but requires documentation to write
     90  * suggest naming all flag enums `FooFlag` to hint at boolean nature
    8191
    8292## Specific Nodes ##
     
    97107
    98108`TypeDecl`
    99 * stripped `isComplete()` accessor in favour of direct access to `sized`
     109* moved `TypeDecl::Kind` to `ast::TypeVar::Kind`
    100110
    101111`EnumDecl`
     
    106116  * does imply get_/set_ API, and some care about moving backward
    107117
     118`Init`
     119* `bool maybeConstruct` => `enum ConstructFlag { DoConstruct, MaybeConstruct }`
     120
    108121`Label`
    109122* `get_statement()` exclusively used for code location, replaced with `CodeLocation` field
     
    112125* **TODO** port copy operator
    113126  * Needs to be an almost-shallow clone, where the declarations are cloned only if needed
    114   * **TODO** port DeclReplacer
     127  * **TODO** port `DeclReplacer`
    115128* Still a `std::list` for children, rather than `std::vector`
    116129  * allows more-efficient splicing for purposes of later code generation
    117130
    118131`Type`
     132* `CV::Qualifiers` moved to end of constructor parameter list, defaulted to `{}`
     133  * `ReferenceToType` puts a defaulted list of attributes after qualifiers
    119134* `forall` field split off into `ParameterizedType` subclass
    120135  * any type that needs it can inherit from `ParameterizedType`
     136    * currently `FunctionType`, `ReferenceToType`
    121137* `get_qualifiers()` replaced with accessor `qualifiers()` and mutator `set_qualifiers()`
    122   * `get_CV()` replaced with `is_CV()` variants
     138  * `get_const()` etc. replaced with `is_const()` etc. variants
     139* `referenceDepth()` now returns `unsigned` rather than `int`
    123140* A number of features only supported on aggregates pushed down to `ReferenceToType`:
    124141  * `attributes`: per docs [1] GCC only supports type attributes on aggregates and typedefs
    125142    * suggest adding a `TypeWithAttributes` wrapper type if this proves insufficient
    126   * `getAggr()`
    127   * `genericSubstitution()`
     143  * `getAggr()` => `aggr()`
     144    * also now returns `const AggregateDecl *`
     145* `genericSubstitution()` moved to own visitor **TODO** write
    128146
    129147`BasicType`
    130 * does not inherit from `Type` to allow pointer inlining
    131 * moved `Kind` before qualifiers in constructor to allow for default
    132148* **TODO** move `kind`, `typeNames` into code generator
     149
     150`ReferenceToType`
     151* deleted `get_baseParameters()` from children
     152  * replace with `aggr() ? aggr()->parameters : nullptr`
     153* hoisted `lookup` implementation into parent, made non-virtual
     154  * also changed to return vector rather than filling; change back if any great win for reuse
     155* `baseStruct` etc. renamed to `base`
     156
     157`PointerType`/`ArrayType`
     158* `is_array()` => `isArray()`
     159* `bool isVarLen;` => `enum LengthFlag { FixedLen, VariableLen }; LengthFlag isVarLen;`
     160* `bool isStatic;` => `enum DimensionFlag { DynamicDim, StaticDim }; DimensionFlag isStatic;`
     161
     162`FunctionType`
     163* `bool isVarArgs;` => `enum ArgumentFlag { FixedArgs, VariableArgs }; ArgumentFlag isVarArgs;`
     164
     165`TypeInstType`
     166* `bool isFtype` => `TypeVar::Kind kind`
     167
     168`TypeofType`
     169* `bool is_basetypeof` => `enum Kind { Typeof, Basetypeof } kind;`
     170
     171`TupleType`
     172* removed `value_type` typedef due to likely error
     173  * if readded, should be `const Type *`
     174
     175`AttrType`
     176* did not port due to deprecation of feature
     177  * feature is `type@thing` e.g. `int@MAX`
    133178
    134179[1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes
  • src/InitTweak/InitTweak.cc

    rbe567e9 r69bafd2  
    55#include <memory>                  // for __shared_ptr
    66
     7#include "AST/Type.hpp"
    78#include "Common/PassVisitor.h"
    89#include "Common/SemanticError.h"  // for SemanticError
     
    513514                }
    514515        }
     516        const ast::Type* getPointerBase( const ast::Type* t ) {
     517                if ( const ast::PointerType* p = dynamic_cast< const ast::PointerType* >( t ) ) {
     518                        return p->base;
     519                } else if ( const ast::ArrayType* a = dynamic_cast< const ast::ArrayType* >( t ) ) {
     520                        return a->base;
     521                } else if ( const ast::ReferenceType* r = dynamic_cast< const ast::ReferenceType* >( t ) ) {
     522                        return r->base;
     523                } else return nullptr;
     524        }
    515525
    516526        Type * isPointerType( Type * type ) {
  • src/InitTweak/InitTweak.h

    rbe567e9 r69bafd2  
    2020#include <string>             // for string, allocator
    2121
     22#include "AST/Fwd.hpp"        // for AST nodes
    2223#include "SynTree/SynTree.h"  // for Visitor Nodes
    2324
     
    8384        /// returns the base type of a PointerType or ArrayType, else returns NULL
    8485        Type * getPointerBase( Type * );
     86        const ast::Type* getPointerBase( const ast::Type* );
    8587
    8688        /// returns the argument if it is a PointerType or ArrayType, else returns NULL
Note: See TracChangeset for help on using the changeset viewer.