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