summaryrefslogblamecommitdiff
path: root/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
blob: 1f1a41055c04d05c0a4a00c37475a4a7bab5eac9 (plain) (tree)
1
2
3
4
5
6
7
8
9
                            
                                


                          
 


                       
 
                                    

                                    
                                                

                                                         
                              
 




                                                       
                                

                    
 

                             
 





                                                                                          
                                                                                      
                                                                                                    
                                                                                            
                                                                             
                                                                            
                                                 


                                                      




                                                                              



                                                                              
                                                     

                                                     
                                                                                         
     
 
                                     
                                                   



                                                                           
     






                                                                               
                  



                                                                 
               
                                                                 
     
  
                                          
                        
                                           
                              
            
                       
                                                  
     

                        
         

                                  

                  

                                                         
     
             
               

   
                                                          
 
                           
                          
                            
                                                           

                                                                              

                                        


                                                
                                                           


                                                               
                                                                            


                      
                                 
                                            
                                               

                                                   
               
                                 
                         
              
                                            
                                                  
                                
                                                  
                      

                                                                              
                      
                                                 
                      
                  
                   
                                  



         
                                                                                  
                                     

                                                          
                         
                                 
                                                                    
                                                                    
                            



          
                                                                                               
                                             
                                                          
                                        




                                                              
                                              

                                                          
                      
                                 
                                                                     
                                                         

                                                                     
            
                                     
                         



       




                                                                              
                                                                   


                                            
                                                                    

                                                                       
                                               



                                                                           
       


                                                                
                      
                                 



                                                               
                                                                 

                                                                                                                          
                                                                         

                                                                    


                                                                   
                                                                     


                                                                       
                
                                               
                                                                                                 
                                                                             
                                                                       
                            
                                                                                                            

                                                                                     





                                                                                                 
                                                      
             
                                                            
                                                                                                                                     

           
                                                                                                      




                         






                                                                            
                                                          
                                                      
                      
                                 

                                                                           

                                                                                   
                                                                 

                                                                                  

                                    

                                                 

           
                       


       
 







                                                           
                          
                                 
                                                                     
                                                         
                                   
                                   

                           

                                                                                                   
                                                                                 
                                                     

                             
         
                              

                                     


       
 



                                                        
 
                                           
                                                                     
 
                                             

                                                          
                          
                                 
                                                      
                                 
                                                                     
                                  
                                          
                                
                                            
                               
                                           
                                 
                                             
                                
                                                 
                   
                              
         
                             
       


                                               
                                           
       


                                                              
                                           
                                                                                           

                                                                    
                                         
                                                                                                

   






                                                                                 





                                                                              





                              
 
                                                   








                                                                             
                                              
                                                              
                                        





                                                                                                                               
 

                                   
                    
                            
                                            
                                         

                                             
                                                                                               


















                                                                                                        

                                                                                                       

                              
                                                                                         
                                                 

                            
                                                                    
                                                               
 
                                  
                                                      
                          
     
                     

                            
                   

                                     
                                            
                                   
                                
       



                                            


                                                          

                                  
                                                
                                   
                                   
                                                  

                                                              
                                       
         
                                                                     
                             
                                            
                                               
                                                    
         

                                       

   












                                                                          
                    
                            
                                          

                                                                
                                  
            

                                          
                                
                                                   
                                                                                           


                                   


     
                     
                                  
                                          
                                                         
                                          
                                  


                                    

                                          
                                                                 


                                            

                                                                              

                                    
                                              
                                                                                         
                                                                    
                                                                             

                                                                                                                    
                         
                        
               
                                                     
           
                         

                                     


                                                
                                   
       


     

                                                                             

                                                          

                                    
                                                               
                                    







                                                                                                                          
                                 



                                              
                                                         

                        



                              
                                                       
                       
                                                     

                               
                                                                       
                                      









                                                       
                   

















                                                              





                                                                            
                       
                                                                                       
                                               
                                                                        

                             
                                                      
                   
                 











                                                                                                                  
               

                                       
                
           
 

                                                                              
                                                                

                                     
                                                                                
                                        
                                                           

                     

                         
                                                                   






                                                                                              
                   

                                                                                         
                                                 
                                     
                                                              
           
                    
                                                                    
                       

                     
                                      
                                                                                 
                   
                                            
                    










                                                                              
       
                                                                                
     
 
                              
                                             
                            
                         
                
                       
                                 
                                               
                                                        
                                         
                                     
                       
       





                                                 
                 
     


                                                    
             
                                        
                                
            

                                            
                             
                                                                                 
         
                                                        
       

                                
 


                                                                                                
 
                                                   
                                                      
                                                                       
                              


                      
                          

                                              
                      
                                 
                                        
                                                       
                                             
                                
                                                               
                                                                               
                          
                
                            
                                 
                                

                              
                             

                                  

                                                                                              

                                     

                                               
                                                       
                                                                             
                                      
                                                                                    
                          
                             

                             
                                


                                                                
                                                                                          
                                         
                                                                                                  
                          
                                                                                      
                                         












                                                                                           



                                                



                                                                   
                                                                                   

                                                                                     



                          
 
                                                    
                                  
                             
                 
                          
                                                                         

                                                                   
                                                        
                          
                                                              
                          
                                     
                                           
                                                                       
                                  
                                            
                          
                                                        

                                  
                                 



                                          
                                               
                              
                                                        

       

                                                                  
                    
       


                                                                            
                                                             


                                            
                             

                                                
         
       
                        
                                                                 







                                                                                               
 













                                                                           


                                                              
                                    
                             
                              
                                            
                             

                                    
         

     



                                                 
 



                                                                                   





                                                                                                          

                                           

                                                                                                                
                                                                       


                                         
 









                                                                          
       

     
                                                

                                                              
                                                                                           
                                                      

                                                                                          
       

     
 












                                                                                       
                                 
                       




                                


                                      

                             
                                                

                                         



                                              



                                                                                    
           

                          

       
                 

   































                                                                                              








                                                                                       

                                              



                                                                                                       






                                                                                             


                                                                                                                                             




                                                          
       


                               
                                                                                                 

                    
                                         



       







                                                                                     
                        
                               
                                  
                                     


     
                     
                                 
                                    



                                  





                            
                                              
                                           
 
                                             
                                                     
 
                                                                  
                



                                               
                                                                               
                          
                                      
                       

                                              
                                              
                                          
                           
                                       
                        
                                            

                                        
              
   
 
                                                          
                                                                                  



                                                                              
   






                                                       
 
/* NSC -- new Scala compiler
 * Copyright 2005-2010 LAMP/EPFL
 * @author  Martin Odersky
 */
// $Id$

package scala.tools.nsc
package symtab
package classfile

import java.io.{ File, IOException }
import java.lang.Integer.toHexString

import scala.collection.immutable.{Map, ListMap}
import scala.collection.mutable.{ListBuffer, ArrayBuffer}
import scala.tools.nsc.io.AbstractFile
import scala.annotation.switch

/** This abstract class implements a class file parser.
 *
 *  @author Martin Odersky
 *  @version 1.0
 */
abstract class ClassfileParser {
  val global: Global
  import global._

  import ClassfileConstants._
  import Flags._

  protected var in: AbstractFileReader = _  // the class file reader
  protected var clazz: Symbol = _           // the class symbol containing dynamic members
  protected var staticModule: Symbol = _    // the module symbol containing static members
  protected var instanceDefs: Scope = _     // the scope of all instance definitions
  protected var staticDefs: Scope = _       // the scope of all static definitions
  protected var pool: ConstantPool = _      // the classfile's constant pool
  protected var isScala: Boolean = _        // does class file describe a scala class?
  protected var isScalaRaw: Boolean = _     // this class file is a scala class with no pickled info
  protected var hasMeta: Boolean = _        // does class file contain jaco meta attribute?s
  protected var busy: Option[Symbol] = None // lock to detect recursive reads
  private var   externalName: Name = _      // JVM name of the current class
  protected var classTParams = Map[Name,Symbol]()
  protected var srcfile0 : Option[AbstractFile] = None

  def srcfile = srcfile0

  private object metaParser extends MetaParser {
    val global: ClassfileParser.this.global.type = ClassfileParser.this.global
  }

  private object unpickler extends UnPickler {
    val global: ClassfileParser.this.global.type = ClassfileParser.this.global
  }

  def parse(file: AbstractFile, root: Symbol) = try {
    def handleMissing(e: MissingRequirementError) = {
      if (settings.debug.value) e.printStackTrace
      throw new IOException("Missing dependency '" + e.req + "', required by " + in.file)
    }

    def handleError(e: Exception) = {
      if (settings.debug.value) e.printStackTrace()
      throw new IOException("class file '" + in.file + "' is broken\n(" + {
        if (e.getMessage() != null) e.getMessage()
        else e.getClass.toString
      } + ")")
    }
    assert(!busy.isDefined, {
      val (s1, s2) = (busy.get, root)
      if (s1 eq s2) "unsatisfiable cyclic dependency in '%s'".format(s1)
      else "illegal class file dependency between '%s' and '%s'".format(s1, s2)
    })

    busy = Some(root)
    /*root match {
      case cs: ClassSymbol =>
        cs.classFile = file
      case ms: ModuleSymbol =>
        ms.moduleClass.asInstanceOf[ClassSymbol].classFile = file
      case _ =>
        println("Skipping class: " + root + ": " + root.getClass)
    }
*/
    this.in = new AbstractFileReader(file)
    if (root.isModule) {
      this.clazz = root.linkedClassOfModule
      this.staticModule = root
    } else {
      this.clazz = root
      this.staticModule = root.linkedModuleOfClass
    }
    this.isScala = false
    this.hasMeta = false
    try {
      parseHeader
      this.pool = new ConstantPool
      parseClass()
    } catch {
      case e: MissingRequirementError => handleMissing(e)
      case e: RuntimeException        => handleError(e)
    }
  } finally {
    busy = None
  }

  protected def statics: Symbol = staticModule.moduleClass

  private def parseHeader {
    val magic = in.nextInt
    if (magic != JAVA_MAGIC)
      throw new IOException("class file '" + in.file + "' "
                            + "has wrong magic number 0x" + toHexString(magic)
                            + ", should be 0x" + toHexString(JAVA_MAGIC))
    val minorVersion = in.nextChar.toInt
    val majorVersion = in.nextChar.toInt
    if ((majorVersion < JAVA_MAJOR_VERSION) ||
        ((majorVersion == JAVA_MAJOR_VERSION) &&
         (minorVersion < JAVA_MINOR_VERSION)))
      throw new IOException("class file '" + in.file + "' "
                            + "has unknown version "
                            + majorVersion + "." + minorVersion
                            + ", should be at least "
                            + JAVA_MAJOR_VERSION + "." + JAVA_MINOR_VERSION)
  }

  class ConstantPool {
    private val len = in.nextChar
    private val starts = new Array[Int](len)
    private val values = new Array[AnyRef](len)
    private val internalized = new Array[Name](len)

    { var i = 1
      while (i < starts.length) {
        starts(i) = in.bp
        i += 1
        (in.nextByte.toInt: @switch) match {
          case CONSTANT_UTF8 | CONSTANT_UNICODE =>
            in.skip(in.nextChar)
          case CONSTANT_CLASS | CONSTANT_STRING =>
            in.skip(2)
          case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF
             | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT =>
            in.skip(4)
          case CONSTANT_LONG | CONSTANT_DOUBLE =>
            in.skip(8)
            i += 1
          case _ =>
            errorBadTag(in.bp - 1)
        }
      }
    }

    /** Return the name found at given index. The returned name is a term name. */
    def getName(index: Int): Name = {
      if (index <= 0 || len <= index) errorBadIndex(index)
      var name = values(index).asInstanceOf[Name]
      if (name eq null) {
        val start = starts(index)
        if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start)
        name = newTermName(in.buf, start + 3, in.getChar(start + 1))
        values(index) = name
      }
      name
    }

    /** Return the name found at given index in the constant pool, with '/' replaced by '.'. */
    def getExternalName(index: Int): Name = {
      if (index <= 0 || len <= index) errorBadIndex(index)
      if (internalized(index) eq null) {
        internalized(index) = getName(index).replace('/', '.')
      }
      internalized(index)
    }

    def getClassSymbol(index: Int): Symbol = {
      if (index <= 0 || len <= index) errorBadIndex(index)
      var c = values(index).asInstanceOf[Symbol]
      if (c eq null) {
        val start = starts(index)
        if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
        val name = getExternalName(in.getChar(start + 1))
        if (name.endsWith("$"))
          c = definitions.getModule(name.subName(0, name.length - 1))
        else
          c = classNameToSymbol(name)
        values(index) = c
      }
      c
    }

    /** Return the external name of the class info structure found at 'index'.
     *  Use 'getClassSymbol' if the class is sure to be a top-level class.
     */
    def getClassName(index: Int): Name = {
      val start = starts(index)
      if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
      getExternalName(in.getChar(start + 1))
    }

    /** Return the symbol of the class member at <code>index</code>.
     *  The following special cases exist:
     *   - If the member refers to special MODULE$ static field, return
     *  the symbol of the corresponding module.
     *   - If the member is a field, and is not found with the given name,
     *     another try is made by appending nme.LOCAL_SUFFIX
     *   - If no symbol is found in the right tpe, a new try is made in the
     *     companion class, in case the owner is an implementation class.
     */
    def getMemberSymbol(index: Int, static: Boolean): Symbol = {
      if (index <= 0 || len <= index) errorBadIndex(index)
      var f = values(index).asInstanceOf[Symbol]
      if (f eq null) {
        val start = starts(index)
        val first = in.buf(start).toInt
        if (first != CONSTANT_FIELDREF &&
            first != CONSTANT_METHODREF &&
            first != CONSTANT_INTFMETHODREF) errorBadTag(start)
        val ownerTpe = getClassOrArrayType(in.getChar(start + 1))
        if (settings.debug.value)
          log("getMemberSymbol(static: " + static + "): owner type: " + ownerTpe + " " + ownerTpe.typeSymbol.originalName)
        val (name, tpe) = getNameAndType(in.getChar(start + 3), ownerTpe)
        if (settings.debug.value)
          log("getMemberSymbol: name and tpe: " + name + ": " + tpe)
        if (name == nme.MODULE_INSTANCE_FIELD) {
          val index = in.getChar(start + 1)
          val name = getExternalName(in.getChar(starts(index) + 1))
          //assert(name.endsWith("$"), "Not a module class: " + name)
          f = forceMangledName(name.subName(0, name.length - 1), true)
          if (f == NoSymbol)
            f = definitions.getModule(name.subName(0, name.length - 1))
        } else {
          val origName = nme.originalName(name)
          val owner = if (static) ownerTpe.typeSymbol.linkedClassOfClass else ownerTpe.typeSymbol
//          println("\t" + owner.info.member(name).tpe.widen + " =:= " + tpe)
          f = owner.info.member(origName).suchThat(_.tpe.widen =:= tpe)
          if (f == NoSymbol)
            f = owner.info.member(newTermName(origName.toString + nme.LOCAL_SUFFIX)).suchThat(_.tpe =:= tpe)
          if (f == NoSymbol) {
            // if it's an impl class, try to find it's static member inside the class
            if (ownerTpe.typeSymbol.isImplClass)
              f = ownerTpe.member(origName).suchThat(_.tpe =:= tpe)
            else {
              log("Couldn't find " + name + ": " + tpe + " inside: \n" + ownerTpe)
              f = if (tpe.isInstanceOf[MethodType]) owner.newMethod(owner.pos, name).setInfo(tpe)
                  else owner.newValue(owner.pos, name).setInfo(tpe).setFlag(MUTABLE)
              log("created fake member " + f.fullName)
            }
//            println("\townerTpe.decls: " + ownerTpe.decls)
//            println("Looking for: " + name + ": " + tpe + " inside: " + ownerTpe.typeSymbol + "\n\tand found: " + ownerTpe.members)
          }
        }
        assert(f != NoSymbol, "could not find " + name + ": " + tpe + "inside: \n" + ownerTpe.members)
        values(index) = f
      }
      f
    }

    /** Return a name and a type at the given index. If the type is a method
     *  type, a dummy symbol is created in 'ownerTpe', which is used as the
     *  owner of its value parameters. This might lead to inconsistencies,
     *  if a symbol of the given name already exists, and has a different
     *  type.
     */
    private def getNameAndType(index: Int, ownerTpe: Type): (Name, Type) = {
      if (index <= 0 || len <= index) errorBadIndex(index)
      var p = values(index).asInstanceOf[(Name, Type)]
      if (p eq null) {
        val start = starts(index)
        if (in.buf(start).toInt != CONSTANT_NAMEANDTYPE) errorBadTag(start)
        val name = getName(in.getChar(start + 1).toInt)
        // create a dummy symbol for method types
        val dummySym = ownerTpe.typeSymbol.newMethod(ownerTpe.typeSymbol.pos, name)
        var tpe  = getType(dummySym, in.getChar(start + 3).toInt)

        // fix the return type, which is blindly set to the class currently parsed
        if (name == nme.CONSTRUCTOR)
          tpe match {
            case MethodType(formals, restpe) =>
              tpe = MethodType(formals, ownerTpe)
          }

        p = (name, tpe)
      }
      p
    }

    /** Return the type of a class constant entry. Since
     *  arrays are considered to be class types, they might
     *  appear as entries in 'newarray' or 'cast' opcodes.
     */
    def getClassOrArrayType(index: Int): Type = {
      if (index <= 0 || len <= index) errorBadIndex(index)
      val value = values(index)
      var c: Type = null
      if (value eq null) {
        val start = starts(index)
        if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
        val name = getExternalName(in.getChar(start + 1))
        if (name(0) == ARRAY_TAG) {
          c = sigToType(null, name)
          values(index) = c
        } else {
          val sym = classNameToSymbol(name)
                  /*if (name.endsWith("$")) definitions.getModule(name.subName(0, name.length - 1))
                    else if (name.endsWith("$class")) definitions.getModule(name)
                    else definitions.getClass(name)*/
          values(index) = sym
          c = sym.tpe
        }
      } else c = value match {
          case tp: Type => tp
          case cls: Symbol => cls.tpe
      }
      c
    }

    def getType(index: Int): Type = getType(null, index)

    def getType(sym: Symbol, index: Int): Type =
      sigToType(sym, getExternalName(index))

    def getSuperClass(index: Int): Symbol =
      if (index == 0) definitions.AnyClass else getClassSymbol(index)

    def getConstant(index: Int): Constant = {
      if (index <= 0 || len <= index) errorBadIndex(index)
      var value = values(index)
      if (value eq null) {
        val start = starts(index)
        value = (in.buf(start).toInt: @switch) match {
          case CONSTANT_STRING =>
            Constant(getName(in.getChar(start + 1).toInt).toString())
          case CONSTANT_INTEGER =>
            Constant(in.getInt(start + 1))
          case CONSTANT_FLOAT =>
            Constant(in.getFloat(start + 1))
          case CONSTANT_LONG =>
            Constant(in.getLong(start + 1))
          case CONSTANT_DOUBLE =>
            Constant(in.getDouble(start + 1))
          case CONSTANT_CLASS =>
            getClassOrArrayType(index).typeSymbol
          case _ =>
            errorBadTag(start)
        }
        values(index) = value
      }
      value match {
        case  ct: Constant => ct
        case cls: Symbol   => Constant(cls.tpe)
        case arr: Type     => Constant(arr)
      }
    }

    /** Throws an exception signaling a bad constant index. */
    private def errorBadIndex(index: Int) =
      throw new RuntimeException("bad constant pool index: " + index + " at pos: " + in.bp)

    /** Throws an exception signaling a bad tag at given address. */
    private def errorBadTag(start: Int) =
      throw new RuntimeException("bad constant pool tag " + in.buf(start) + " at byte " + start)
  }

  /** Try to force the chain of enclosing classes for the given name. Otherwise
   *  flatten would not lift classes that were not referenced in the source code.
   */
  def forceMangledName(name: Name, module: Boolean): Symbol = {
    val parts = name.toString.split(Array('.', '$'))
    var sym: Symbol = definitions.RootClass
    atPhase(currentRun.flattenPhase.prev) {
      for (part0 <- parts; val part = newTermName(part0)) {
        val sym1 = sym.info.decl(part.encode)//.suchThat(module == _.isModule)
        if (sym1 == NoSymbol)
          sym = sym.info.decl(part.encode.toTypeName)
        else
          sym = sym1
      }
    }
//    println("found: " + sym)
    sym
  }


  /** Return the class symbol of the given name. */
  def classNameToSymbol(name: Name): Symbol = {
    def lookupClass(name: Name) =
      if (name.pos('.') == name.length)
        definitions.getMember(definitions.EmptyPackageClass, name.toTypeName)
      else
        definitions.getClass(name)

    innerClasses.get(name) match {
      case Some(entry) =>
        //println("found inner class " + name)
        val res = innerClasses.classSymbol(entry.externalName)
        //println("\trouted to: " + res)
        res
      case None =>
        //if (name.toString.contains("$")) println("No inner class: " + name + innerClasses + " while parsing " + in.file.name)
        lookupClass(name)
    }
  }

  var sawPrivateConstructor = false

  def parseClass() {
    val jflags = in.nextChar
    val isAnnotation = hasAnnotation(jflags)
    var sflags = transFlags(jflags, true)
    var nameIdx = in.nextChar
    externalName = pool.getClassName(nameIdx)
    val c = if (externalName.toString.indexOf('$') < 0) pool.getClassSymbol(nameIdx) else clazz

    /** Parse parents for Java classes. For Scala, return AnyRef, since the real type will be unpickled.
     *  Updates the read pointer of 'in'. */
    def parseParents: List[Type] = {
      if (isScala) {
        in.nextChar              // skip superclass
        val ifaces = in.nextChar
        in.bp += ifaces * 2     // .. and iface count interfaces
        List(definitions.AnyRefClass.tpe) // dummy superclass, will be replaced by pickled information
      } else {
        val superType = if (isAnnotation) { in.nextChar; definitions.AnnotationClass.tpe }
                        else pool.getSuperClass(in.nextChar).tpe
        val ifaceCount = in.nextChar
        var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe
        if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces
        superType :: ifaces
      }
    }

    if (c != clazz && externalName.toString.indexOf("$") < 0 && (clazz eq NoSymbol) && (c ne NoSymbol))
      clazz = c

    addEnclosingTParams(clazz)
    parseInnerClasses() // also sets the isScala / isScalaRaw / hasMeta flags, see r15956
    // get the class file parser to reuse scopes.
    instanceDefs = new Scope
    staticDefs = new Scope
    val classInfo = ClassInfoType(parseParents, instanceDefs, clazz)
    val staticInfo = ClassInfoType(List(), staticDefs, statics)

    if (!isScala && !isScalaRaw) {
//      println("Entering inner classes for " + clazz)
      enterOwnInnerClasses
    }
    val curbp = in.bp
    skipMembers() // fields
    skipMembers() // methods
    if (!isScala) {
      clazz.setFlag(sflags)
      setPrivateWithin(clazz, jflags)
      setPrivateWithin(staticModule, jflags)
      if (!hasMeta || isScalaRaw) {
        clazz.setInfo(classInfo)
      }
      statics.setInfo(staticInfo)
      staticModule.setInfo(statics.tpe)
      staticModule.setFlag(JAVA)
      staticModule.moduleClass.setFlag(JAVA)
      // attributes now depend on having infos set already
      parseAttributes(clazz, classInfo)

      in.bp = curbp
      val fieldCount = in.nextChar
      for (i <- 0 until fieldCount) parseField()
      sawPrivateConstructor = false
      val methodCount = in.nextChar
      for (i <- 0 until methodCount) parseMethod()
      if (!sawPrivateConstructor &&
          (instanceDefs.lookup(nme.CONSTRUCTOR) == NoSymbol &&
           (sflags & INTERFACE) == 0L))
        {
          //Console.println("adding constructor to " + clazz);//DEBUG
          instanceDefs.enter(
            clazz.newConstructor(NoPosition)
            .setFlag(clazz.flags & ConstrFlags)
            .setInfo(MethodType(List(), clazz.tpe)))
        }
    } else
      parseAttributes(clazz, classInfo)
  }

  /** Add type parameters of enclosing classes */
  def addEnclosingTParams(clazz: Symbol) {
    var sym = clazz.owner
    while (sym.isClass && !sym.isModuleClass) {
//      println("adding tparams of " + sym)
      for (t <- sym.tpe.typeArgs) {
//        println("\tadding " + (t.typeSymbol.name + "->" + t.typeSymbol))
        classTParams = classTParams + (t.typeSymbol.name -> t.typeSymbol)
      }
      sym = sym.owner
    }
  }

  def parseField() {
    val jflags = in.nextChar
    var sflags = transFlags(jflags, false)
    if ((sflags & FINAL) == 0L) sflags = sflags | MUTABLE
    if ((sflags & PRIVATE) != 0L && !global.settings.XO.value) {
      in.skip(4); skipAttributes()
    } else {
      val name = pool.getName(in.nextChar)
      val info = pool.getType(in.nextChar)
      val sym = getOwner(jflags)
        .newValue(NoPosition, name).setFlag(sflags)
      sym.setInfo(if ((jflags & JAVA_ACC_ENUM) == 0) info else ConstantType(Constant(sym)))
      setPrivateWithin(sym, jflags)
      parseAttributes(sym, info)
      getScope(jflags).enter(sym)
    }
  }

  def parseMethod() {
    val jflags = in.nextChar.toInt
    var sflags = transFlags(jflags, false)
    if (isPrivate(jflags) && !global.settings.XO.value) {
      val name = pool.getName(in.nextChar)
      if (name == nme.CONSTRUCTOR)
        sawPrivateConstructor = true
      in.skip(2); skipAttributes()
    } else {
      if ((jflags & JAVA_ACC_BRIDGE) != 0)
        sflags |= BRIDGE
      if ((sflags & PRIVATE) != 0L && global.settings.XO.value) {
        in.skip(4); skipAttributes()
      } else {
        val name = pool.getName(in.nextChar)
        val sym = getOwner(jflags).newMethod(NoPosition, name).setFlag(sflags)
        var info = pool.getType(sym, (in.nextChar))
        if (name == nme.CONSTRUCTOR)
          info match {
            case MethodType(params, restpe) =>
              // if this is a non-static inner class, remove the explicit outer parameter
              val newParams = innerClasses.get(externalName) match {
                case Some(entry) if !isScalaRaw && !isStatic(entry.jflags) =>
                  assert(params.head.tpe.typeSymbol == clazz.owner, params.head.tpe.typeSymbol + ": " + clazz.owner)
                  params.tail
                case _ =>
                  params
              }
              info = MethodType(newParams, clazz.tpe)
          }
        sym.setInfo(info)
        setPrivateWithin(sym, jflags)
        parseAttributes(sym, info)
        if ((jflags & JAVA_ACC_VARARGS) != 0) {
          sym.setInfo(arrayToRepeated(sym.info))
        }
        getScope(jflags).enter(sym)
      }
    }
  }

  /** Convert array parameters denoting a repeated parameter of a Java method
   *  to JavaRepeatedParamClass types.
   */
  private def arrayToRepeated(tp: Type): Type = tp match {
    case MethodType(params, rtpe) =>
      val formals = tp.paramTypes
      assert(formals.last.typeSymbol == definitions.ArrayClass)
      val method = params.last.owner
      val elemtp = formals.last.typeArgs.head match {
        case RefinedType(List(t1, t2), _) if (t1.typeSymbol.isAbstractType && t2.typeSymbol == definitions.ObjectClass) =>
          t1 // drop intersection with Object for abstract types in varargs. UnCurry can handle them.
        case t =>
          t
      }
      val newParams = method.newSyntheticValueParams(
        formals.init ::: List(appliedType(definitions.JavaRepeatedParamClass.typeConstructor, List(elemtp))))
      MethodType(newParams, rtpe)
    case PolyType(tparams, rtpe) =>
      PolyType(tparams, arrayToRepeated(rtpe))
  }

  private def sigToType(sym: Symbol, sig: Name): Type = {
    var index = 0
    val end = sig.length
    def accept(ch: Char) {
      assert(sig(index) == ch)
      index += 1
    }
    def subName(isDelimiter: Char => Boolean): Name = {
      val start = index
      while (!isDelimiter(sig(index))) { index += 1 }
      sig.subName(start, index)
    }
    def sig2type(tparams: Map[Name,Symbol], skiptvs: Boolean): Type = {
      val tag = sig(index); index += 1
      tag match {
        case BYTE_TAG   => definitions.ByteClass.tpe
        case CHAR_TAG   => definitions.CharClass.tpe
        case DOUBLE_TAG => definitions.DoubleClass.tpe
        case FLOAT_TAG  => definitions.FloatClass.tpe
        case INT_TAG    => definitions.IntClass.tpe
        case LONG_TAG   => definitions.LongClass.tpe
        case SHORT_TAG  => definitions.ShortClass.tpe
        case VOID_TAG   => definitions.UnitClass.tpe
        case BOOL_TAG   => definitions.BooleanClass.tpe
        case 'L' =>
          def processInner(tp: Type): Type = tp match {
            case TypeRef(pre, sym, args) if (!sym.isStatic) =>
              TypeRef(processInner(pre.widen), sym, args)
            case _ =>
              tp
          }
          def processClassType(tp: Type): Type = tp match {
            case TypeRef(pre, classSym, args) =>
              val existentials = new ListBuffer[Symbol]()
              if (sig(index) == '<') {
                accept('<')
                val xs = new ListBuffer[Type]()
                var i = 0
                while (sig(index) != '>') {
                  sig(index) match {
                    case variance @ ('+' | '-' | '*') =>
                      index += 1
                      val bounds = variance match {
                        case '+' => TypeBounds(definitions.NothingClass.tpe,
                                               sig2type(tparams, skiptvs))
                        case '-' => TypeBounds(sig2type(tparams, skiptvs),
                                               definitions.AnyClass.tpe)
                        case '*' => TypeBounds(definitions.NothingClass.tpe,
                                               definitions.AnyClass.tpe)
                      }
                      val newtparam = sym.newExistential(sym.pos, "?"+i) setInfo bounds
                      existentials += newtparam
                      xs += newtparam.tpe //@M should probably be .tpeHK
                      i += 1
                    case _ =>
                      xs += sig2type(tparams, skiptvs)
                  }
                }
                accept('>')
                assert(xs.length > 0)
                existentialAbstraction(existentials.toList, TypeRef(pre, classSym, xs.toList))
              } else if (classSym.isMonomorphicType) {
                tp
              } else {
                // raw type - existentially quantify all type parameters
                val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams)
                val t = TypeRef(pre, classSym, eparams.map(_.tpe))
                val res = existentialAbstraction(eparams, t)
                if (settings.debug.value && settings.verbose.value) println("raw type " + classSym + " -> " + res)
                res
              }
            case tp =>
              assert(sig(index) != '<')
              tp
          }

          val classSym = classNameToSymbol(subName(c => c == ';' || c == '<'))
          assert(!classSym.hasFlag(OVERLOADED), classSym.alternatives)
          var tpe = processClassType(processInner(classSym.tpe))
          while (sig(index) == '.') {
            accept('.')
            val name = subName(c => c == ';' || c == '<' || c == '.').toTypeName
            val clazz = tpe.member(name)
            tpe = processClassType(processInner(clazz.tpe))
          }
          accept(';')
          tpe
        case ARRAY_TAG =>
          while ('0' <= sig(index) && sig(index) <= '9') index += 1
          var elemtp = sig2type(tparams, skiptvs)
          // make unbounded Array[T] where T is a type variable into Array[T with Object]
          // (this is necessary because such arrays have a representation which is incompatibe
          // with arrays of primitive types.
          if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe))
            elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe))
          appliedType(definitions.ArrayClass.tpe, List(elemtp))
        case '(' =>
          // we need a method symbol. given in line 486 by calling getType(methodSym, ..)
          assert(sym ne null)
          val paramtypes = new ListBuffer[Type]()
          while (sig(index) != ')') {
            paramtypes += objToAny(sig2type(tparams, skiptvs))
          }
          index += 1
          val restype = if (sym != null && sym.isClassConstructor) {
            accept('V')
            clazz.tpe
          } else
            sig2type(tparams, skiptvs)
          JavaMethodType(sym.newSyntheticValueParams(paramtypes.toList), restype)
        case 'T' =>
          val n = subName(';'.==).toTypeName
          index += 1
          if (skiptvs) definitions.AnyClass.tpe
          else tparams(n).typeConstructor
      }
    } // sig2type(tparams, skiptvs)

    def sig2typeBounds(tparams: Map[Name, Symbol], skiptvs: Boolean): Type = {
      val ts = new ListBuffer[Type]
      while (sig(index) == ':') {
        index += 1
        if (sig(index) != ':') // guard against empty class bound
          ts += objToAny(sig2type(tparams, skiptvs))
      }
      TypeBounds(definitions.NothingClass.tpe, intersectionType(ts.toList, sym))
    }

    var tparams = classTParams
    val newTParams = new ListBuffer[Symbol]()
    if (sig(index) == '<') {
      assert(sym != null)
      index += 1
      val start = index
      while (sig(index) != '>') {
        val tpname = subName(':'.==).toTypeName
        val s = sym.newTypeParameter(NoPosition, tpname)
        tparams = tparams + (tpname -> s)
        sig2typeBounds(tparams, true)
        newTParams += s
      }
      index = start
      while (sig(index) != '>') {
        val tpname = subName(':'.==).toTypeName
        val s = tparams(tpname)
        s.setInfo(sig2typeBounds(tparams, false))
      }
      accept('>')
    }
    val ownTypeParams = newTParams.toList
    if (!ownTypeParams.isEmpty)
      sym.setInfo(new TypeParamsType(ownTypeParams))
    val tpe =
      if ((sym eq null) || !sym.isClass)
        sig2type(tparams, false)
      else {
        classTParams = tparams
        val parents = new ListBuffer[Type]()
        while (index < end) {
          parents += sig2type(tparams, false)  // here the variance doesnt'matter
        }
        ClassInfoType(parents.toList, instanceDefs, sym)
      }
    polyType(ownTypeParams, tpe)
  } // sigToType

  class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType {
    override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") }
  }

  def parseAttributes(sym: Symbol, symtype: Type) {
    def convertTo(c: Constant, pt: Type): Constant = {
      if (pt.typeSymbol == definitions.BooleanClass && c.tag == IntTag)
        Constant(c.value != 0)
      else
        c convertTo pt
    }
    def parseAttribute() {
      val attrName = pool.getName(in.nextChar)
      val attrLen = in.nextInt
      attrName match {
        case nme.SignatureATTR =>
          if (!isScala && !isScalaRaw) {
            val sig = pool.getExternalName(in.nextChar)
            val newType = sigToType(sym, sig)
            sym.setInfo(newType)
            if (settings.debug.value && settings.verbose.value)
              println("" + sym + "; signature = " + sig + " type = " + newType)
            hasMeta = true
          } else
            in.skip(attrLen)
        case nme.SyntheticATTR =>
          sym.setFlag(SYNTHETIC)
          in.skip(attrLen)
        case nme.BridgeATTR =>
          sym.setFlag(BRIDGE)
          in.skip(attrLen)
        case nme.DeprecatedATTR =>
          val arg = Literal(Constant("see corresponding Javadoc for more information."))
          sym.addAnnotation(AnnotationInfo(definitions.DeprecatedAttr.tpe, List(arg), List()))
          in.skip(attrLen)
        case nme.ConstantValueATTR =>
          val c = pool.getConstant(in.nextChar)
          val c1 = convertTo(c, symtype)
          if (c1 ne null) sym.setInfo(ConstantType(c1))
          else println("failure to convert " + c + " to " + symtype); //debug
        case nme.ScalaSignatureATTR =>
          unpickler.unpickle(in.buf, in.bp, clazz, staticModule, in.file.toString())
          in.skip(attrLen)
          this.isScala = true
        case nme.ScalaATTR =>
          isScalaRaw = true
        case nme.JacoMetaATTR =>
          val meta = pool.getName(in.nextChar).toString().trim()
          metaParser.parse(meta, sym, symtype)
          this.hasMeta = true
         // Attribute on methods of java annotation classes when that method has a default
        case nme.AnnotationDefaultATTR =>
          sym.addAnnotation(AnnotationInfo(definitions.AnnotationDefaultAttr.tpe, List(), List()))
          in.skip(attrLen)
        // Java annotatinos on classes / methods / fields with RetentionPolicy.RUNTIME
        case nme.RuntimeAnnotationATTR =>
          if (!isScala) {
            // no need to read annotations if isScala, ClassfileAnnotations are pickled
            parseAnnotations(attrLen)
            if (settings.debug.value)
              global.inform("" + sym + "; annotations = " + sym.annotations)
          } else
            in.skip(attrLen)

        // TODO 1: parse runtime visible annotations on parameters
        // case nme.RuntimeParamAnnotationATTR

        // TODO 2: also parse RuntimeInvisibleAnnotation / RuntimeInvisibleParamAnnotation,
        // i.e. java annotations with RetentionPolicy.CLASS?

        case nme.ExceptionsATTR if (!isScala) =>
          parseExceptions(attrLen)

        case nme.SourceFileATTR =>
          val srcfileLeaf = pool.getName(in.nextChar).toString.trim
          val srcpath = sym.enclosingPackage match {
            case NoSymbol => srcfileLeaf
            case pkg => pkg.fullName(File.separatorChar)+File.separator+srcfileLeaf
          }
          srcfile0 = settings.outputDirs.srcFilesFor(in.file, srcpath).find(_.exists)
        case _ =>
          in.skip(attrLen)
      }
    }

    def parseAnnotArg: Option[ClassfileAnnotArg] = {
      val tag = in.nextByte.toChar
      val index = in.nextChar
      tag match {
        case STRING_TAG =>
          Some(LiteralAnnotArg(Constant(pool.getName(index).toString())))
        case BOOL_TAG | BYTE_TAG | CHAR_TAG | SHORT_TAG | INT_TAG |
             LONG_TAG | FLOAT_TAG | DOUBLE_TAG =>
          Some(LiteralAnnotArg(pool.getConstant(index)))
        case CLASS_TAG  =>
          Some(LiteralAnnotArg(Constant(pool.getType(index))))
        case ENUM_TAG   =>
          val t = pool.getType(index)
          val n = pool.getName(in.nextChar)
          val s = t.typeSymbol.linkedModuleOfClass.info.decls.lookup(n)
          assert(s != NoSymbol, t)
          Some(LiteralAnnotArg(Constant(s)))
        case ARRAY_TAG  =>
          val arr = new ArrayBuffer[ClassfileAnnotArg]()
          var hasError = false
          for (i <- 0 until index)
            parseAnnotArg match {
              case Some(c) => arr += c
              case None => hasError = true
            }
          if (hasError) None
          else Some(ArrayAnnotArg(arr.toArray))
        case ANNOTATION_TAG =>
          parseAnnotation(index) map (NestedAnnotArg(_))
      }
    }

    /** Parse and return a single annotation.  If it is malformed,
     *  return None.
     */
    def parseAnnotation(attrNameIndex: Char): Option[AnnotationInfo] = try {
      val attrType = pool.getType(attrNameIndex)
      val nargs = in.nextChar
      val nvpairs = new ListBuffer[(Name, ClassfileAnnotArg)]
      var hasError = false
      for (i <- 0 until nargs) {
        val name = pool.getName(in.nextChar)
        parseAnnotArg match {
          case Some(c) => nvpairs += ((name, c))
          case None => hasError = true
        }
      }
      if (hasError) None
      else Some(AnnotationInfo(attrType, List(), nvpairs.toList))
    } catch {
      case f: FatalError => throw f // don't eat fatal errors, they mean a class was not found
      case ex: Throwable =>
        if (settings.debug.value)
          global.inform("dropping annotation on " + sym +
                        ", an error occured during parsing (e.g. annotation  class not found)")
        None // ignore malformed annotations ==> t1135
    }

    /**
     * Parse the "Exceptions" attribute which denotes the exceptions
     * thrown by a method.
     */
    def parseExceptions(len: Int) {
      val nClasses = in.nextChar
      for (n <- 0 until nClasses) {
        val cls = pool.getClassSymbol(in.nextChar.toInt)
        sym.addAnnotation(AnnotationInfo(definitions.ThrowsClass.tpe,
                                         Literal(Constant(cls.tpe)) :: Nil,
                                         Nil))
      }
    }

    /** Parse a sequence of annotations and attach them to the
     *  current symbol sym.
     */
    def parseAnnotations(len: Int) {
      val nAttr = in.nextChar
      for (n <- 0 until nAttr)
        parseAnnotation(in.nextChar) match {
          case Some(annot) =>
            sym.addAnnotation(annot)
          case None =>
        }
    }

    // begin parseAttributes
    val attrCount = in.nextChar
    for (i <- 0 until attrCount) parseAttribute()
  }

  /** Enter own inner classes in the right scope. It needs the scopes to be set up,
   *  and implicitly current class' superclasses.
   */
  private def enterOwnInnerClasses {
    def className(name: Name): Name = {
      name.subName(name.lastPos('.') + 1, name.length)
    }

    def enterClassAndModule(entry: InnerClassEntry, completer: global.loaders.SymbolLoader, jflags: Int) {
      val name = entry.originalName
      var sflags = transFlags(jflags, true)

      val innerClass = getOwner(jflags).newClass(NoPosition, name.toTypeName).setInfo(completer).setFlag(sflags)
      val innerModule = getOwner(jflags).newModule(NoPosition, name).setInfo(completer).setFlag(sflags)
      innerModule.moduleClass.setInfo(global.loaders.moduleClassLoader)

      getScope(jflags).enter(innerClass)
      getScope(jflags).enter(innerModule)

      val decls = innerClass.enclosingPackage.info.decls
      val e = decls.lookupEntry(className(entry.externalName))
      if (e ne null) {
        //println("removing " + e)
        decls.unlink(e)
      }
      val e1 = decls.lookupEntry(className(entry.externalName).toTypeName)
      if (e1 ne null) {
        //println("removing " + e1)
        decls.unlink(e1)
      }
    }

    for (entry <- innerClasses.valuesIterator) {
      // create a new class member for immediate inner classes
      if (entry.outerName == externalName) {
        val file = global.classPath.findSourceFile(entry.externalName.toString) getOrElse {
          throw new AssertionError(entry.externalName)
        }
        enterClassAndModule(entry, new global.loaders.ClassfileLoader(file), entry.jflags)
      }
    }
  }

  /** Parse inner classes. Expects in.bp to point to the superclass entry. Restores the
   *  old bp.
   */
  def parseInnerClasses() {
    val oldbp = in.bp
    skipSuperclasses()
    skipMembers() // fields
    skipMembers() // methods
    val attrs = in.nextChar
    for (i <- 0 until attrs) {
      val attrName = pool.getName(in.nextChar)
      val attrLen = in.nextInt
      attrName match {
        case nme.SignatureATTR =>
          if (!isScala)
            hasMeta = true
          in.skip(attrLen)
        case nme.JacoMetaATTR =>
          this.hasMeta = true
          in.skip(attrLen)
        case nme.ScalaSignatureATTR =>
          isScala = true
          in.skip(attrLen)
        case nme.ScalaATTR =>
          isScalaRaw = true
        case nme.InnerClassesATTR if !isScala =>
          val entries = in.nextChar.toInt
          for (i <- 0 until entries) {
            val innerIndex = in.nextChar.toInt
            val outerIndex = in.nextChar.toInt
            val nameIndex = in.nextChar.toInt
            val jflags = in.nextChar.toInt
            if (innerIndex != 0 && outerIndex != 0 && nameIndex != 0) {
              val entry = InnerClassEntry(innerIndex, outerIndex, nameIndex, jflags)
              innerClasses += (pool.getClassName(innerIndex) -> entry)
            }
          }
        case _ =>
          in.skip(attrLen)
      }
    }
    in.bp = oldbp
  }

  /** An entry in the InnerClasses attribute of this class file. */
  case class InnerClassEntry(external: Int, outer: Int, name: Int, jflags: Int) {
    def externalName: Name = pool.getClassName(external)
    def outerName: Name = pool.getClassName(outer)
    def originalName: Name = pool.getName(name)

    override def toString =
      originalName + " in " + outerName + "(" + externalName +")"
  }

  object innerClasses extends collection.mutable.HashMap[Name, InnerClassEntry] {
    /** Return the Symbol of the top level class enclosing 'name', or 'name's symbol
     *  if no entry found for 'name'.
     */
    def topLevelClass(name: Name): Symbol = {
      val tlName = if (isDefinedAt(name)) {
        var entry = this(name)
        while (isDefinedAt(entry.outerName))
          entry = this(entry.outerName)
        entry.outerName
      } else
        name
      classNameToSymbol(tlName)
    }

    /** Return the class symbol for 'externalName'. It looks it up in its outer class.
     *  Forces all outer class symbols to be completed.
     *
     *  If the given name is not an inner class, it returns the symbol found in 'definitions'.
     */
    def classSymbol(externalName: Name): Symbol = {
      /** Return the symbol of `innerName', having the given `externalName'. */
      def innerSymbol(externalName: Name, innerName: Name, static: Boolean): Symbol = {
        def getMember(sym: Symbol, name: Name): Symbol =
          if (static)
            if (sym == clazz) staticDefs.lookup(name)
            else sym.linkedModuleOfClass.info.member(name)
          else
            if (sym == clazz) instanceDefs.lookup(name)
            else sym.info.member(name)

        innerClasses.get(externalName) match {
          case Some(entry) =>
            val outerName =
              if (entry.outerName.endsWith("$")) entry.outerName.subName(0, entry.outerName.length - 1)
              else entry.outerName
            val sym = classSymbol(outerName)
            val s =
              // if loading during initialization of `definitions' typerPhase is not yet set.
              // in that case we simply load the mmeber at the current phase
              if (currentRun.typerPhase != null)
                atPhase(currentRun.typerPhase)(getMember(sym, innerName.toTypeName))
              else
                getMember(sym, innerName.toTypeName)
            assert(s ne NoSymbol, sym + "." + innerName + " linkedModule: " + sym.linkedModuleOfClass + sym.linkedModuleOfClass.info.members)
            s

          case None =>
            val cls = classNameToSymbol(externalName)
            cls
            //if (static) cls.linkedClassOfModule else cls
        }
      }

      get(externalName) match {
        case Some(entry) =>
          val clazz = innerSymbol(entry.externalName, entry.originalName, isStatic(entry.jflags))
          clazz
        case None =>
          classNameToSymbol(externalName)
      }
    }
  }

  class LazyAliasType(alias: Symbol) extends LazyType {
    override def complete(sym: Symbol) {
      alias.initialize
      val tparams1 = cloneSymbols(alias.typeParams)
      sym.setInfo(polyType(tparams1, alias.tpe.substSym(alias.typeParams, tparams1)))
    }
  }

  def skipAttributes() {
    val attrCount = in.nextChar
    for (i <- 0 until attrCount) {
      in.skip(2); in.skip(in.nextInt)
    }
  }

  def skipMembers() {
    val memberCount = in.nextChar
    for (i <- 0 until memberCount) {
      in.skip(6); skipAttributes()
    }
  }

  def skipSuperclasses() {
    in.skip(2) // superclass
    val ifaces = in.nextChar
    in.skip(2 * ifaces)
  }

  protected def getOwner(flags: Int): Symbol =
    if (isStatic(flags)) statics else clazz

  protected def getScope(flags: Int): Scope =
    if (isStatic(flags)) staticDefs else instanceDefs

  protected def transFlags(flags: Int, isClass: Boolean): Long = {
    var res = 0l
    if ((flags & JAVA_ACC_PRIVATE) != 0)
      res = res | PRIVATE
    else if ((flags & JAVA_ACC_PROTECTED) != 0)
      res = res | PROTECTED
    if ((flags & JAVA_ACC_ABSTRACT) != 0 && (flags & JAVA_ACC_ANNOTATION) == 0)
      res = res | DEFERRED
    if ((flags & JAVA_ACC_FINAL) != 0)
      res = res | FINAL
    if (((flags & JAVA_ACC_INTERFACE) != 0) &&
        ((flags & JAVA_ACC_ANNOTATION) == 0))
      res = res | TRAIT | INTERFACE | ABSTRACT
    if ((flags & JAVA_ACC_SYNTHETIC) != 0)
      res = res | SYNTHETIC
    if ((flags & JAVA_ACC_STATIC) != 0)
      res = res | STATIC
    if (isClass && ((res & DEFERRED) != 0L))
        res = res & ~DEFERRED | ABSTRACT

    res | JAVA
  }

  private def setPrivateWithin(sym: Symbol, jflags: Int) {
    if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0)
      // See ticket #1687 for an example of when topLevelClass is NoSymbol: it
      // apparently occurs when processing v45.3 bytecode.
      if (sym.toplevelClass != NoSymbol)
        sym.privateWithin = sym.toplevelClass.owner
  }

  @inline final private def isPrivate(flags: Int) =
    (flags & JAVA_ACC_PRIVATE) != 0
  @inline final private def isStatic(flags: Int) =
    (flags & JAVA_ACC_STATIC) != 0
  @inline final private def hasAnnotation(flags: Int) =
    (flags & JAVA_ACC_ANNOTATION) != 0
}