001    /*
002     * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.javac.code;
027    
028    import java.util.EnumSet;
029    import java.util.Collections;
030    import java.util.Map;
031    import java.util.Set;
032    import javax.lang.model.element.Modifier;
033    
034    /** Access flags and other modifiers for Java classes and members.
035     *
036     *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
037     *  you write code that depends on this, you do so at your own risk.
038     *  This code and its internal interfaces are subject to change or
039     *  deletion without notice.</b>
040     */
041    public class Flags {
042    
043        private Flags() {} // uninstantiable
044    
045        public static String toString(long flags) {
046            StringBuffer buf = new StringBuffer();
047            String sep = "";
048            for (Flag s : asFlagSet(flags)) {
049                buf.append(sep);
050                buf.append(s);
051                sep = " ";
052            }
053            return buf.toString();
054        }
055    
056        public static EnumSet<Flag> asFlagSet(long mask) {
057            EnumSet<Flag> flags = EnumSet.noneOf(Flag.class);
058            if ((mask&PUBLIC) != 0) flags.add(Flag.PUBLIC);
059            if ((mask&PRIVATE) != 0) flags.add(Flag.PRIVATE);
060            if ((mask&PROTECTED) != 0) flags.add(Flag.PROTECTED);
061            if ((mask&STATIC) != 0) flags.add(Flag.STATIC);
062            if ((mask&FINAL) != 0) flags.add(Flag.FINAL);
063            if ((mask&SYNCHRONIZED) != 0) flags.add(Flag.SYNCHRONIZED);
064            if ((mask&VOLATILE) != 0) flags.add(Flag.VOLATILE);
065            if ((mask&TRANSIENT) != 0) flags.add(Flag.TRANSIENT);
066            if ((mask&NATIVE) != 0) flags.add(Flag.NATIVE);
067            if ((mask&INTERFACE) != 0) flags.add(Flag.INTERFACE);
068            if ((mask&ABSTRACT) != 0) flags.add(Flag.ABSTRACT);
069            if ((mask&STRICTFP) != 0) flags.add(Flag.STRICTFP);
070            if ((mask&BRIDGE) != 0) flags.add(Flag.BRIDGE);
071            if ((mask&SYNTHETIC) != 0) flags.add(Flag.SYNTHETIC);
072            if ((mask&DEPRECATED) != 0) flags.add(Flag.DEPRECATED);
073            if ((mask&HASINIT) != 0) flags.add(Flag.HASINIT);
074            if ((mask&ENUM) != 0) flags.add(Flag.ENUM);
075            if ((mask&IPROXY) != 0) flags.add(Flag.IPROXY);
076            if ((mask&NOOUTERTHIS) != 0) flags.add(Flag.NOOUTERTHIS);
077            if ((mask&EXISTS) != 0) flags.add(Flag.EXISTS);
078            if ((mask&COMPOUND) != 0) flags.add(Flag.COMPOUND);
079            if ((mask&CLASS_SEEN) != 0) flags.add(Flag.CLASS_SEEN);
080            if ((mask&SOURCE_SEEN) != 0) flags.add(Flag.SOURCE_SEEN);
081            if ((mask&LOCKED) != 0) flags.add(Flag.LOCKED);
082            if ((mask&UNATTRIBUTED) != 0) flags.add(Flag.UNATTRIBUTED);
083            if ((mask&ANONCONSTR) != 0) flags.add(Flag.ANONCONSTR);
084            if ((mask&ACYCLIC) != 0) flags.add(Flag.ACYCLIC);
085            if ((mask&PARAMETER) != 0) flags.add(Flag.PARAMETER);
086            if ((mask&VARARGS) != 0) flags.add(Flag.VARARGS);
087            if ((mask&SEPARABLE) != 0) flags.add(Flag.SEPARABLE);
088            return flags;
089        }
090    
091        /* Standard Java flags.
092         */
093        public static final int PUBLIC       = 1<<0;
094        public static final int PRIVATE      = 1<<1;
095        public static final int PROTECTED    = 1<<2;
096        public static final int STATIC       = 1<<3;
097        public static final int FINAL        = 1<<4;
098        public static final int SYNCHRONIZED = 1<<5;
099        public static final int VOLATILE     = 1<<6;
100        public static final int TRANSIENT    = 1<<7;
101        public static final int NATIVE       = 1<<8;
102        public static final int INTERFACE    = 1<<9;
103        public static final int ABSTRACT     = 1<<10;
104        public static final int STRICTFP     = 1<<11;
105    
106        /* Flag that marks a symbol synthetic, added in classfile v49.0. */
107        public static final int SYNTHETIC    = 1<<12;
108    
109        /** Flag that marks attribute interfaces, added in classfile v49.0. */
110        public static final int ANNOTATION   = 1<<13;
111    
112        /** An enumeration type or an enumeration constant, added in
113         *  classfile v49.0. */
114        public static final int ENUM         = 1<<14;
115    
116        public static final int SEPARABLE  = 1<<15; 
117          
118        public static final int StandardFlags = 0x0fff | SEPARABLE;
119    
120        // Because the following access flags are overloaded with other
121        // bit positions, we translate them when reading and writing class
122        // files into unique bits positions: ACC_SYNTHETIC <-> SYNTHETIC,
123        // for example.
124        public static final int ACC_SUPER    = 0x0020;
125        public static final int ACC_BRIDGE   = 0x0040;
126        public static final int ACC_VARARGS  = 0x0080;
127    
128        /*****************************************
129         * Internal compiler flags (no bits in the lower 16).
130         *****************************************/
131    
132        /** Flag is set if symbol is deprecated.
133         */
134        public static final int DEPRECATED   = 1<<17;
135    
136        /** Flag is set for a variable symbol if the variable's definition
137         *  has an initializer part.
138         */
139        public static final int HASINIT          = 1<<18;
140    
141        /** Flag is set for compiler-generated anonymous method symbols
142         *  that `own' an initializer block.
143         */
144        public static final int BLOCK            = 1<<20;
145    
146        /** Flag is set for compiler-generated abstract methods that implement
147         *  an interface method (Miranda methods).
148         */
149        public static final int IPROXY           = 1<<21;
150    
151        /** Flag is set for nested classes that do not access instance members
152         *  or `this' of an outer class and therefore don't need to be passed
153         *  a this$n reference.  This flag is currently set only for anonymous
154         *  classes in superclass constructor calls and only for pre 1.4 targets.
155         *  todo: use this flag for optimizing away this$n parameters in
156         *  other cases.
157         */
158        public static final int NOOUTERTHIS  = 1<<22;
159    
160        /** Flag is set for package symbols if a package has a member or
161         *  directory and therefore exists.
162         */
163        public static final int EXISTS           = 1<<23;
164    
165        /** Flag is set for compiler-generated compound classes
166         *  representing multiple variable bounds
167         */
168        public static final int COMPOUND     = 1<<24;
169    
170        /** Flag is set for class symbols if a class file was found for this class.
171         */
172        public static final int CLASS_SEEN   = 1<<25;
173    
174        /** Flag is set for class symbols if a source file was found for this
175         *  class.
176         */
177        public static final int SOURCE_SEEN  = 1<<26;
178    
179        /* State flags (are reset during compilation).
180         */
181    
182        /** Flag for class symbols is set and later re-set as a lock in
183         *  Enter to detect cycles in the superclass/superinterface
184         *  relations.  Similarly for constructor call cycle detection in
185         *  Attr.
186         */
187        public static final int LOCKED           = 1<<27;
188    
189        /** Flag for class symbols is set and later re-set to indicate that a class
190         *  has been entered but has not yet been attributed.
191         */
192        public static final int UNATTRIBUTED = 1<<28;
193    
194        /** Flag for synthesized default constructors of anonymous classes.
195         */
196        public static final int ANONCONSTR   = 1<<29;
197    
198        /** Flag for class symbols to indicate it has been checked and found
199         *  acyclic.
200         */
201        public static final int ACYCLIC          = 1<<30;
202    
203        /** Flag that marks bridge methods.
204         */
205        public static final long BRIDGE          = 1L<<31;
206    
207        /** Flag that marks formal parameters.
208         */
209        public static final long PARAMETER   = 1L<<33;
210    
211        /** Flag that marks varargs methods.
212         */
213        public static final long VARARGS   = 1L<<34;
214    
215        /** Flag for annotation type symbols to indicate it has been
216         *  checked and found acyclic.
217         */
218        public static final long ACYCLIC_ANN      = 1L<<35;
219    
220        /** Flag that marks a generated default constructor.
221         */
222        public static final long GENERATEDCONSTR   = 1L<<36;
223    
224        /** Flag that marks a hypothetical method that need not really be
225         *  generated in the binary, but is present in the symbol table to
226         *  simplify checking for erasure clashes.
227         */
228        public static final long HYPOTHETICAL   = 1L<<37;
229    
230        /**
231         * Flag that marks a Sun proprietary class.
232         */
233        public static final long PROPRIETARY = 1L<<38;
234    
235        /** Modifier masks.
236         */
237        public static final int
238            AccessFlags           = PUBLIC | PROTECTED | PRIVATE,
239            LocalClassFlags       = FINAL | ABSTRACT | STRICTFP | ENUM | SYNTHETIC,
240            MemberClassFlags      = LocalClassFlags | INTERFACE | AccessFlags,
241            ClassFlags            = LocalClassFlags | INTERFACE | PUBLIC | ANNOTATION,
242            InterfaceVarFlags     = FINAL | STATIC | PUBLIC,
243            VarFlags              = AccessFlags | FINAL | STATIC |
244                                    VOLATILE | TRANSIENT | ENUM,
245            ConstructorFlags      = AccessFlags | SEPARABLE,
246            AllowedInterfaceMethodFlags   = ABSTRACT | PUBLIC | SEPARABLE,
247            ImplicitInterfaceMethodFlags  = ABSTRACT | PUBLIC,
248            MethodFlags           = AccessFlags | ABSTRACT | STATIC | NATIVE |
249                                    SYNCHRONIZED | FINAL | STRICTFP | SEPARABLE;
250        public static final long
251            LocalVarFlags         = FINAL | PARAMETER;
252    
253        public static Set<Modifier> asModifierSet(long flags) {
254            Set<Modifier> modifiers = modifierSets.get(flags);
255            if (modifiers == null) {
256                modifiers = java.util.EnumSet.noneOf(Modifier.class);
257                if (0 != (flags & PUBLIC))    modifiers.add(Modifier.PUBLIC);
258                if (0 != (flags & PROTECTED)) modifiers.add(Modifier.PROTECTED);
259                if (0 != (flags & PRIVATE))   modifiers.add(Modifier.PRIVATE);
260                if (0 != (flags & ABSTRACT))  modifiers.add(Modifier.ABSTRACT);
261                if (0 != (flags & STATIC))    modifiers.add(Modifier.STATIC);
262                if (0 != (flags & FINAL))     modifiers.add(Modifier.FINAL);
263                if (0 != (flags & TRANSIENT)) modifiers.add(Modifier.TRANSIENT);
264                if (0 != (flags & VOLATILE))  modifiers.add(Modifier.VOLATILE);
265                if (0 != (flags & SYNCHRONIZED))
266                                              modifiers.add(Modifier.SYNCHRONIZED);
267                if (0 != (flags & NATIVE))    modifiers.add(Modifier.NATIVE);
268                if (0 != (flags & STRICTFP))  modifiers.add(Modifier.STRICTFP);
269                if (0 != (flags & SEPARABLE)) modifiers.add(Modifier.SEPARABLE);
270                modifiers = Collections.unmodifiableSet(modifiers);
271                modifierSets.put(flags, modifiers);
272            }
273            return modifiers;
274        }
275    
276        // Cache of modifier sets.
277        private static Map<Long, Set<Modifier>> modifierSets =
278            new java.util.concurrent.ConcurrentHashMap<Long, Set<Modifier>>(64);
279    
280        public static boolean isStatic(Symbol symbol) {
281            return (symbol.flags() & STATIC) != 0;
282        }
283    
284        public static boolean isEnum(Symbol symbol) {
285            return (symbol.flags() & ENUM) != 0;
286        }
287    
288        public static boolean isConstant(Symbol.VarSymbol symbol) {
289            return symbol.getConstValue() != null;
290        }
291    
292        public enum Flag {
293    
294            PUBLIC("public"),
295            PRIVATE("private"),
296            PROTECTED("protected"),
297            STATIC("static"),
298            FINAL("final"),
299            SYNCHRONIZED("synchronized"),
300            VOLATILE("volatile"),
301            TRANSIENT("transient"),
302            NATIVE("native"),
303            INTERFACE("interface"),
304            ABSTRACT("abstract"),
305            STRICTFP("strictfp"),
306            BRIDGE("bridge"),
307            SYNTHETIC("synthetic"),
308            DEPRECATED("deprecated"),
309            HASINIT("hasinit"),
310            ENUM("enum"),
311            IPROXY("iproxy"),
312            NOOUTERTHIS("noouterthis"),
313            EXISTS("exists"),
314            COMPOUND("compound"),
315            CLASS_SEEN("class_seen"),
316            SOURCE_SEEN("source_seen"),
317            LOCKED("locked"),
318            UNATTRIBUTED("unattributed"),
319            ANONCONSTR("anonconstr"),
320            ACYCLIC("acyclic"),
321            PARAMETER("parameter"),
322            VARARGS("varargs"),
323            PACKAGE("package"),
324            SEPARABLE("separable");
325    
326            String name;
327    
328            Flag(String name) {
329                this.name = name;
330            }
331    
332            public String toString() {
333                return name;
334            }
335        }
336    }