Changes in / [1e97287:89c2f7c9]


Ignore:
Location:
src
Files:
3 added
13 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Decl.hpp

    r1e97287 r89c2f7c9  
    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
     
    166166class TypeDecl final : public NamedTypeDecl {
    167167public:
    168         /// type variable variants. otype is a specialized dtype
    169         enum Kind { Dtype, Ftype, Ttype, NUMBER_OF_KINDS } kind;
     168        TypeVar::Kind kind;
    170169        bool sized;
    171170        ptr<Type> init;
     
    173172        /// Data extracted from a type decl
    174173        struct Data {
    175                 Kind kind;
     174                TypeVar::Kind kind;
    176175                bool isComplete;
    177176
    178                 Data() : kind( (Kind)-1 ), isComplete( false ) {}
     177                Data() : kind( (TypeVar::Kind)-1 ), isComplete( false ) {}
    179178                Data( TypeDecl* d ) : kind( d->kind ), isComplete( d->sized ) {}
    180                 Data( Kind k, bool c ) : kind( k ), isComplete( c ) {}
     179                Data( TypeVar::Kind k, bool c ) : kind( k ), isComplete( c ) {}
    181180                Data( const Data& d1, const Data& d2 )
    182181                : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {}
     
    189188
    190189        TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b,
    191                 Kind k, bool s, Type* i = nullptr )
    192         : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ), init( i ) {}
     190                TypeVar::Kind k, bool s, Type* i = nullptr )
     191        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
     192          init( i ) {}
    193193
    194194        std::string typeString() const override;
    195195        /// Produces a name for generated code
    196196        std::string genTypeString() const;
     197
     198        /// convenience accessor to match Type::isComplete()
     199        bool isComplete() { return sized; }
    197200
    198201        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Expr.hpp

    r1e97287 r89c2f7c9  
    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         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        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

    r1e97287 r89c2f7c9  
    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

    r1e97287 r89c2f7c9  
    116116class TupleType;
    117117class TypeofType;
    118 class AttrType;
    119118class VarArgsType;
    120119class ZeroType;
     
    329328inline void increment( const class TypeofType *, Node::ref_type );
    330329inline void decrement( const class TypeofType *, Node::ref_type );
    331 inline void increment( const class AttrType *, Node::ref_type );
    332 inline void decrement( const class AttrType *, Node::ref_type );
    333330inline void increment( const class VarArgsType *, Node::ref_type );
    334331inline void decrement( const class VarArgsType *, Node::ref_type );
  • src/AST/Init.hpp

    r1e97287 r89c2f7c9  
    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        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        const Init * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Node.hpp

    r1e97287 r89c2f7c9  
    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;
     
    137135        const node_t & operator* () const { return *node; }
    138136        explicit operator bool() const { return node; }
    139         operator const node_t *() const { return node; }
     137        operator const node_t * () const { return node; }
    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

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

    r1e97287 r89c2f7c9  
    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

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

    r1e97287 r89c2f7c9  
    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

    r1e97287 r89c2f7c9  
    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`
     
    105115* Merged `inferParams`/`resnSlots` into union, as suggested by comment in old version
    106116  * does imply get_/set_ API, and some care about moving backward
     117
     118`Init`
     119* `bool maybeConstruct` => `enum ConstructFlag { DoConstruct, MaybeConstruct }`
    107120
    108121`Label`
     
    129142* **TODO** port copy operator
    130143  * Needs to be an almost-shallow clone, where the declarations are cloned only if needed
    131   * **TODO** port DeclReplacer
     144  * **TODO** port `DeclReplacer`
    132145* Still a `std::list` for children, rather than `std::vector`
    133146  * allows more-efficient splicing for purposes of later code generation
    134147
    135148`Type`
     149* `CV::Qualifiers` moved to end of constructor parameter list, defaulted to `{}`
     150  * `ReferenceToType` puts a defaulted list of attributes after qualifiers
    136151* `forall` field split off into `ParameterizedType` subclass
    137152  * any type that needs it can inherit from `ParameterizedType`
     153    * currently `FunctionType`, `ReferenceToType`
    138154* `get_qualifiers()` replaced with accessor `qualifiers()` and mutator `set_qualifiers()`
    139   * `get_CV()` replaced with `is_CV()` variants
     155  * `get_const()` etc. replaced with `is_const()` etc. variants
     156* `referenceDepth()` now returns `unsigned` rather than `int`
    140157* A number of features only supported on aggregates pushed down to `ReferenceToType`:
    141158  * `attributes`: per docs [1] GCC only supports type attributes on aggregates and typedefs
    142159    * suggest adding a `TypeWithAttributes` wrapper type if this proves insufficient
    143   * `getAggr()`
    144   * `genericSubstitution()`
     160  * `getAggr()` => `aggr()`
     161    * also now returns `const AggregateDecl *`
     162* `genericSubstitution()` moved to own visitor **TODO** write
    145163
    146164`BasicType`
    147 * does not inherit from `Type` to allow pointer inlining
    148 * moved `Kind` before qualifiers in constructor to allow for default
    149165* **TODO** move `kind`, `typeNames` into code generator
     166
     167`ReferenceToType`
     168* deleted `get_baseParameters()` from children
     169  * replace with `aggr() ? aggr()->parameters : nullptr`
     170* hoisted `lookup` implementation into parent, made non-virtual
     171  * also changed to return vector rather than filling; change back if any great win for reuse
     172* `baseStruct` etc. renamed to `base`
     173
     174`PointerType`/`ArrayType`
     175* `is_array()` => `isArray()`
     176* `bool isVarLen;` => `enum LengthFlag { FixedLen, VariableLen }; LengthFlag isVarLen;`
     177* `bool isStatic;` => `enum DimensionFlag { DynamicDim, StaticDim }; DimensionFlag isStatic;`
     178
     179`FunctionType`
     180* `bool isVarArgs;` => `enum ArgumentFlag { FixedArgs, VariableArgs }; ArgumentFlag isVarArgs;`
     181
     182`TypeInstType`
     183* `bool isFtype` => `TypeVar::Kind kind`
     184
     185`TypeofType`
     186* `bool is_basetypeof` => `enum Kind { Typeof, Basetypeof } kind;`
     187
     188`TupleType`
     189* removed `value_type` typedef due to likely error
     190  * if readded, should be `const Type *`
     191
     192`AttrType`
     193* did not port due to deprecation of feature
     194  * feature is `type@thing` e.g. `int@MAX`
    150195
    151196[1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes
  • src/InitTweak/InitTweak.cc

    r1e97287 r89c2f7c9  
    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                assert(!"needs to build Type.cpp before inclusion");
     518                // if ( const ast::PointerType* p = dynamic_cast< const ast::PointerType* >( t ) ) {
     519                //      return p->base;
     520                // } else if ( const ast::ArrayType* a = dynamic_cast< const ast::ArrayType* >( t ) ) {
     521                //      return a->base;
     522                // } else if ( const ast::ReferenceType* r = dynamic_cast< const ast::ReferenceType* >( t ) ) {
     523                //      return r->base;
     524                // } else return nullptr;
     525        }
    515526
    516527        Type * isPointerType( Type * type ) {
  • src/InitTweak/InitTweak.h

    r1e97287 r89c2f7c9  
    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.