]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/denum.c
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/enum.c
14 #include "root/root.h"
20 #include "expression.h"
22 #include "declaration.h"
25 Expression
* semantic ( Expression
* e
, Scope
* sc
);
27 /********************************* EnumDeclaration ****************************/
29 EnumDeclaration :: EnumDeclaration ( Loc loc
, Identifier
* id
, Type
* memtype
)
32 //printf("EnumDeclaration() %s\n", toChars());
34 type
= new TypeEnum ( this );
35 this -> memtype
= memtype
;
41 protection
= Prot ( PROTundefined
);
47 Dsymbol
* EnumDeclaration :: syntaxCopy ( Dsymbol
* s
)
50 EnumDeclaration
* ed
= new EnumDeclaration ( loc
, ident
,
51 memtype
? memtype
-> syntaxCopy () : NULL
);
52 return ScopeDsymbol :: syntaxCopy ( ed
);
55 void EnumDeclaration :: setScope ( Scope
* sc
)
57 if ( semanticRun
> PASSinit
)
59 ScopeDsymbol :: setScope ( sc
);
62 void EnumDeclaration :: addMember ( Scope
* sc
, ScopeDsymbol
* sds
)
64 /* Anonymous enum members get added to enclosing scope.
66 ScopeDsymbol
* scopesym
= isAnonymous () ? sds
: this ;
70 ScopeDsymbol :: addMember ( sc
, sds
);
73 symtab
= new DsymbolTable ();
78 for ( size_t i
= 0 ; i
< members
-> dim
; i
++)
80 EnumMember
* em
= (* members
)[ i
]-> isEnumMember ();
82 //printf("add %s to scope %s\n", em->toChars(), scopesym->toChars());
83 em
-> addMember ( sc
, isAnonymous () ? scopesym
: this );
90 void EnumDeclaration :: semantic ( Scope
* sc
)
92 //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
93 //printf("EnumDeclaration::semantic() %p %s\n", this, toChars());
94 if ( semanticRun
>= PASSsemanticdone
)
95 return ; // semantic() already completed
96 if ( semanticRun
== PASSsemantic
)
99 :: error ( loc
, "circular reference to enum base type %s" , memtype
-> toChars ());
101 semanticRun
= PASSsemanticdone
;
104 unsigned dprogress_save
= Module :: dprogress
;
110 scx
= _scope
; // save so we don't make redundant copies
115 type
= type
-> semantic ( loc
, sc
);
117 protection
= sc
-> protection
;
118 if ( sc
-> stc
& STCdeprecated
)
120 userAttribDecl
= sc
-> userAttribDecl
;
122 semanticRun
= PASSsemantic
;
124 if (! members
&& ! memtype
) // enum ident;
126 semanticRun
= PASSsemanticdone
;
131 symtab
= new DsymbolTable ();
133 /* The separate, and distinct, cases are:
135 * 2. enum : memtype { ... }
136 * 3. enum ident { ... }
137 * 4. enum ident : memtype { ... }
138 * 5. enum ident : memtype;
144 memtype
= memtype
-> semantic ( loc
, sc
);
146 /* Check to see if memtype is forward referenced
148 if ( memtype
-> ty
== Tenum
)
150 EnumDeclaration
* sym
= ( EnumDeclaration
*) memtype
-> toDsymbol ( sc
);
151 if (! sym
-> memtype
|| ! sym
-> members
|| ! sym
-> symtab
|| sym
-> _scope
)
153 // memtype is forward referenced, so try again later
154 _scope
= scx
? scx
: sc
-> copy ();
156 _scope
-> _module
-> addDeferredSemantic ( this );
157 Module :: dprogress
= dprogress_save
;
158 //printf("\tdeferring %s\n", toChars());
159 semanticRun
= PASSinit
;
163 if ( memtype
-> ty
== Tvoid
)
165 error ( "base type must not be void" );
166 memtype
= Type :: terror
;
168 if ( memtype
-> ty
== Terror
)
173 for ( size_t i
= 0 ; i
< members
-> dim
; i
++)
175 Dsymbol
* s
= (* members
)[ i
];
176 s
-> errors
= true ; // poison all the members
179 semanticRun
= PASSsemanticdone
;
184 semanticRun
= PASSsemanticdone
;
186 if (! members
) // enum ident : memtype;
189 if ( members
-> dim
== 0 )
191 error ( "enum %s must have at least one member" , toChars ());
203 sce
= sc
-> push ( this );
206 sce
= sce
-> startCTFE ();
207 sce
-> setNoFree (); // needed for getMaxMinValue()
209 /* Each enum member gets the sce scope
211 for ( size_t i
= 0 ; i
< members
-> dim
; i
++)
213 EnumMember
* em
= (* members
)[ i
]-> isEnumMember ();
220 /* addMember() is not called when the EnumDeclaration appears as a function statement,
221 * so we have to do what addMember() does and install the enum members in the right symbol
224 ScopeDsymbol
* scopesym
= NULL
;
227 /* Anonymous enum members get added to enclosing scope.
229 for ( Scope
* sct
= sce
; 1 ; sct
= sct
-> enclosing
)
234 scopesym
= sct
-> scopesym
;
235 if (! sct
-> scopesym
-> symtab
)
236 sct
-> scopesym
-> symtab
= new DsymbolTable ();
243 // Otherwise enum members are in the EnumDeclaration's symbol table
247 for ( size_t i
= 0 ; i
< members
-> dim
; i
++)
249 EnumMember
* em
= (* members
)[ i
]-> isEnumMember ();
253 em
-> addMember ( sc
, scopesym
);
258 for ( size_t i
= 0 ; i
< members
-> dim
; i
++)
260 EnumMember
* em
= (* members
)[ i
]-> isEnumMember ();
262 em
-> semantic ( em
-> _scope
);
264 //printf("defaultval = %lld\n", defaultval);
266 //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
267 //printf("members = %s\n", members->toChars());
270 /******************************
271 * Get the value of the .max/.min property as an Expression
273 * id Id::max or Id::min
276 Expression
* EnumDeclaration :: getMaxMinValue ( Loc loc
, Identifier
* id
)
278 //printf("EnumDeclaration::getMaxValue()\n");
281 Expression
** pval
= ( id
== Id :: max
) ? & maxval
: & minval
;
285 error ( loc
, "recursive definition of .%s property" , id
-> toChars ());
295 if ( semanticRun
== PASSinit
|| ! members
)
299 /* Allow these special enums to not need a member list
301 return memtype
-> getProperty ( loc
, id
, 0 );
304 error ( "is forward referenced looking for .%s" , id
-> toChars ());
307 if (!( memtype
&& memtype
-> isintegral ()))
309 error ( loc
, "has no .%s property because base type %s is not an integral type" ,
311 memtype
? memtype
-> toChars () : "" );
315 for ( size_t i
= 0 ; i
< members
-> dim
; i
++)
317 EnumMember
* em
= (* members
)[ i
]-> isEnumMember ();
323 Expression
* e
= em
-> value ();
331 /* In order to work successfully with UDTs,
332 * build expressions to do the comparisons,
333 * and let the semantic analyzer and constant
334 * folder give us the result.
341 Expression
* ec
= new CmpExp ( id
== Id :: max
? TOKgt
: TOKlt
, em
-> loc
, e
, * pval
);
343 ec
= :: semantic ( ec
, em
-> _scope
);
345 ec
= ec
-> ctfeInterpret ();
352 Expression
* e
= * pval
;
353 if ( e
-> op
!= TOKerror
)
362 * pval
= new ErrorExp ();
367 * Determine if enum is a 'special' one.
371 bool EnumDeclaration :: isSpecial () const
373 return ( ident
== Id :: __c_long
||
374 ident
== Id :: __c_ulong
||
375 ident
== Id :: __c_longlong
||
376 ident
== Id :: __c_ulonglong
||
377 ident
== Id :: __c_long_double
) && memtype
;
380 Expression
* EnumDeclaration :: getDefaultValue ( Loc loc
)
382 //printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
390 if ( semanticRun
== PASSinit
|| ! members
)
394 /* Allow these special enums to not need a member list
396 return memtype
-> defaultInit ( loc
);
399 error ( loc
, "forward reference of %s.init" , toChars ());
403 for ( size_t i
= 0 ; i
< members
-> dim
; i
++)
405 EnumMember
* em
= (* members
)[ i
]-> isEnumMember ();
408 defaultval
= em
-> value ();
414 defaultval
= new ErrorExp ();
418 Type
* EnumDeclaration :: getMemtype ( Loc loc
)
424 /* Enum is forward referenced. We don't need to resolve the whole thing,
428 memtype
= memtype
-> semantic ( loc
, _scope
);
431 if (! isAnonymous () && members
)
432 memtype
= Type :: tint32
;
437 if (! isAnonymous () && members
)
438 memtype
= Type :: tint32
;
441 error ( loc
, "is forward referenced looking for base type" );
448 bool EnumDeclaration :: oneMember ( Dsymbol
** ps
, Identifier
* ident
)
451 return Dsymbol :: oneMembers ( members
, ps
, ident
);
452 return Dsymbol :: oneMember ( ps
, ident
);
455 Type
* EnumDeclaration :: getType ()
460 const char * EnumDeclaration :: kind ()
465 bool EnumDeclaration :: isDeprecated ()
470 Prot
EnumDeclaration :: prot ()
475 Dsymbol
* EnumDeclaration :: search ( const Loc
& loc
, Identifier
* ident
, int flags
)
477 //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
480 // Try one last time to resolve this enum
484 if (! members
|| ! symtab
|| _scope
)
486 error ( "is forward referenced when looking for '%s'" , ident
-> toChars ());
491 Dsymbol
* s
= ScopeDsymbol :: search ( loc
, ident
, flags
);
495 /********************************* EnumMember ****************************/
497 EnumMember :: EnumMember ( Loc loc
, Identifier
* id
, Expression
* value
, Type
* origType
)
498 : VarDeclaration ( loc
, NULL
, id
? id
: Id :: empty
, new ExpInitializer ( loc
, value
))
501 this -> origValue
= value
;
502 this -> origType
= origType
;
505 Expression
*& EnumMember :: value ()
507 return (( ExpInitializer
*) _init
)-> exp
;
510 Dsymbol
* EnumMember :: syntaxCopy ( Dsymbol
* s
)
513 return new EnumMember ( loc
, ident
,
514 value () ? value ()-> syntaxCopy () : NULL
,
515 origType
? origType
-> syntaxCopy () : NULL
);
518 const char * EnumMember :: kind ()
520 return "enum member" ;
523 void EnumMember :: semantic ( Scope
* sc
)
525 //printf("EnumMember::semantic() %s\n", toChars());
526 if ( errors
|| semanticRun
>= PASSsemanticdone
)
528 if ( semanticRun
== PASSsemantic
)
530 error ( "circular reference to enum member" );
533 semanticRun
= PASSsemanticdone
;
541 if ( errors
|| semanticRun
>= PASSsemanticdone
)
549 semanticRun
= PASSsemantic
;
551 protection
= ed
-> isAnonymous () ? ed
-> protection
: Prot ( PROTpublic
);
553 storage_class
= STCmanifest
;
554 userAttribDecl
= ed
-> isAnonymous () ? ed
-> userAttribDecl
: NULL
;
556 // The first enum member is special
557 bool first
= ( this == (* ed
-> members
)[ 0 ]);
561 origType
= origType
-> semantic ( loc
, sc
);
563 assert ( value ()); // "type id;" is not a valid enum member declaration
568 Expression
* e
= value ();
569 assert ( e
-> dyncast () == DYNCAST_EXPRESSION
);
570 e
= :: semantic ( e
, sc
);
571 e
= resolveProperties ( sc
, e
);
572 e
= e
-> ctfeInterpret ();
573 if ( e
-> op
== TOKerror
)
575 if ( first
&& ! ed
-> memtype
&& ! ed
-> isAnonymous ())
577 ed
-> memtype
= e
-> type
;
578 if ( ed
-> memtype
-> ty
== Terror
)
583 if ( ed
-> memtype
-> ty
!= Terror
)
585 /* Bugzilla 11746: All of named enum members should have same type
586 * with the first member. If the following members were referenced
587 * during the first member semantic, their types should be unified.
589 for ( size_t i
= 0 ; i
< ed
-> members
-> dim
; i
++)
591 EnumMember
* em
= (* ed
-> members
)[ i
]-> isEnumMember ();
592 if (! em
|| em
== this || em
-> semanticRun
< PASSsemanticdone
|| em
-> origType
)
595 //printf("[%d] em = %s, em->semanticRun = %d\n", i, toChars(), em->semanticRun);
596 Expression
* ev
= em
-> value ();
597 ev
= ev
-> implicitCastTo ( sc
, ed
-> memtype
);
598 ev
= ev
-> ctfeInterpret ();
599 ev
= ev
-> castTo ( sc
, ed
-> type
);
600 if ( ev
-> op
== TOKerror
)
606 ed
-> memtype
= Type :: terror
;
612 if ( ed
-> memtype
&& ! origType
)
614 e
= e
-> implicitCastTo ( sc
, ed
-> memtype
);
615 e
= e
-> ctfeInterpret ();
617 // save origValue for better json output
620 if (! ed
-> isAnonymous ())
622 e
= e
-> castTo ( sc
, ed
-> type
);
623 e
= e
-> ctfeInterpret ();
628 e
= e
-> implicitCastTo ( sc
, origType
);
629 e
= e
-> ctfeInterpret ();
630 assert ( ed
-> isAnonymous ());
632 // save origValue for better json output
645 if (! ed
-> isAnonymous ())
648 Expression
* e
= new IntegerExp ( loc
, 0 , Type :: tint32
);
649 e
= e
-> implicitCastTo ( sc
, t
);
650 e
= e
-> ctfeInterpret ();
652 // save origValue for better json output
655 if (! ed
-> isAnonymous ())
657 e
= e
-> castTo ( sc
, ed
-> type
);
658 e
= e
-> ctfeInterpret ();
664 /* Find the previous enum member,
665 * and set this to be the previous value + 1
667 EnumMember
* emprev
= NULL
;
668 for ( size_t i
= 0 ; i
< ed
-> members
-> dim
; i
++)
670 EnumMember
* em
= (* ed
-> members
)[ i
]-> isEnumMember ();
679 if ( emprev
-> semanticRun
< PASSsemanticdone
) // if forward reference
680 emprev
-> semantic ( emprev
-> _scope
); // resolve it
684 Expression
* eprev
= emprev
-> value ();
685 Type
* tprev
= eprev
-> type
-> equals ( ed
-> type
) ? ed
-> memtype
: eprev
-> type
;
687 Expression
* emax
= tprev
-> getProperty ( ed
-> loc
, Id :: max
, 0 );
688 emax
= :: semantic ( emax
, sc
);
689 emax
= emax
-> ctfeInterpret ();
691 // Set value to (eprev + 1).
692 // But first check that (eprev != emax)
694 Expression
* e
= new EqualExp ( TOKequal
, loc
, eprev
, emax
);
695 e
= :: semantic ( e
, sc
);
696 e
= e
-> ctfeInterpret ();
699 error ( "initialization with (%s.%s + 1) causes overflow for type '%s'" , emprev
-> ed
-> toChars (), emprev
-> toChars (), ed
-> type
-> toBasetype ()-> toChars ());
703 // Now set e to (eprev + 1)
704 e
= new AddExp ( loc
, eprev
, new IntegerExp ( loc
, 1 , Type :: tint32
));
705 e
= :: semantic ( e
, sc
);
706 e
= e
-> castTo ( sc
, eprev
-> type
);
707 e
= e
-> ctfeInterpret ();
709 // save origValue (without cast) for better json output
710 if ( e
-> op
!= TOKerror
) // avoid duplicate diagnostics
712 assert ( emprev
-> origValue
);
713 origValue
= new AddExp ( loc
, emprev
-> origValue
, new IntegerExp ( loc
, 1 , Type :: tint32
));
714 origValue
= :: semantic ( origValue
, sc
);
715 origValue
= origValue
-> ctfeInterpret ();
718 if ( e
-> op
== TOKerror
)
720 if ( e
-> type
-> isfloating ())
722 // Check that e != eprev (not always true for floats)
723 Expression
* etest
= new EqualExp ( TOKequal
, loc
, e
, eprev
);
724 etest
= :: semantic ( etest
, sc
);
725 etest
= etest
-> ctfeInterpret ();
726 if ( etest
-> toInteger ())
728 error ( "has inexact value, due to loss of precision" );
735 type
= value ()-> type
;
738 semanticRun
= PASSsemanticdone
;
741 Expression
* EnumMember :: getVarExp ( Loc loc
, Scope
* sc
)
745 return new ErrorExp ();
746 Expression
* e
= new VarExp ( loc
, this );
747 return :: semantic ( e
, sc
);