1 /*
  2  * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package com.sun.tools.javac.code;
 27 
 28 import java.lang.annotation.Retention;
 29 import java.lang.annotation.RetentionPolicy;
 30 import java.util.Collections;
 31 import java.util.EnumSet;
 32 import java.util.Map;
 33 import java.util.Set;
 34 import java.util.concurrent.ConcurrentHashMap;
 35 import java.util.stream.Collectors;
 36 
 37 import javax.lang.model.element.Modifier;
 38 
 39 import com.sun.tools.javac.util.Assert;
 40 
 41 /** Access flags and other modifiers for Java classes and members.
 42  *
 43  *  <p><b>This is NOT part of any supported API.
 44  *  If you write code that depends on this, you do so at your own risk.
 45  *  This code and its internal interfaces are subject to change or
 46  *  deletion without notice.</b>
 47  */
 48 public class Flags {
 49 
 50     private Flags() {} // uninstantiable
 51 
 52     public static String toString(long flags) {
 53         StringBuilder buf = new StringBuilder();
 54         String sep = "";
 55         for (FlagsEnum flag : asFlagSet(flags)) {
 56             buf.append(sep);
 57             buf.append(flag);
 58             sep = " ";
 59         }
 60         return buf.toString();
 61     }
 62 
 63     public static EnumSet<FlagsEnum> asFlagSet(long flags) {
 64         EnumSet<FlagsEnum> flagSet = EnumSet.noneOf(FlagsEnum.class);
 65         for (FlagsEnum flag : FlagsEnum.values()) {
 66             if ((flags & flag.value()) != 0) {
 67                 flagSet.add(flag);
 68                 flags &= ~flag.value();
 69             }
 70         }
 71         Assert.check(flags == 0);
 72         return flagSet;
 73     }
 74 
 75     /* Standard Java flags.
 76      */
 77     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.VARIABLE})
 78     public static final int PUBLIC       = 1;
 79     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.VARIABLE})
 80     public static final int PRIVATE      = 1<<1;
 81     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.VARIABLE})
 82     public static final int PROTECTED    = 1<<2;
 83     @Use({FlagTarget.BLOCK, FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.VARIABLE})
 84     public static final int STATIC       = 1<<3;
 85     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.VARIABLE})
 86     public static final int FINAL        = 1<<4;
 87     @Use({FlagTarget.METHOD})
 88     public static final int SYNCHRONIZED = 1<<5;
 89     @Use({FlagTarget.VARIABLE})
 90     public static final int VOLATILE     = 1<<6;
 91     @Use({FlagTarget.VARIABLE})
 92     public static final int TRANSIENT    = 1<<7;
 93     @Use({FlagTarget.METHOD})
 94     public static final int NATIVE       = 1<<8;
 95     @Use({FlagTarget.CLASS})
 96     public static final int INTERFACE    = 1<<9;
 97     @Use({FlagTarget.CLASS, FlagTarget.METHOD})
 98     public static final int ABSTRACT     = 1<<10;
 99     @Use({FlagTarget.CLASS, FlagTarget.METHOD})
100     public static final int STRICTFP     = 1<<11;
101 
102     /* Flag that marks a symbol synthetic, added in classfile v49.0. */
103     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.VARIABLE})
104     public static final int SYNTHETIC    = 1<<12;
105 
106     /** Flag that marks attribute interfaces, added in classfile v49.0. */
107     @Use({FlagTarget.CLASS})
108     public static final int ANNOTATION   = 1<<13;
109 
110     /** An enumeration type or an enumeration constant, added in
111      *  classfile v49.0. */
112     @Use({FlagTarget.CLASS, FlagTarget.VARIABLE})
113     public static final int ENUM         = 1<<14;
114 
115     /** Added in SE8, represents constructs implicitly declared in source. */
116     @Use({FlagTarget.MODULE, FlagTarget.VARIABLE})
117     public static final int MANDATED     = 1<<15;
118 
119     @NotFlag
120     public static final int StandardFlags = 0x0fff;
121 
122     // Because the following access flags are overloaded with other
123     // bit positions, we translate them when reading and writing class
124     // files into unique bits positions: ACC_SYNTHETIC <-> SYNTHETIC,
125     // for example.
126     @Use({FlagTarget.CLASS})
127     @NoToStringValue
128     public static final int ACC_IDENTITY = 1<<5;
129     @Use({FlagTarget.METHOD})
130     @NoToStringValue
131     public static final int ACC_BRIDGE   = 1<<6;
132     @Use({FlagTarget.METHOD})
133     @NoToStringValue
134     public static final int ACC_VARARGS  = 1<<7;
135     @Use({FlagTarget.VARIABLE})
136     @NoToStringValue
137     public static final int ACC_STRICT   = 1<<11;
138     @Use({FlagTarget.CLASS})
139     @NoToStringValue
140     public static final int ACC_MODULE   = 1<<15;
141 
142     /* ***************************************
143      * Internal compiler flags (no bits in the lower 16).
144      *****************************************/
145 
146     /** Flag is set if symbol is deprecated.  See also DEPRECATED_REMOVAL.
147      */
148     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.MODULE, FlagTarget.PACKAGE, FlagTarget.TYPE_VAR, FlagTarget.VARIABLE})
149     public static final int DEPRECATED   = 1<<17;
150 
151     /** Flag is set for a variable symbol if the variable's definition
152      *  has an initializer part.
153      */
154     @Use({FlagTarget.VARIABLE})
155     public static final int HASINIT          = 1<<18;
156 
157     /** Flag is set for a class or interface whose instances have identity
158      * i.e. any concrete class not declared with the modifier `value'
159      * (a) abstract class not declared `value'
160      * (b) older class files with ACC_SUPER bit set
161      */
162     @Use({FlagTarget.CLASS})
163     public static final int IDENTITY_TYPE            = 1<<18;
164 
165     /** Class is an implicitly declared top level class.
166      */
167     @Use({FlagTarget.CLASS})
168     public static final int IMPLICIT_CLASS    = 1<<19;
169 
170     /** Variable with implicit/inferred type.
171      */
172     @Use(FlagTarget.VARIABLE)
173     public static final int VAR_VARIABLE     = 1<<21;
174 
175     /** Flag is set for compiler-generated anonymous method symbols
176      *  that `own' an initializer block.
177      */
178     @Use({FlagTarget.METHOD})
179     public static final int BLOCK            = 1<<21;
180 
181     /** Marks a type as a value class */
182     @Use({FlagTarget.CLASS})
183     public static final int VALUE_CLASS      = 1<<20;
184 
185     /** A parameter of a lambda function.
186      */
187     @Use(FlagTarget.VARIABLE)
188     public static final int LAMBDA_PARAMETER     = 1<<23;
189 
190     /** Flag is set for ClassSymbols that are being compiled from source.
191      */
192     @Use({FlagTarget.CLASS})
193     public static final int FROM_SOURCE      = 1<<21;
194 
195     /** Flag is set for nested classes that do not access instance members
196      *  or `this' of an outer class and therefore don't need to be passed
197      *  a this$n reference.  This value is currently set only for anonymous
198      *  classes in superclass constructor calls.
199      *  todo: use this value for optimizing away this$n parameters in
200      *  other cases.
201      */
202     @Use({FlagTarget.CLASS, FlagTarget.VARIABLE})
203     public static final int NOOUTERTHIS  = 1<<22;
204 
205     /** Flag is set for package symbols if a package has a member or
206      *  directory and therefore exists.
207      */
208     @Use({FlagTarget.CLASS, FlagTarget.PACKAGE})
209     public static final int EXISTS           = 1<<23;
210 
211     /** Flag is set for compiler-generated compound classes
212      *  representing multiple variable bounds
213      */
214     @Use({FlagTarget.CLASS})
215     public static final int COMPOUND     = 1<<24;
216 
217     /** Flag is set for class symbols if a class file was found for this class.
218      */
219     @Use({FlagTarget.CLASS})
220     public static final int CLASS_SEEN   = 1<<25;
221 
222     /** Flag is set for class symbols if a source file was found for this
223      *  class.
224      */
225     @Use({FlagTarget.CLASS})
226     public static final int SOURCE_SEEN  = 1<<26;
227 
228     /* State flags (are reset during compilation).
229      */
230 
231     /** Flag for class symbols is set and later re-set as a lock in
232      *  Enter to detect cycles in the superclass/superinterface
233      *  relations.  Similarly for constructor call cycle detection in
234      *  Attr.
235      */
236     @Use({FlagTarget.CLASS, FlagTarget.METHOD})
237     public static final int LOCKED           = 1<<27;
238 
239     /** Flag for class symbols is set and later re-set to indicate that a class
240      *  has been entered but has not yet been attributed.
241      */
242     @Use({FlagTarget.CLASS})
243     public static final int UNATTRIBUTED = 1<<28;
244 
245     /** Flag for synthesized default constructors of anonymous classes.
246      */
247     @Use({FlagTarget.METHOD})
248     public static final int ANONCONSTR   = 1<<29;
249 
250     /**
251      * Flag to indicate the superclasses of this ClassSymbol has been attributed.
252      */
253     @Use({FlagTarget.CLASS})
254     public static final int SUPER_OWNER_ATTRIBUTED = 1<<29;
255 
256     /** Flag for class symbols to indicate it has been checked and found
257      *  acyclic.
258      */
259     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.TYPE_VAR})
260     public static final int ACYCLIC          = 1<<30;
261 
262     /** Flag that marks bridge methods.
263      */
264     @Use({FlagTarget.METHOD})
265     public static final long BRIDGE          = 1L<<31;
266 
267     /** Flag that marks formal parameters.
268      */
269     @Use({FlagTarget.VARIABLE})
270     public static final long PARAMETER   = 1L<<33;
271 
272     /** Flag that marks varargs methods.
273      */
274     @Use({FlagTarget.METHOD, FlagTarget.VARIABLE})
275     public static final long VARARGS   = 1L<<34;
276 
277     /** Flag for annotation type symbols to indicate it has been
278      *  checked and found acyclic.
279      */
280     @Use({FlagTarget.CLASS})
281     public static final long ACYCLIC_ANN      = 1L<<35;
282 
283     /** Flag that marks a generated default constructor.
284      */
285     @Use({FlagTarget.METHOD})
286     public static final long GENERATEDCONSTR   = 1L<<36;
287 
288     /** Flag that marks a hypothetical method that need not really be
289      *  generated in the binary, but is present in the symbol table to
290      *  simplify checking for erasure clashes - also used for 292 poly sig methods.
291      */
292     @Use({FlagTarget.METHOD})
293     public static final long HYPOTHETICAL   = 1L<<37;
294 
295     /**
296      * Flag that marks an internal proprietary class.
297      */
298     @Use({FlagTarget.CLASS})
299     public static final long PROPRIETARY = 1L<<38;
300 
301     /**
302      * Flag that marks a multi-catch parameter.
303      */
304     @Use({FlagTarget.VARIABLE})
305     public static final long UNION = 1L<<39;
306 
307     /**
308      * Flags an erroneous TypeSymbol as viable for recovery.
309      * TypeSymbols only.
310      */
311     @Use({FlagTarget.CLASS, FlagTarget.TYPE_VAR})
312     public static final long RECOVERABLE = 1L<<40;
313 
314     /**
315      * Flag that marks an 'effectively final' local variable.
316      */
317     @Use({FlagTarget.VARIABLE})
318     public static final long EFFECTIVELY_FINAL = 1L<<41;
319 
320     /**
321      * Flag that marks non-override equivalent methods with the same signature,
322      * or a conflicting match binding (BindingSymbol).
323      */
324     @Use({FlagTarget.METHOD, FlagTarget.VARIABLE})
325     public static final long CLASH = 1L<<42;
326 
327     /**
328      * Flag that marks either a default method or an interface containing default methods.
329      */
330     @Use({FlagTarget.CLASS, FlagTarget.METHOD})
331     public static final long DEFAULT = 1L<<43; // part of ExtendedStandardFlags, cannot be reused
332 
333     /**
334      * Flag that marks class as auxiliary, ie a non-public class following
335      * the public class in a source file, that could block implicit compilation.
336      */
337     @Use({FlagTarget.CLASS})
338     public static final long AUXILIARY = 1L<<44;
339 
340     /**
341      * Flag that marks that a symbol is not available in the current profile
342      */
343     @Use({FlagTarget.CLASS})
344     public static final long NOT_IN_PROFILE = 1L<<45;
345 
346     /**
347      * Flag that indicates that an override error has been detected by Check.
348      */
349     @Use({FlagTarget.METHOD})
350     public static final long BAD_OVERRIDE = 1L<<45;
351 
352     /**
353      * Flag that indicates a signature polymorphic method (292).
354      */
355     @Use({FlagTarget.METHOD})
356     public static final long SIGNATURE_POLYMORPHIC = 1L<<46;
357 
358     /**
359      * Flag that indicates that an inference variable is used in a 'throws' clause.
360      */
361     @Use({FlagTarget.TYPE_VAR})
362     public static final long THROWS = 1L<<47;
363 
364     /**
365      * Flag to indicate sealed class/interface declaration.
366      */
367     @Use({FlagTarget.CLASS})
368     public static final long SEALED = 1L<<48; // part of ExtendedStandardFlags, cannot be reused
369 
370     /**
371      * Flag that marks a synthetic method body for a lambda expression
372      */
373     @Use({FlagTarget.METHOD})
374     public static final long LAMBDA_METHOD = 1L<<49;
375 
376     /**
377      * Flag that marks a synthetic local capture field in a local/anon class
378      */
379     @Use({FlagTarget.VARIABLE})
380     public static final long LOCAL_CAPTURE_FIELD = 1L<<49;
381 
382     /**
383      * Flag to control recursion in TransTypes
384      */
385     @Use({FlagTarget.CLASS})
386     public static final long TYPE_TRANSLATED = 1L<<50;
387 
388     /**
389      * Flag to indicate class symbol is for module-info
390      */
391     @Use({FlagTarget.CLASS})
392     public static final long MODULE = 1L<<51;
393 
394     /**
395      * Flag to indicate the given ModuleSymbol is an automatic module.
396      */
397     @Use({FlagTarget.MODULE})
398     public static final long AUTOMATIC_MODULE = 1L<<52;
399 
400     /**
401      * Flag to indicate the given PackageSymbol contains any non-.java and non-.class resources.
402      */
403     @Use({FlagTarget.PACKAGE})
404     public static final long HAS_RESOURCE = 1L<<52;
405 
406     /**
407      * Flag to indicate the given ParamSymbol has a user-friendly name filled.
408      */
409     @Use({FlagTarget.VARIABLE}) //ParamSymbols only
410     public static final long NAME_FILLED = 1L<<52;
411 
412     /**
413      * Flag to indicate the given ModuleSymbol is a system module.
414      */
415     @Use({FlagTarget.MODULE})
416     public static final long SYSTEM_MODULE = 1L<<53;
417 
418     /**
419      * Flag to indicate the given ClassSymbol is a value based.
420      */
421     @Use({FlagTarget.CLASS})
422     public static final long VALUE_BASED = 1L<<53;
423 
424     /**
425      * Flag to indicate the given ClassSymbol is a value based.
426      */
427     @Use({FlagTarget.CLASS})
428     public static final long MIGRATED_VALUE_CLASS = 1L<<57; //ClassSymbols only
429 
430     /**
431      * Flag to indicate the given symbol has a @Deprecated annotation.
432      */
433     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.MODULE, FlagTarget.PACKAGE, FlagTarget.TYPE_VAR, FlagTarget.VARIABLE})
434     public static final long DEPRECATED_ANNOTATION = 1L<<54;
435 
436     /**
437      * Flag to indicate the given symbol has been deprecated and marked for removal.
438      */
439     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.MODULE, FlagTarget.PACKAGE, FlagTarget.TYPE_VAR, FlagTarget.VARIABLE})
440     public static final long DEPRECATED_REMOVAL = 1L<<55;
441 
442     /**
443      * Flag to indicate the API element in question is for a preview API.
444      */
445     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.MODULE, FlagTarget.PACKAGE, FlagTarget.TYPE_VAR, FlagTarget.VARIABLE})
446     public static final long PREVIEW_API = 1L<<56; //any Symbol kind
447 
448     /**
449      * Flag for synthesized default constructors of anonymous classes that have an enclosing expression.
450      */
451     @Use({FlagTarget.METHOD})
452     public static final long ANONCONSTR_BASED = 1L<<57;
453 
454     /**
455      * Flag that marks finalize block as body-only, should not be copied into catch clauses.
456      * Used to implement try-with-resources.
457      */
458     @Use({FlagTarget.BLOCK})
459     public static final long BODY_ONLY_FINALIZE = 1L<<17;
460 
461     /**
462      * Flag to indicate the API element in question is for a preview API.
463      */
464     @Use({FlagTarget.CLASS, FlagTarget.METHOD, FlagTarget.MODULE, FlagTarget.PACKAGE, FlagTarget.TYPE_VAR, FlagTarget.VARIABLE})
465     public static final long PREVIEW_REFLECTIVE = 1L<<58; //any Symbol kind
466 
467     /**
468      * Flag to indicate the given variable is a match binding variable.
469      */
470     @Use({FlagTarget.VARIABLE})
471     public static final long MATCH_BINDING = 1L<<59;
472 
473     /**
474      * A flag to indicate a match binding variable whose scope extends after the current statement.
475      */
476     @Use({FlagTarget.VARIABLE})
477     public static final long MATCH_BINDING_TO_OUTER = 1L<<60;
478 
479     /**
480      * Flag to indicate that a class is a record. The flag is also used to mark fields that are
481      * part of the state vector of a record and to mark the canonical constructor
482      */
483     @Use({FlagTarget.CLASS, FlagTarget.VARIABLE, FlagTarget.METHOD})
484     public static final long RECORD = 1L<<61;
485 
486     /**
487      * Flag to mark a record constructor as a compact one
488      */
489     @Use({FlagTarget.METHOD})
490     public static final long COMPACT_RECORD_CONSTRUCTOR = 1L<<51;
491 
492     /**
493      * Flag to mark a record field that was not initialized in the compact constructor
494      */
495     @Use({FlagTarget.VARIABLE})
496     public static final long UNINITIALIZED_FIELD= 1L<<51;
497 
498     /** Flag is set for compiler-generated record members, it could be applied to
499      *  accessors and fields
500      */
501     @Use({FlagTarget.METHOD, FlagTarget.VARIABLE})
502     public static final int GENERATED_MEMBER = 1<<24;
503 
504     /**
505      * Flag to indicate restricted method declaration.
506      */
507     @Use({FlagTarget.METHOD})
508     public static final long RESTRICTED = 1L<<62;
509 
510     /**
511      * Flag to indicate parameters that require identity.
512      */
513     @Use({FlagTarget.VARIABLE}) //ParamSymbols only
514     public static final long REQUIRES_IDENTITY = 1L<<62;
515 
516     /**
517      * Flag to indicate type annotations have been queued for field initializers.
518      */
519     @Use({FlagTarget.VARIABLE})
520     public static final long FIELD_INIT_TYPE_ANNOTATIONS_QUEUED = 1L<<53;
521 
522     /**
523      * Flag to indicate that the class/interface was declared with the non-sealed modifier.
524      */
525     @Use({FlagTarget.CLASS})
526     @CustomToStringValue("non-sealed")
527     public static final long NON_SEALED = 1L<<63;  // part of ExtendedStandardFlags, cannot be reused
528 
529     /**
530      * Flag to indicate that a field is strict
531      */
532     @Use({FlagTarget.VARIABLE})
533     public static final long STRICT = 1L<<19; // VarSymbols
534 
535     /**
536      * Describe modifier flags as they might appear in source code, i.e.,
537      * separated by spaces and in the order suggested by JLS 8.1.1.
538      */
539     public static String toSource(long flags) {
540         return asModifierSet(flags).stream()
541           .map(Modifier::toString)
542           .collect(Collectors.joining(" "));
543     }
544 
545     /** Modifier masks.
546      */
547     @NotFlag
548     public static final int
549         AccessFlags                       = PUBLIC | PROTECTED | PRIVATE,
550         LocalClassFlags                   = FINAL | ABSTRACT | STRICTFP | ENUM | SYNTHETIC | IDENTITY_TYPE,
551         StaticLocalClassFlags             = LocalClassFlags | STATIC | INTERFACE,
552         MemberClassFlags                  = LocalClassFlags | INTERFACE | AccessFlags,
553         MemberStaticClassFlags            = MemberClassFlags | STATIC,
554         ClassFlags                        = LocalClassFlags | INTERFACE | PUBLIC | ANNOTATION,
555         InterfaceVarFlags                 = FINAL | STATIC | PUBLIC,
556         VarFlags                          = AccessFlags | FINAL | STATIC |
557                                             VOLATILE | TRANSIENT | ENUM,
558         ConstructorFlags                  = AccessFlags,
559         InterfaceMethodFlags              = ABSTRACT | PUBLIC,
560         MethodFlags                       = AccessFlags | ABSTRACT | STATIC | NATIVE |
561                                             SYNCHRONIZED | FINAL | STRICTFP,
562         RecordMethodFlags                 = AccessFlags | ABSTRACT | STATIC |
563                                             SYNCHRONIZED | FINAL | STRICTFP;
564     @NotFlag
565     public static final long
566         //NOTE: flags in ExtendedStandardFlags cannot be overlayed across Symbol kinds:
567         ExtendedStandardFlags             = (long)StandardFlags | DEFAULT | SEALED | NON_SEALED | VALUE_CLASS,
568         ExtendedMemberClassFlags          = (long)MemberClassFlags | SEALED | NON_SEALED | VALUE_CLASS,
569         ExtendedMemberStaticClassFlags    = (long) MemberStaticClassFlags | SEALED | NON_SEALED | VALUE_CLASS,
570         ExtendedClassFlags                = (long)ClassFlags | SEALED | NON_SEALED | VALUE_CLASS,
571         ExtendedLocalClassFlags           = (long) LocalClassFlags | VALUE_CLASS,
572         ExtendedStaticLocalClassFlags     = (long) StaticLocalClassFlags | VALUE_CLASS,
573         ValueFieldFlags                   = (long) VarFlags | STRICT | FINAL,
574         ModifierFlags                     = ((long)StandardFlags & ~INTERFACE) | DEFAULT | SEALED | NON_SEALED | VALUE_CLASS,
575         InterfaceMethodMask               = ABSTRACT | PRIVATE | STATIC | PUBLIC | STRICTFP | DEFAULT,
576         AnnotationTypeElementMask         = ABSTRACT | PUBLIC,
577         LocalVarFlags                     = FINAL | PARAMETER,
578         ReceiverParamFlags                = PARAMETER;
579 
580     public static Set<Modifier> asModifierSet(long flags) {
581         Set<Modifier> modifiers = modifierSets.get(flags);
582         if (modifiers == null) {
583             modifiers = java.util.EnumSet.noneOf(Modifier.class);
584             if (0 != (flags & PUBLIC))    modifiers.add(Modifier.PUBLIC);
585             if (0 != (flags & PROTECTED)) modifiers.add(Modifier.PROTECTED);
586             if (0 != (flags & PRIVATE))   modifiers.add(Modifier.PRIVATE);
587             if (0 != (flags & ABSTRACT))  modifiers.add(Modifier.ABSTRACT);
588             if (0 != (flags & STATIC))    modifiers.add(Modifier.STATIC);
589             if (0 != (flags & SEALED))    modifiers.add(Modifier.SEALED);
590             if (0 != (flags & NON_SEALED))
591                                           modifiers.add(Modifier.NON_SEALED);
592             if (0 != (flags & FINAL))     modifiers.add(Modifier.FINAL);
593             if (0 != (flags & TRANSIENT)) modifiers.add(Modifier.TRANSIENT);
594             if (0 != (flags & VOLATILE))  modifiers.add(Modifier.VOLATILE);
595             if (0 != (flags & SYNCHRONIZED))
596                                           modifiers.add(Modifier.SYNCHRONIZED);
597             if (0 != (flags & NATIVE))    modifiers.add(Modifier.NATIVE);
598             if (0 != (flags & STRICTFP))  modifiers.add(Modifier.STRICTFP);
599             if (0 != (flags & DEFAULT))   modifiers.add(Modifier.DEFAULT);
600             if (0 != (flags & VALUE_CLASS))     modifiers.add(Modifier.VALUE);
601             modifiers = Collections.unmodifiableSet(modifiers);
602             modifierSets.put(flags, modifiers);
603         }
604         return modifiers;
605     }
606 
607     // Cache of modifier sets.
608     private static final Map<Long, Set<Modifier>> modifierSets = new ConcurrentHashMap<>(64);
609 
610     public static boolean isStatic(Symbol symbol) {
611         return (symbol.flags() & STATIC) != 0;
612     }
613 
614     public static boolean isEnum(Symbol symbol) {
615         return (symbol.flags() & ENUM) != 0;
616     }
617 
618     public static boolean isConstant(Symbol.VarSymbol symbol) {
619         return symbol.getConstValue() != null;
620     }
621 
622     public enum FlagTarget {
623         /** This flag can appear the JCBlock.
624          */
625         BLOCK,
626         /** This flag can appear on ClassSymbols.
627          */
628         CLASS,
629         /** This flag can appear on ModuleSymbols.
630          */
631         MODULE,
632         /** This flag can appear on PackageSymbols.
633          */
634         PACKAGE,
635         /** This flag can appear on TypeVarSymbols.
636          */
637         TYPE_VAR,
638         /** This flag can appear on MethodSymbols.
639          */
640         METHOD,
641         /** This flag can appear on VarSymbols, includes
642          *  including ParamSymbol, and BindingSymbol.
643          */
644         VARIABLE;
645     }
646 
647     @Retention(RetentionPolicy.RUNTIME)
648     public @interface Use {
649         public FlagTarget[] value();
650     }
651 
652     @Retention(RetentionPolicy.RUNTIME)
653     public @interface NotFlag {}
654 
655     @Retention(RetentionPolicy.RUNTIME)
656     public @interface CustomToStringValue {
657         public String value();
658     }
659 
660     @Retention(RetentionPolicy.RUNTIME)
661     public @interface NoToStringValue {
662     }
663 }