1 /*
  2  * Copyright (c) 2021, 2024, 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 java.lang.reflect;
 27 
 28 import jdk.internal.javac.PreviewFeature;
 29 import jdk.internal.misc.PreviewFeatures;
 30 
 31 import java.util.Collections;
 32 import java.util.Objects;
 33 import java.util.Map;
 34 import java.util.Set;
 35 import java.util.function.Function;
 36 import static java.util.Map.entry;
 37 
 38 /**
 39  * Represents a JVM access or module-related flag on a runtime member,
 40  * such as a {@linkplain Class class}, {@linkplain Field field}, or
 41  * {@linkplain Executable method}.
 42  *
 43  * <P>JVM access and module-related flags are related to, but distinct
 44  * from Java language {@linkplain Modifier modifiers}. Some modifiers
 45  * and access flags have a one-to-one correspondence, such as {@code
 46  * public}. In other cases, some language-level modifiers do
 47  * <em>not</em> have an access flag, such as {@code sealed} (JVMS
 48  * {@jvms 4.7.31}) and some access flags have no corresponding
 49  * modifier, such as {@linkplain #SYNTHETIC synthetic}.
 50  *
 51  * <p>The values for the constants representing the access and module
 52  * flags are taken from sections of <cite>The Java Virtual Machine
 53  * Specification</cite> including {@jvms 4.1} (class access and
 54  * property modifiers), {@jvms 4.5} (field access and property flags),
 55  * {@jvms 4.6} (method access and property flags), {@jvms 4.7.6}
 56  * (nested class access and property flags), {@jvms 4.7.24} (method
 57  * parameters), and {@jvms 4.7.25} (module flags and requires,
 58  * exports, and opens flags).
 59  *
 60  * <p>The {@linkplain #mask() mask} values for the different access
 61  * flags are <em>not</em> distinct. Flags are defined for different
 62  * kinds of JVM structures and the same bit position has different
 63  * meanings in different contexts. For example, {@code 0x0000_0040}
 64  * indicates a {@link #VOLATILE volatile} field but a {@linkplain
 65  * #BRIDGE bridge method}; {@code 0x0000_0080} indicates a {@link
 66  * #TRANSIENT transient} field but a {@linkplain #VARARGS variable
 67  * arity (varargs)} method.
 68  *
 69  * @implSpec
 70  * The access flag constants are ordered by non-decreasing mask
 71  * value; that is the mask value of a constant is greater than or
 72  * equal to the mask value of an immediate neighbor to its (syntactic)
 73  * left. If new constants are added, this property will be
 74  * maintained. That implies new constants will not necessarily be
 75  * added at the end of the existing list.
 76  *
 77  * @apiNote
 78  * The JVM class file format has a {@linkplain ClassFileFormatVersion new version} defined for each new
 79  * {@linkplain Runtime.Version#feature() feature release}. A new class
 80  * file version may define new access flags or retire old ones. {@code
 81  * AccessFlag} is intended to model the set of access flags across
 82  * class file format versions. The range of versions an access flag is
 83  * recognized is not explicitly indicated in this API. See the current
 84  * <cite>The Java Virtual Machine Specification</cite> for
 85  * details. Unless otherwise indicated, access flags can be assumed to
 86  * be recognized in the {@linkplain Runtime#version() current
 87  * version}.
 88  *
 89  * @see java.lang.reflect.Modifier
 90  * @see java.lang.module.ModuleDescriptor.Modifier
 91  * @see java.lang.module.ModuleDescriptor.Requires.Modifier
 92  * @see java.lang.module.ModuleDescriptor.Exports.Modifier
 93  * @see java.lang.module.ModuleDescriptor.Opens.Modifier
 94  * @see java.compiler/javax.lang.model.element.Modifier
 95  * @since 20
 96  */
 97 @SuppressWarnings("doclint:reference") // cross-module link
 98 public enum AccessFlag {
 99     // Note to maintainers: anonymous class instances are used rather
100     // than lambdas to initialize the functions used for the
101     // cffvToLocations field to avoid using lambdas too early in JDK
102     // initialization.
103 
104     /**
105      * The access flag {@code ACC_PUBLIC}, corresponding to the source
106      * modifier {@link Modifier#PUBLIC public}, with a mask value of
107      * <code>{@value "0x%04x" Modifier#PUBLIC}</code>.
108      */
109     PUBLIC(Modifier.PUBLIC, true,
110            Location.SET_PUBLIC_1,
111            new Function<ClassFileFormatVersion, Set<Location>>() {
112                @Override
113                public Set<Location> apply(ClassFileFormatVersion cffv) {
114                    return (cffv == ClassFileFormatVersion.RELEASE_0) ?
115                        Location.SET_CLASS_FIELD_METHOD:
116                        Location.SET_PUBLIC_1;
117                }
118            }),
119 
120     /**
121      * The access flag {@code ACC_PRIVATE}, corresponding to the
122      * source modifier {@link Modifier#PRIVATE private}, with a mask
123      * value of <code>{@value "0x%04x" Modifier#PRIVATE}</code>.
124      */
125     PRIVATE(Modifier.PRIVATE, true, Location.SET_FIELD_METHOD_INNER_CLASS,
126             new Function<ClassFileFormatVersion, Set<Location>>() {
127                 @Override
128                     public Set<Location> apply(ClassFileFormatVersion cffv) {
129                     return (cffv == ClassFileFormatVersion.RELEASE_0) ?
130                         Location.SET_FIELD_METHOD:
131                         Location.SET_FIELD_METHOD_INNER_CLASS;
132                 }
133             }),
134 
135     /**
136      * The access flag {@code ACC_PROTECTED}, corresponding to the
137      * source modifier {@link Modifier#PROTECTED protected}, with a mask
138      * value of <code>{@value "0x%04x" Modifier#PROTECTED}</code>.
139      */
140     PROTECTED(Modifier.PROTECTED, true, Location.SET_FIELD_METHOD_INNER_CLASS,
141               new Function<ClassFileFormatVersion, Set<Location>>() {
142                   @Override
143                   public Set<Location> apply(ClassFileFormatVersion cffv) {
144                   return (cffv == ClassFileFormatVersion.RELEASE_0) ?
145                       Location.SET_FIELD_METHOD:
146                       Location.SET_FIELD_METHOD_INNER_CLASS;
147                   }
148               }),
149 
150     /**
151      * The access flag {@code ACC_STATIC}, corresponding to the source
152      * modifier {@link Modifier#STATIC static}, with a mask value of
153      * <code>{@value "0x%04x" Modifier#STATIC}</code>.
154      */
155     STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS,
156            new Function<ClassFileFormatVersion, Set<Location>>() {
157                @Override
158                public Set<Location> apply(ClassFileFormatVersion cffv) {
159                    return (cffv == ClassFileFormatVersion.RELEASE_0) ?
160                        Location.SET_FIELD_METHOD:
161                        Location.SET_FIELD_METHOD_INNER_CLASS;}
162            }),
163 
164     /**
165      * The access flag {@code ACC_FINAL}, corresponding to the source
166      * modifier {@link Modifier#FINAL final}, with a mask
167      * value of <code>{@value "0x%04x" Modifier#FINAL}</code>.
168      */
169     FINAL(Modifier.FINAL, true,
170           Location.SET_FINAL_8,
171            new Function<ClassFileFormatVersion, Set<Location>>() {
172               @Override
173               public Set<Location> apply(ClassFileFormatVersion cffv) {
174                   if (cffv.compareTo(ClassFileFormatVersion.RELEASE_8) >= 0) {
175                       return Location.SET_FINAL_8;
176                   } else {
177                       return (cffv == ClassFileFormatVersion.RELEASE_0) ?
178                           Location.SET_CLASS_FIELD_METHOD :
179                           Location.SET_CLASS_FIELD_METHOD_INNER_CLASS;
180                   }
181               }
182           }),
183 
184     /**
185      * The access flag {@code ACC_SUPER} with a mask value of {@code
186      * 0x0020}.
187      *
188      * @apiNote
189      * In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
190      * flag as set in every class file (JVMS {@jvms 4.1}).
191      * If preview feature is enabled,
192      * the {@code 0x0020} access flag bit is {@linkplain #IDENTITY IDENTITY access flag}.
193      */
194     SUPER(0x0000_0020, false,
195             PreviewFeatures.isEnabled() ? Location.EMPTY_SET : Location.SET_CLASS,
196             new Function<ClassFileFormatVersion, Set<Location>>() {
197             @Override
198             public Set<Location> apply(ClassFileFormatVersion cffv) {
199                 return (cffv.compareTo(ClassFileFormatVersion.latest()) >= 0) &&
200                         PreviewFeatures.isEnabled() ? Location.EMPTY_SET : Location.SET_CLASS;
201             }
202         }),
203 
204     /**
205      * The access flag {@code ACC_IDENTITY}, corresponding to the
206      * modifier {@link Modifier#IDENTITY identity}, with a mask
207      * value of <code>{@value "0x%04x" Modifier#IDENTITY}</code>.
208      * @jvms 4.1 -B. Class access and property modifiers
209      *
210      * @since Valhalla
211      */
212     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
213     IDENTITY(Modifier.IDENTITY, false,
214             PreviewFeatures.isEnabled() ? Location.SET_CLASS_INNER_CLASS : Location.EMPTY_SET,
215             new Function<ClassFileFormatVersion, Set<Location>>() {
216                 @Override
217                 public Set<Location> apply(ClassFileFormatVersion cffv) {
218                     return (cffv.compareTo(ClassFileFormatVersion.latest()) >= 0
219                             && PreviewFeatures.isEnabled())
220                             ? Location.SET_CLASS_INNER_CLASS : Location.EMPTY_SET;
221                 }
222             }),
223 
224     /**
225      * The module flag {@code ACC_OPEN} with a mask value of {@code
226      * 0x0020}.
227      * @see java.lang.module.ModuleDescriptor#isOpen
228      */
229     OPEN(0x0000_0020, false, Location.SET_MODULE,
230          new Function<ClassFileFormatVersion, Set<Location>>() {
231              @Override
232              public Set<Location> apply(ClassFileFormatVersion cffv) {
233                  return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
234                      Location.SET_MODULE:
235                      Location.EMPTY_SET;}
236          }),
237 
238     /**
239      * The module requires flag {@code ACC_TRANSITIVE} with a mask
240      * value of {@code 0x0020}.
241      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
242      */
243     TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
244                new Function<ClassFileFormatVersion, Set<Location>>() {
245                    @Override
246                    public Set<Location> apply(ClassFileFormatVersion cffv) {
247                        return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
248                            Location.SET_MODULE_REQUIRES:
249                            Location.EMPTY_SET;}
250                }),
251 
252     /**
253      * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
254      * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with
255      * a mask value of <code>{@value "0x%04x" Modifier#SYNCHRONIZED}</code>.
256      */
257     SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD, null),
258 
259     /**
260      * The module requires flag {@code ACC_STATIC_PHASE} with a mask
261      * value of {@code 0x0040}.
262      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC
263      */
264     STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES,
265                  new Function<ClassFileFormatVersion, Set<Location>>() {
266                      @Override
267                      public Set<Location> apply(ClassFileFormatVersion cffv) {
268                          return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
269                              Location.SET_MODULE_REQUIRES:
270                              Location.EMPTY_SET;}
271                  }),
272 
273     /**
274      * The access flag {@code ACC_VOLATILE}, corresponding to the
275      * source modifier {@link Modifier#VOLATILE volatile}, with a mask
276      * value of <code>{@value "0x%04x" Modifier#VOLATILE}</code>.
277      */
278     VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD, null),
279 
280     /**
281      * The access flag {@code ACC_BRIDGE} with a mask value of
282      * <code>{@value "0x%04x" Modifier#BRIDGE}</code>
283      * @see Method#isBridge()
284      */
285     BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD,
286            new Function<ClassFileFormatVersion, Set<Location>>() {
287                @Override
288                public Set<Location> apply(ClassFileFormatVersion cffv) {
289                    return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
290                        Location.SET_METHOD:
291                        Location.EMPTY_SET;}
292            }),
293 
294     /**
295      * The access flag {@code ACC_TRANSIENT}, corresponding to the
296      * source modifier {@link Modifier#TRANSIENT transient}, with a
297      * mask value of <code>{@value "0x%04x" Modifier#TRANSIENT}</code>.
298      */
299     TRANSIENT(Modifier.TRANSIENT, true, Location.SET_FIELD, null),
300 
301     /**
302      * The access flag {@code ACC_VARARGS} with a mask value of
303      <code>{@value "0x%04x" Modifier#VARARGS}</code>.
304      * @see Executable#isVarArgs()
305      */
306     VARARGS(Modifier.VARARGS, false, Location.SET_METHOD,
307             new Function<ClassFileFormatVersion, Set<Location>>() {
308                 @Override
309                 public Set<Location> apply(ClassFileFormatVersion cffv) {
310                     return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
311                         Location.SET_METHOD:
312                         Location.EMPTY_SET;}
313             }),
314 
315     /**
316      * The access flag {@code ACC_NATIVE}, corresponding to the source
317      * modifier {@link Modifier#NATIVE native}, with a mask value of
318      * <code>{@value "0x%04x" Modifier#NATIVE}</code>.
319      */
320     NATIVE(Modifier.NATIVE, true, Location.SET_METHOD, null),
321 
322     /**
323      * The access flag {@code ACC_INTERFACE} with a mask value of
324      * {@code 0x0200}.
325      * @see Class#isInterface()
326      */
327     INTERFACE(Modifier.INTERFACE, false, Location.SET_CLASS_INNER_CLASS,
328               new Function<ClassFileFormatVersion, Set<Location>>() {
329                   @Override
330                   public Set<Location> apply(ClassFileFormatVersion cffv) {
331                       return (cffv.compareTo(ClassFileFormatVersion.RELEASE_0) == 0 ) ?
332                           Location.SET_CLASS:
333                           Location.SET_CLASS_INNER_CLASS;}
334               }),
335 
336     /**
337      * The access flag {@code ACC_ABSTRACT}, corresponding to the
338      * source modifier {@link Modifier#ABSTRACT abstract}, with a mask
339      * value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>.
340      */
341     ABSTRACT(Modifier.ABSTRACT, true,
342              Location.SET_CLASS_METHOD_INNER_CLASS,
343              new Function<ClassFileFormatVersion, Set<Location>>() {
344                  @Override
345                  public Set<Location> apply(ClassFileFormatVersion cffv) {
346                      return (cffv.compareTo(ClassFileFormatVersion.RELEASE_0) == 0 ) ?
347                          Location.SET_CLASS_METHOD:
348                          Location.SET_CLASS_METHOD_INNER_CLASS;}
349              }),
350 
351     /**
352      * The access flag {@code ACC_STRICT}, corresponding to the source
353      * modifier {@link Modifier#STRICT strictfp}, with a mask value of
354      * <code>{@value "0x%04x" Modifier#STRICT}</code>.
355      *
356      * @apiNote
357      * The {@code ACC_STRICT} access flag is defined for class file
358      * major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
359      * corresponding to Java SE 1.2 through 16.
360      */
361     STRICT(Modifier.STRICT, true, Location.EMPTY_SET,
362              new Function<ClassFileFormatVersion, Set<Location>>() {
363                @Override
364                public Set<Location> apply(ClassFileFormatVersion cffv) {
365                    return (cffv.compareTo(ClassFileFormatVersion.RELEASE_2)  >= 0 &&
366                            cffv.compareTo(ClassFileFormatVersion.RELEASE_16) <= 0) ?
367                        Location.SET_METHOD:
368                        Location.EMPTY_SET;}
369            }),
370 
371     /**
372      * The access flag {@code ACC_STRICT}, with a mask
373      * value of <code>{@value "0x%04x" Modifier#STRICT}</code>.
374      * @jvms 4.5 Fields
375      *
376      * @since Valhalla
377      */
378     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
379     STRICT_FIELD(Modifier.STRICT, false,
380             PreviewFeatures.isEnabled() ? Location.SET_FIELD : Location.EMPTY_SET,
381             new Function<ClassFileFormatVersion, Set<Location>>() {
382                 @Override
383                 public Set<Location> apply(ClassFileFormatVersion cffv) {
384                     return (cffv.compareTo(ClassFileFormatVersion.latest()) >= 0
385                             && PreviewFeatures.isEnabled())
386                             ? Location.SET_FIELD : Location.EMPTY_SET;
387                 }
388             }) {
389         @Override
390         public String toString() {
391             return "STRICT";
392         }
393     },
394 
395     /**
396      * The access flag {@code ACC_SYNTHETIC} with a mask value of
397      * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>.
398      * @see Class#isSynthetic()
399      * @see Executable#isSynthetic()
400      * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
401      */
402     SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9,
403               new Function<ClassFileFormatVersion, Set<Location>>() {
404                   @Override
405                   public Set<Location> apply(ClassFileFormatVersion cffv) {
406                       if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 )
407                           return Location.SET_SYNTHETIC_9;
408                       else {
409                           return
410                               switch(cffv) {
411                               case RELEASE_7 -> Location.SET_SYNTHETIC_7;
412                               case RELEASE_8 -> Location.SET_SYNTHETIC_8;
413                               default        -> Location.EMPTY_SET;
414                               };
415                       }
416                   }
417               }),
418 
419     /**
420      * The access flag {@code ACC_ANNOTATION} with a mask value of
421      * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>.
422      * @see Class#isAnnotation()
423      */
424     ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS,
425                new Function<ClassFileFormatVersion, Set<Location>>() {
426                    @Override
427                    public Set<Location> apply(ClassFileFormatVersion cffv) {
428                        return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
429                            Location.SET_CLASS_INNER_CLASS:
430                            Location.EMPTY_SET;}
431                }),
432 
433     /**
434      * The access flag {@code ACC_ENUM} with a mask value of
435      * <code>{@value "0x%04x" Modifier#ENUM}</code>.
436      * @see Class#isEnum()
437      */
438     ENUM(Modifier.ENUM, false, Location.SET_CLASS_FIELD_INNER_CLASS,
439          new Function<ClassFileFormatVersion, Set<Location>>() {
440              @Override
441              public Set<Location> apply(ClassFileFormatVersion cffv) {
442                  return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
443                      Location.SET_CLASS_FIELD_INNER_CLASS:
444                      Location.EMPTY_SET;}
445          }),
446 
447     /**
448      * The access flag {@code ACC_MANDATED} with a mask value of
449      * <code>{@value "0x%04x" Modifier#MANDATED}</code>.
450      */
451     MANDATED(Modifier.MANDATED, false, Location.SET_MANDATED_9,
452              new Function<ClassFileFormatVersion, Set<Location>>() {
453                  @Override
454                  public Set<Location> apply(ClassFileFormatVersion cffv) {
455                      if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) {
456                          return Location.SET_MANDATED_9;
457                      } else {
458                          return (cffv == ClassFileFormatVersion.RELEASE_8) ?
459                              Location.SET_METHOD_PARAM:
460                              Location.EMPTY_SET;
461                      }
462                  }
463              }),
464 
465     /**
466      * The access flag {@code ACC_MODULE} with a mask value of {@code
467      * 0x8000}.
468      */
469     MODULE(0x0000_8000, false, Location.SET_CLASS,
470            new Function<ClassFileFormatVersion, Set<Location>>() {
471                @Override
472                public Set<Location> apply(ClassFileFormatVersion cffv) {
473                    return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
474                        Location.SET_CLASS:
475                        Location.EMPTY_SET;}
476            })
477     ;
478 
479     // May want to override toString for a different enum constant ->
480     // name mapping.
481 
482     private final int mask;
483     private final boolean sourceModifier;
484 
485     // Intentionally using Set rather than EnumSet since EnumSet is
486     // mutable.
487     private final Set<Location> locations;
488     // Lambda to implement locations(ClassFileFormatVersion cffv)
489     private final Function<ClassFileFormatVersion, Set<Location>> cffvToLocations;
490 
491     private AccessFlag(int mask,
492                        boolean sourceModifier,
493                        Set<Location> locations,
494                        Function<ClassFileFormatVersion, Set<Location>> cffvToLocations) {
495         this.mask = mask;
496         this.sourceModifier = sourceModifier;
497         this.locations = locations;
498         this.cffvToLocations = cffvToLocations;
499     }
500 
501     /**
502      * {@return the corresponding integer mask for the access flag}
503      */
504     public int mask() {
505         return mask;
506     }
507 
508     /**
509      * {@return whether or not the flag has a directly corresponding
510      * modifier in the Java programming language}
511      */
512     public boolean sourceModifier() {
513         return sourceModifier;
514     }
515 
516     /**
517      * {@return kinds of constructs the flag can be applied to in the
518      * latest class file format version}
519      */
520     public Set<Location> locations() {
521         return locations;
522     }
523 
524     /**
525      * {@return kinds of constructs the flag can be applied to in the
526      * given class file format version}
527      * @param cffv the class file format version to use
528      * @throws NullPointerException if the parameter is {@code null}
529      */
530     public Set<Location> locations(ClassFileFormatVersion cffv) {
531         Objects.requireNonNull(cffv);
532         if (cffvToLocations == null) {
533             return locations;
534         } else {
535             return cffvToLocations.apply(cffv);
536         }
537     }
538 
539     /**
540      * {@return an unmodifiable set of access flags for the given mask value
541      * appropriate for the location in question}
542      *
543      * @param mask bit mask of access flags
544      * @param location context to interpret mask value
545      * @throws IllegalArgumentException if the mask contains bit
546      * positions not supported for the location in question
547      */
548     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
549         Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class);
550         for (var accessFlag : LocationToFlags.locationToFlags.get(location)) {
551             int accessMask = accessFlag.mask();
552             if ((mask & accessMask) != 0) {
553                 result.add(accessFlag);
554                 mask = mask & ~accessMask;
555                 if (mask == 0) {
556                     break;      // no more mask bits
557                 }
558             }
559         }
560         if (mask != 0) {
561             throw new IllegalArgumentException("Unmatched bit position 0x" +
562                                                Integer.toHexString(mask) +
563                                                " for location " + location);
564         }
565         return Collections.unmodifiableSet(result);
566     }
567 
568     /**
569      * {@return an unmodifiable set of access flags for the given mask value
570      * appropriate for the location in question}
571      *
572      * @param mask bit mask of access flags
573      * @param location context to interpret mask value
574      * @param cffv the class file format version
575      * @throws IllegalArgumentException if the mask contains bit
576      * positions not supported for the location in question
577      *
578      * @since Valhalla
579      */
580     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location,
581                                                     ClassFileFormatVersion cffv) {
582         Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class);
583         for (var accessFlag : AccessFlag.values()) {
584             int accessMask = accessFlag.mask();
585             if ((mask & accessMask) != 0) {
586                 var locations = accessFlag.locations(cffv);
587                 if (locations.contains(location)) {
588                     result.add(accessFlag);
589                     mask = mask & ~accessMask;
590                     if (mask == 0) {
591                         break;      // no more mask bits
592                     }
593                 }
594             }
595         }
596         if (mask != 0) {
597             throw new IllegalArgumentException("Unmatched bit position 0x" +
598                                                Integer.toHexString(mask) +
599                                                " for location " + location +
600                                                " for class file format version " + cffv);
601         }
602         return Collections.unmodifiableSet(result);
603     }
604 
605 
606     /**
607      * A location within a class file where flags can be applied.
608      *
609      * Note that since these locations represent class file structures
610      * rather than language structures many language structures, such
611      * as constructors and interfaces, are <em>not</em> present.
612      * @since 20
613      */
614     public enum Location {
615         /**
616          * Class location.
617          * @jvms 4.1 The ClassFile Structure
618          */
619         CLASS,
620 
621         /**
622          * Field location.
623          * @jvms 4.5 Fields
624          */
625         FIELD,
626 
627         /**
628          * Method location.
629          * @jvms 4.6 Methods
630          */
631         METHOD,
632 
633         /**
634          * Inner class location.
635          * @jvms 4.7.6 The InnerClasses Attribute
636          */
637         INNER_CLASS,
638 
639         /**
640          * Method parameter location.
641          * @jvms 4.7.24 The MethodParameters Attribute
642          */
643         METHOD_PARAMETER,
644 
645         /**
646          * Module location
647          * @jvms 4.7.25 The Module Attribute
648          */
649         MODULE,
650 
651         /**
652          * Module requires location
653          * @jvms 4.7.25 The Module Attribute
654          */
655         MODULE_REQUIRES,
656 
657         /**
658          * Module exports location
659          * @jvms 4.7.25 The Module Attribute
660          */
661         MODULE_EXPORTS,
662 
663         /**
664          * Module opens location
665          * @jvms 4.7.25 The Module Attribute
666          */
667         MODULE_OPENS;
668 
669         // Repeated sets of locations used by AccessFlag constants
670         private static final Set<Location> EMPTY_SET = Set.of();
671         private static final Set<Location> SET_MODULE = Set.of(MODULE);
672         private static final Set<Location> SET_CLASS_METHOD_INNER_CLASS =
673             Set.of(CLASS, METHOD, INNER_CLASS);
674         private static final Set<Location> SET_CLASS_FIELD_METHOD =
675             Set.of(CLASS, FIELD, METHOD);
676         private static final Set<Location> SET_CLASS_FIELD_INNER_CLASS =
677             Set.of(CLASS, FIELD, INNER_CLASS);
678         private static final Set<Location> SET_CLASS_FIELD_METHOD_INNER_CLASS =
679             Set.of(CLASS, FIELD, METHOD, INNER_CLASS);
680         private static final Set<Location> SET_CLASS_METHOD =
681             Set.of(CLASS, METHOD);
682         private static final Set<Location> SET_FIELD_METHOD =
683             Set.of(FIELD, METHOD);
684         private static final Set<Location> SET_FIELD_METHOD_INNER_CLASS =
685             Set.of(FIELD, METHOD, INNER_CLASS);
686         private static final Set<Location> SET_METHOD = Set.of(METHOD);
687         private static final Set<Location> SET_METHOD_PARAM = Set.of(METHOD_PARAMETER);
688         private static final Set<Location> SET_FIELD = Set.of(FIELD);
689         private static final Set<Location> SET_CLASS = Set.of(CLASS);
690         private static final Set<Location> SET_CLASS_INNER_CLASS =
691             Set.of(CLASS, INNER_CLASS);
692         private static final Set<Location> SET_MODULE_REQUIRES =
693             Set.of(MODULE_REQUIRES);
694         private static final Set<Location> SET_PUBLIC_1 =
695             Set.of(CLASS, FIELD, METHOD, INNER_CLASS);
696         private static final Set<Location> SET_FINAL_8 =
697             Set.of(CLASS, FIELD, METHOD,
698                    INNER_CLASS,     /* added in 1.1 */
699                    METHOD_PARAMETER); /* added in 8 */
700         private static final Set<Location> SET_SYNTHETIC_7 =
701               Set.of(CLASS, FIELD, METHOD,
702                      INNER_CLASS);
703         private static final Set<Location> SET_SYNTHETIC_8 =
704               Set.of(CLASS, FIELD, METHOD,
705                      INNER_CLASS, METHOD_PARAMETER);
706         private static final Set<Location> SET_SYNTHETIC_9 =
707               // Added as an access flag in 7
708               Set.of(CLASS, FIELD, METHOD,
709                      INNER_CLASS,
710                      METHOD_PARAMETER, // Added in 8
711                      // Module-related items added in 9
712                      MODULE, MODULE_REQUIRES,
713                      MODULE_EXPORTS, MODULE_OPENS);
714         private static final Set<Location> SET_MANDATED_9 =
715             Set.of(METHOD_PARAMETER, // From 8
716                    // Starting in 9
717                    MODULE, MODULE_REQUIRES,
718                    MODULE_EXPORTS, MODULE_OPENS);
719     }
720 
721     private static class LocationToFlags {
722         private static Map<Location, Set<AccessFlag>> locationToFlags =
723             Map.ofEntries(entry(Location.CLASS,
724                                 Set.of(PUBLIC, FINAL, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER),
725                                        INTERFACE, ABSTRACT,
726                                        SYNTHETIC, ANNOTATION,
727                                        ENUM, AccessFlag.MODULE)),
728                           entry(Location.FIELD,
729                                 PreviewFeatures.isEnabled() ?
730                                         // STRICT_FIELD should be included only if preview is enabled
731                                         Set.of(PUBLIC, PRIVATE, PROTECTED,
732                                             STATIC, FINAL, VOLATILE,
733                                             TRANSIENT, SYNTHETIC, ENUM, STRICT_FIELD) :
734                                         Set.of(PUBLIC, PRIVATE, PROTECTED,
735                                                 STATIC, FINAL, VOLATILE,
736                                                 TRANSIENT, SYNTHETIC, ENUM)),
737                           entry(Location.METHOD,
738                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
739                                        STATIC, FINAL, SYNCHRONIZED,
740                                        BRIDGE, VARARGS, NATIVE,
741                                        ABSTRACT, STRICT, SYNTHETIC)),
742                           entry(Location.INNER_CLASS,
743                                           Set.of(PUBLIC, PRIVATE, PROTECTED, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER),
744                                                   STATIC, FINAL, INTERFACE, ABSTRACT,
745                                                   SYNTHETIC, ANNOTATION, ENUM)),
746                           entry(Location.METHOD_PARAMETER,
747                                 Set.of(FINAL, SYNTHETIC, MANDATED)),
748                           entry(Location.MODULE,
749                                 Set.of(OPEN, SYNTHETIC, MANDATED)),
750                           entry(Location.MODULE_REQUIRES,
751                                 Set.of(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED)),
752                           entry(Location.MODULE_EXPORTS,
753                                 Set.of(SYNTHETIC, MANDATED)),
754                           entry(Location.MODULE_OPENS,
755                                 Set.of(SYNTHETIC, MANDATED)));
756     }
757 }