source: src/AST/Type.hpp @ 1f68d5d

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 1f68d5d was c9f6983, checked in by Fangren Yu <f37yu@…>, 3 years ago

fix non-initialization UB

  • Property mode set to 100644
File size: 17.6 KB
RevLine 
[2bb4a01]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Type.hpp --
8//
9// Author           : Aaron B. Moss
10// Created On       : Thu May 9 10:00:00 2019
[923d25a]11// Last Modified By : Andrew Beach
12// Last Modified On : Thu Jul 23 14:15:00 2020
13// Update Count     : 6
[2bb4a01]14//
15
16#pragma once
17
[9e1d485]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"
[9b4f329]25#include "Decl.hpp"          // for AggregateDecl subclasses
[9e1d485]26#include "Fwd.hpp"
[d76c588]27#include "Node.hpp"          // for Node, ptr, ptr_base
[9e1d485]28#include "Visitor.hpp"
[2bb4a01]29
[f3cc5b6]30// Must be included in *all* AST classes; should be #undef'd at the end of the file
[99da267]31#define MUTATE_FRIEND \
32    template<typename node_t> friend node_t * mutate(const node_t * node); \
33        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
[f3cc5b6]34
[2bb4a01]35namespace ast {
36
[e0e9a0b]37template< typename T > class Pass;
[f53acdf8]38
[2bb4a01]39class Type : public Node {
[9e1d485]40public:
[54e41b3]41        CV::Qualifiers qualifiers;
[c829320]42        std::vector<ptr<Attribute>> attributes;
[87701b6]43
[1ae47de]44        Type( CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[c829320]45        : qualifiers(q), attributes(std::move(as)) {}
[54e41b3]46
47        bool is_const() const { return qualifiers.is_const; }
48        bool is_volatile() const { return qualifiers.is_volatile; }
49        bool is_restrict() const { return qualifiers.is_restrict; }
50        bool is_mutex() const { return qualifiers.is_mutex; }
51        bool is_atomic() const { return qualifiers.is_atomic; }
52
[76ed81f]53        Type * set_const( bool v ) { qualifiers.is_const = v; return this; }
[dafe9e1]54        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
[76ed81f]55        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
56        Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
57        Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
[9e1d485]58
59        /// How many elemental types are represented by this type
60        virtual unsigned size() const { return 1; }
61        /// Is this a void type?
62        virtual bool isVoid() const { return size() == 0; }
63        /// Get the i'th component of this type
[d76c588]64        virtual const Type * getComponent( unsigned i ) const;
[9e1d485]65
66        /// type without outer pointers and arrays
[d76c588]67        const Type * stripDeclarator() const;
[9e1d485]68        /// type without outer references
[d76c588]69        const Type * stripReferences() const;
[9e1d485]70        /// number of reference occuring consecutively on the outermost layer of this type
71        /// (i.e. do not count references nested within other types)
72        virtual unsigned referenceDepth() const { return 0; }
73        /// true iff type is complete type (i.e. compiler knows the size, alignment, and layout)
74        virtual bool isComplete() const { return true; }
75
[69bafd2]76        virtual const Type * accept( Visitor & v ) const override = 0;
[9e1d485]77private:
78        virtual Type * clone() const override = 0;
[f3cc5b6]79        MUTATE_FRIEND
[9e1d485]80};
81
[ee574a2]82/// Clear/reset the qualifiers on this type, cloning only if necessary
[d76c588]83template< enum Node::ref_type ref_t >
[ee574a2]84void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {} ) {
85        if ( p->qualifiers.val != q.val ) p.get_and_mutate()->qualifiers = q;
[d76c588]86}
87
[ee574a2]88/// Add the specified qualifiers to this type, cloning only if necessary
[d76c588]89template< enum Node::ref_type ref_t >
[ee574a2]90void add_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
91        if ( ( p->qualifiers.val & q.val ) != q.val ) p.get_and_mutate()->qualifiers |= q;
92}
93
94/// Remove the specified qualifiers from this type, cloning only if necessary
95template< enum Node::ref_type ref_t >
96void remove_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
97        if ( ( p->qualifiers.val & q.val ) != 0 ) p.get_and_mutate()->qualifiers -= q;
[d76c588]98}
99
[9e1d485]100/// `void`
101class VoidType final : public Type {
102public:
103        VoidType( CV::Qualifiers q = {} ) : Type( q ) {}
[87701b6]104
[9e1d485]105        unsigned size() const override { return 0; }
106        bool isVoid() const override { return true; }
107        bool isComplete() const override { return false; }
108
[69bafd2]109        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]110private:
111        VoidType * clone() const override { return new VoidType{ *this }; }
[f3cc5b6]112        MUTATE_FRIEND
[9e1d485]113};
114
115/// Built-in arithmetic type
116class BasicType final : public Type {
117public:
118        // GENERATED START, DO NOT EDIT
119        // GENERATED BY BasicTypes-gen.cc
120        enum Kind {
121                Bool,
122                Char,
123                SignedChar,
124                UnsignedChar,
125                ShortSignedInt,
126                ShortUnsignedInt,
127                SignedInt,
128                UnsignedInt,
129                LongSignedInt,
130                LongUnsignedInt,
131                LongLongSignedInt,
132                LongLongUnsignedInt,
133                SignedInt128,
134                UnsignedInt128,
135                uFloat16,
136                uFloat16Complex,
137                uFloat32,
138                uFloat32Complex,
139                Float,
140                FloatComplex,
141                uFloat32x,
142                uFloat32xComplex,
143                uFloat64,
144                uFloat64Complex,
145                Double,
146                DoubleComplex,
147                uFloat64x,
148                uFloat64xComplex,
149                uuFloat80,
150                uFloat128,
151                uFloat128Complex,
152                uuFloat128,
153                LongDouble,
154                LongDoubleComplex,
155                uFloat128x,
156                uFloat128xComplex,
157                NUMBER_OF_BASIC_TYPES
158        } kind;
159        // GENERATED END
160
161        /// xxx -- MAX_INTEGER_TYPE should probably be in BasicTypes-gen.cc, rather than hardcoded here
162        enum { MAX_INTEGER_TYPE = UnsignedInt128 };
163
164        /// string names of basic types; generated to match with Kind
165        static const char *typeNames[];
166
[f53acdf8]167        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[0f6a7752]168        : Type(q, std::move(as)), kind(k) {}
[9e1d485]169
170        /// Check if this type represents an integer type
[3648d98]171        bool isInteger() const { return (unsigned)kind <= (unsigned)MAX_INTEGER_TYPE; }
[9e1d485]172
[69bafd2]173        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]174private:
175        BasicType * clone() const override { return new BasicType{ *this }; }
[f3cc5b6]176        MUTATE_FRIEND
[9e1d485]177};
178
179/// Pointer/array variable length?
180enum LengthFlag { FixedLen, VariableLen };
181
182/// Pointer/array static dimension?
183enum DimensionFlag { DynamicDim, StaticDim };
184
185/// Pointer type `T*`
186class PointerType final : public Type {
187public:
188        ptr<Type> base;
189
190        // In C99, pointer types can be qualified in many ways, e.g. `int a[ static 3 ]`
191        ptr<Expr> dimension;
192        LengthFlag isVarLen = FixedLen;
193        DimensionFlag isStatic = DynamicDim;
194
195        PointerType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b), dimension() {}
[87701b6]196        PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
[9e1d485]197                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
198
199        // true if this pointer is actually an array
200        bool isArray() const { return isVarLen || isStatic || dimension; }
201
202        bool isComplete() const override { return ! isVarLen; }
203
[69bafd2]204        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]205private:
206        PointerType * clone() const override { return new PointerType{ *this }; }
[f3cc5b6]207        MUTATE_FRIEND
[9e1d485]208};
209
210/// Array type `T[]`
211class ArrayType final : public Type {
212public:
213        ptr<Type> base;
214        ptr<Expr> dimension;
215        LengthFlag isVarLen;
216        DimensionFlag isStatic;
[2bb4a01]217
[87701b6]218        ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
[9e1d485]219                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
220
221        // array types are complete if they have a dimension expression or are
222        // VLAs ('*' in parameter declaration), and incomplete otherwise.
223        // See 6.7.6.2
224        bool isComplete() const override { return dimension || isVarLen; }
225
[69bafd2]226        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]227private:
228        ArrayType * clone() const override { return new ArrayType{ *this }; }
[f3cc5b6]229        MUTATE_FRIEND
[9e1d485]230};
231
232/// Reference type `T&`
233class ReferenceType final : public Type {
234public:
235        ptr<Type> base;
236
237        ReferenceType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
238
239        unsigned referenceDepth() const override { return base->referenceDepth() + 1; }
240
241        // Since reference types act like value types, their size is the size of the base.
242        // This makes it simple to cast the empty tuple to a reference type, since casts that increase
243        // the number of values are disallowed.
244        unsigned size() const override { return base->size(); }
245
[69bafd2]246        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]247private:
248        ReferenceType * clone() const override { return new ReferenceType{ *this }; }
[f3cc5b6]249        MUTATE_FRIEND
[2bb4a01]250};
251
[9e1d485]252/// Qualified type `P.C`
253class QualifiedType final : public Type {
254public:
255        ptr<Type> parent;
256        ptr<Type> child;
257
[87701b6]258        QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} )
[9e1d485]259        : Type(q), parent(p), child(c) {}
260
[69bafd2]261        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]262private:
263        QualifiedType * clone() const override { return new QualifiedType{ *this }; }
[f3cc5b6]264        MUTATE_FRIEND
[9e1d485]265};
266
267/// Function variable arguments flag
268enum ArgumentFlag { FixedArgs, VariableArgs };
269
270/// Type of a function `[R1, R2](*)(P1, P2, P3)`
[361bf01]271class FunctionType final : public Type {
[9e1d485]272public:
[3e5dd913]273        using ForallList = std::vector<ptr<TypeInstType>>;
274        using AssertionList = std::vector<ptr<VariableExpr>>;
[361bf01]275        ForallList forall;
[3e5dd913]276        AssertionList assertions;
[361bf01]277
[954c954]278        std::vector<ptr<Type>> returns;
279        std::vector<ptr<Type>> params;
[9e1d485]280
[87701b6]281        /// Does the function accept a variable number of arguments following the arguments specified
[9e1d485]282        /// in the parameters list.
283        /// This could be because of
284        /// - an ellipsis in a prototype declaration
285        /// - an unprototyped declaration
286        ArgumentFlag isVarArgs;
287
288        FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
[361bf01]289        : Type(q), returns(), params(), isVarArgs(va) {}
[9e1d485]290
[3e5dd913]291        FunctionType( const FunctionType & o ) = default;
[e0e9a0b]292
[9e1d485]293        /// true if either the parameters or return values contain a tttype
294        bool isTtype() const;
295        /// true if function parameters are unconstrained by prototype
[54e41b3]296        bool isUnprototyped() const { return isVarArgs && params.size() == 0; }
[9e1d485]297
[69bafd2]298        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]299private:
300        FunctionType * clone() const override { return new FunctionType{ *this }; }
[f3cc5b6]301        MUTATE_FRIEND
[9e1d485]302};
303
304/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
[361bf01]305class BaseInstType : public Type {
[9e1d485]306public:
[54e41b3]307        std::vector<ptr<Expr>> params;
[9e1d485]308        std::string name;
309        bool hoistType = false;
310
[98e8b3b]311        BaseInstType(
[e0e9a0b]312                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[361bf01]313        : Type(q, std::move(as)), params(), name(n) {}
[9e1d485]314
[3aec25f]315        BaseInstType(
316                const std::string& n, std::vector<ptr<Expr>> && params,
317                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[361bf01]318        : Type(q, std::move(as)), params(std::move(params)), name(n) {}
[3aec25f]319
[361bf01]320        BaseInstType( const BaseInstType & o ) = default;
[e0e9a0b]321
[9e1d485]322        /// Gets aggregate declaration this type refers to
323        virtual const AggregateDecl * aggr() const = 0;
324        /// Looks up member declarations with given name
325        std::vector<readonly<Decl>> lookup( const std::string & name ) const;
326
327private:
[98e8b3b]328        virtual BaseInstType * clone() const override = 0;
[f3cc5b6]329        MUTATE_FRIEND
[9e1d485]330};
331
[923d25a]332// Common implementation for the SUE instance types. Not to be used directly.
333template<typename decl_t>
[98e8b3b]334class SueInstType final : public BaseInstType {
[9e1d485]335public:
[923d25a]336        using base_type = decl_t;
337        readonly<decl_t> base;
[9e1d485]338
[923d25a]339        SueInstType(
[e0e9a0b]340                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[98e8b3b]341        : BaseInstType( n, q, std::move(as) ), base() {}
[e0e9a0b]342
[923d25a]343        SueInstType(
[3aec25f]344                const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
345
346        SueInstType(
347                const base_type * b, std::vector<ptr<Expr>> && params,
348                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
[87701b6]349
[9e1d485]350        bool isComplete() const override;
351
[923d25a]352        const decl_t * aggr() const override { return base; }
[9e1d485]353
[69bafd2]354        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]355private:
[923d25a]356        SueInstType<decl_t> * clone() const override { return new SueInstType<decl_t>{ *this }; }
[f3cc5b6]357        MUTATE_FRIEND
[9e1d485]358};
359
[923d25a]360/// An instance of a struct type.
361using StructInstType = SueInstType<StructDecl>;
[9e1d485]362
[923d25a]363/// An instance of a union type.
364using UnionInstType = SueInstType<UnionDecl>;
[9e1d485]365
[923d25a]366/// An instance of an enum type.
367using EnumInstType = SueInstType<EnumDecl>;
[9e1d485]368
[923d25a]369/// An instance of a trait type.
[98e8b3b]370class TraitInstType final : public BaseInstType {
[9e1d485]371public:
372        readonly<TraitDecl> base;
373
[f53acdf8]374        TraitInstType(
[e0e9a0b]375                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[98e8b3b]376        : BaseInstType( n, q, std::move(as) ), base() {}
[f53acdf8]377
378        TraitInstType(
[e0e9a0b]379                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
[87701b6]380
[9e1d485]381        // not meaningful for TraitInstType
382        bool isComplete() const override { assert(false); }
383
384        const TraitDecl * aggr() const override { return base; }
385
[69bafd2]386        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]387private:
388        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
[f3cc5b6]389        MUTATE_FRIEND
[9e1d485]390};
391
392/// instance of named type alias (typedef or variable)
[98e8b3b]393class TypeInstType final : public BaseInstType {
[9e1d485]394public:
395        readonly<TypeDecl> base;
[3e5dd913]396        // previously from renameTyVars; now directly use integer fields instead of synthesized strings
397        // a nonzero value of formal_usage indicates a formal type (only used in function type)
398        // a zero value of formal_usage indicates an actual type (referenced inside body of parametric structs and functions)
[07de76b]399        TypeDecl::Kind kind;
[c9f6983]400        int formal_usage = 0;
401        int expr_id = 0;
[3e5dd913]402
403        // compact representation used for map lookups.
404        struct TypeEnvKey { 
405                const TypeDecl * base;
406                int formal_usage;
407                int expr_id;
408
409                TypeEnvKey() = default;
410                TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0): base(base), formal_usage(formal_usage), expr_id(expr_id) {}
411                TypeEnvKey(const TypeInstType & inst): base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
412                std::string typeString() const { return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + base->name; }
413                bool operator==(const TypeEnvKey & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
414
415        };
416
417        bool operator==(const TypeInstType & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
[9e1d485]418
[f53acdf8]419        TypeInstType(
[e0e9a0b]420                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
[9e1d485]421                std::vector<ptr<Attribute>> && as = {} )
[98e8b3b]422        : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
[07de76b]423        TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
[9e1d485]424                std::vector<ptr<Attribute>> && as = {} )
[98e8b3b]425        : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
[9e1d485]426
[361bf01]427        TypeInstType( const TypeInstType & o ) = default;
[e0e9a0b]428
[3e5dd913]429        TypeInstType( const TypeEnvKey & key )
430        : BaseInstType(key.base->name), base(key.base), kind(key.base->kind), formal_usage(key.formal_usage), expr_id(key.expr_id) {}
431
[9e1d485]432        /// sets `base`, updating `kind` correctly
433        void set_base( const TypeDecl * );
434
435        bool isComplete() const override;
436
437        // not meaningful for TypeInstType
438        const AggregateDecl * aggr() const override { assert(false); }
439
[69bafd2]440        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[3e5dd913]441
442        std::string typeString() const { 
443                if (formal_usage > 0) return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + name; 
444                else return name;
445        }
[9e1d485]446private:
447        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
[f3cc5b6]448        MUTATE_FRIEND
[9e1d485]449};
450
451/// tuple type e.g. `[int, char]`
452class TupleType final : public Type {
453public:
454        std::vector<ptr<Type>> types;
455        std::vector<ptr<Decl>> members;
456
457        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
458
459        // collection simulation
460        using iterator = std::vector<ptr<Type>>::const_iterator;
461        iterator begin() const { return types.begin(); }
462        iterator end() const { return types.end(); }
[87701b6]463
[9e1d485]464        unsigned size() const override { return types.size(); }
465
[d76c588]466        const Type * getComponent( unsigned i ) const override {
[87701b6]467                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
[9e1d485]468                        i, size() );
469                return *(begin()+i);
470        }
471
[69bafd2]472        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]473private:
474        TupleType * clone() const override { return new TupleType{ *this }; }
[f3cc5b6]475        MUTATE_FRIEND
[9e1d485]476};
477
478/// Type of unresolved `typeof()` expression
479class TypeofType : public Type {
480public:
481        ptr<Expr> expr;
482        enum Kind { Typeof, Basetypeof } kind;
483
[87701b6]484        TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
[9e1d485]485        : Type(q), expr(e), kind(k) {}
486
[69bafd2]487        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]488private:
489        TypeofType * clone() const override { return new TypeofType{ *this }; }
[f3cc5b6]490        MUTATE_FRIEND
[9e1d485]491};
492
493/// GCC built-in varargs type
494class VarArgsType final : public Type {
495public:
496        VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
[87701b6]497
[69bafd2]498        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]499private:
500        VarArgsType * clone() const override { return new VarArgsType{ *this }; }
[f3cc5b6]501        MUTATE_FRIEND
[9e1d485]502};
503
504/// Type of zero constant `0`
505class ZeroType final : public Type {
506public:
507        ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
[87701b6]508
[69bafd2]509        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]510private:
[f3cc5b6]511        ZeroType * clone() const override { return new ZeroType{ *this }; }
512        MUTATE_FRIEND
[9e1d485]513};
514
515/// Type of one constant `1`
516class OneType final : public Type {
517public:
518        OneType( CV::Qualifiers q = {} ) : Type( q ) {}
519
[69bafd2]520        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]521private:
522        OneType * clone() const override { return new OneType{ *this }; }
[f3cc5b6]523        MUTATE_FRIEND
[9e1d485]524};
525
526/// Parent type for scope-qualified types at global scope
527class GlobalScopeType final : public Type {
528public:
[746ae82]529        GlobalScopeType() : Type() {}
[9e1d485]530
[69bafd2]531        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]532private:
533        GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
[f3cc5b6]534        MUTATE_FRIEND
[9e1d485]535};
[e0115286]536
[e5c3811]537bool isUnboundType(const Type * type);
538
[2bb4a01]539}
540
[3e5dd913]541namespace std {
542        template<>
543        struct hash<typename ast::TypeInstType::TypeEnvKey> {
544                size_t operator() (const ast::TypeInstType::TypeEnvKey & x) const {
545                        const size_t p = 1000007;
546                        size_t res = reinterpret_cast<size_t>(x.base);
547                        res = p * res + x.formal_usage;
548                        res = p * res + x.expr_id;
549                        return res;
550                } 
551        };
552}
553
[f3cc5b6]554#undef MUTATE_FRIEND
555
[2bb4a01]556// Local Variables: //
557// tab-width: 4 //
558// mode: c++ //
559// compile-command: "make install" //
560// End: //
Note: See TracBrowser for help on using the repository browser.