1 /* 2 * Copyright (c) 1994, 2003, 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 sun.tools.java; 27 28 import java.util.Stack; 29 import java.io.IOException; 30 import sun.tools.tree.Context; 31 //JCOV 32 import java.io.File; 33 //end JCOV 34 35 /** 36 * This class defines the environment for a compilation. 37 * It is used to load classes, resolve class names and 38 * report errors. It is an abstract class, a subclass 39 * must define implementations for some of the functions.<p> 40 * 41 * An environment has a source object associated with it. 42 * This is the thing against which errors are reported, it 43 * is usually a file name, a field or a class.<p> 44 * 45 * Environments can be nested to change the source object.<p> 46 * 47 * WARNING: The contents of this source file are not part of any 48 * supported API. Code that depends on them does so at its own risk: 49 * they are subject to change or removal without notice. 50 * 51 * @author Arthur van Hoff 52 */ 53 54 public class Environment implements Constants { 55 /** 56 * The actual environment to which everything is forwarded. 57 */ 58 Environment env; 59 60 /** 61 * External character encoding name 62 */ 63 String encoding; 64 65 /** 66 * The object that is currently being parsed/compiled. 67 * It is either a file name (String) or a field (MemberDefinition) 68 * or a class (ClassDeclaration or ClassDefinition). 69 */ 70 Object source; 71 72 public Environment(Environment env, Object source) { 73 if (env != null && env.env != null && env.getClass() == this.getClass()) 74 env = env.env; // a small optimization 75 this.env = env; 76 this.source = source; 77 } 78 public Environment() { 79 this(null, null); 80 } 81 82 /** 83 * Tells whether an Identifier refers to a package which should be 84 * exempt from the "exists" check in Imports#resolve(). 85 */ 86 public boolean isExemptPackage(Identifier id) { 87 return env.isExemptPackage(id); 88 } 89 90 /** 91 * Return a class declaration given a fully qualified class name. 92 */ 93 public ClassDeclaration getClassDeclaration(Identifier nm) { 94 return env.getClassDeclaration(nm); 95 } 96 97 /** 98 * Return a class definition given a fully qualified class name. 99 * <p> 100 * Should be called only with 'internal' class names, i.e., the result 101 * of a call to 'resolveName' or a synthetic class name. 102 */ 103 public final ClassDefinition getClassDefinition(Identifier nm) throws ClassNotFound { 104 if (nm.isInner()) { 105 ClassDefinition c = getClassDefinition(nm.getTopName()); 106 Identifier tail = nm.getFlatName(); 107 walkTail: 108 while (tail.isQualified()) { 109 tail = tail.getTail(); 110 Identifier head = tail.getHead(); 111 //System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail); 112 String hname = head.toString(); 113 // If the name is of the form 'ClassName.N$localName', where N is 114 // a number, the field 'N$localName' may not necessarily be a member 115 // of the class named by 'ClassName', but might be a member of some 116 // inaccessible class contained within it. We use 'getLocalClass' 117 // to do the lookup in this case. This is part of a fix for bugid 118 // 4054523 and 4030421. See also 'BatchEnvironment.makeClassDefinition'. 119 // This should also work for anonymous class names of the form 120 // 'ClassName.N'. Note that the '.' qualifications get converted to 121 // '$' characters when determining the external name of the class and 122 // the name of the class file. 123 if (hname.length() > 0 124 && Character.isDigit(hname.charAt(0))) { 125 ClassDefinition localClass = c.getLocalClass(hname); 126 if (localClass != null) { 127 c = localClass; 128 continue walkTail; 129 } 130 } else { 131 for (MemberDefinition f = c.getFirstMatch(head); 132 f != null; f = f.getNextMatch()) { 133 if (f.isInnerClass()) { 134 c = f.getInnerClass(); 135 continue walkTail; 136 } 137 } 138 } 139 throw new ClassNotFound(Identifier.lookupInner(c.getName(), head)); 140 } 141 //System.out.println("FOUND " + c + " FOR " + nm); 142 return c; 143 } 144 return getClassDeclaration(nm).getClassDefinition(this); 145 } 146 147 148 /** 149 * Return a class declaration given a type. Only works for 150 * class types. 151 */ 152 public ClassDeclaration getClassDeclaration(Type t) { 153 return getClassDeclaration(t.getClassName()); 154 } 155 156 /** 157 * Return a class definition given a type. Only works for 158 * class types. 159 */ 160 public final ClassDefinition getClassDefinition(Type t) throws ClassNotFound { 161 return getClassDefinition(t.getClassName()); 162 } 163 164 /** 165 * Check if a class exists (without actually loading it). 166 * (Since inner classes cannot in general be examined without 167 * loading source, this method does not accept inner names.) 168 */ 169 public boolean classExists(Identifier nm) { 170 return env.classExists(nm); 171 } 172 173 public final boolean classExists(Type t) { 174 return !t.isType(TC_CLASS) || classExists(t.getClassName()); 175 } 176 177 /** 178 * Get the package path for a package 179 */ 180 public Package getPackage(Identifier pkg) throws IOException { 181 return env.getPackage(pkg); 182 } 183 184 /** 185 * Load the definition of a class. 186 */ 187 public void loadDefinition(ClassDeclaration c) { 188 env.loadDefinition(c); 189 } 190 191 /** 192 * Return the source of the environment (ie: the thing being compiled/parsed). 193 */ 194 public final Object getSource() { 195 return source; 196 } 197 198 /** 199 * Resolve a type. Make sure that all the classes referred to by 200 * the type have a definition. Report errors. Return true if 201 * the type is well-formed. Presently used for types appearing 202 * in member declarations, which represent named types internally as 203 * qualified identifiers. Type names appearing in local variable 204 * declarations and within expressions are represented as identifier 205 * or field expressions, and are resolved by 'toType', which delegates 206 * handling of the non-inner portion of the name to this method. 207 * <p> 208 * In 'toType', the various stages of qualification are represented by 209 * separate AST nodes. Here, we are given a single identifier which 210 * contains the entire qualification structure. It is not possible in 211 * general to set the error location to the exact position of a component 212 * that is in error, so an error message must refer to the entire qualified 213 * name. An attempt to keep track of the string length of the components of 214 * the name and to offset the location accordingly fails because the initial 215 * prefix of the name may have been rewritten by an earlier call to 216 * 'resolveName'. See 'SourceMember.resolveTypeStructure'. The situation 217 * is actually even worse than this, because only a single location is 218 * passed in for an entire declaration, which may contain many type names. 219 * All error messages are thus poorly localized. These checks should be 220 * done while traversing the parse tree for the type, not the type descriptor. 221 * <p> 222 * DESIGN NOTE: 223 * As far as I can tell, the two-stage resolution of names represented in 224 * string form is an artifact of the late implementation of inner classes 225 * and the use of mangled names internally within the compiler. All 226 * qualified names should have their hiearchical structure made explicit 227 * in the parse tree at the phase at which they are presented for static 228 * semantic checking. This would affect class names appearing in 'extends', 229 * 'implements', and 'throws' clauses, as well as in member declarations. 230 */ 231 public boolean resolve(long where, ClassDefinition c, Type t) { 232 switch (t.getTypeCode()) { 233 case TC_CLASS: { 234 ClassDefinition def; 235 try { 236 Identifier nm = t.getClassName(); 237 if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) { 238 resolve(nm); // elicit complaints about ambiguity 239 } 240 def = getQualifiedClassDefinition(where, nm, c, false); 241 if (!c.canAccess(this, def.getClassDeclaration())) { 242 // Reported error location may be imprecise 243 // if the name is qualified. 244 error(where, "cant.access.class", def); 245 return true; // return false later 246 } 247 def.noteUsedBy(c, where, env); 248 } catch (AmbiguousClass ee) { 249 error(where, "ambig.class", ee.name1, ee.name2); 250 return false; 251 } catch (ClassNotFound e) { 252 // For now, report "class.and.package" only when the code 253 // is going to fail anyway. 254 try { 255 if (e.name.isInner() && 256 getPackage(e.name.getTopName()).exists()) { 257 env.error(where, "class.and.package", 258 e.name.getTopName()); 259 } 260 } catch (IOException ee) { 261 env.error(where, "io.exception", "package check"); 262 } 263 // This error message is also emitted for 'new' expressions. 264 // error(where, "class.not.found", e.name, "declaration"); 265 error(where, "class.not.found.no.context", e.name); 266 return false; 267 } 268 return true; 269 } 270 271 case TC_ARRAY: 272 return resolve(where, c, t.getElementType()); 273 274 case TC_METHOD: 275 boolean ok = resolve(where, c, t.getReturnType()); 276 Type args[] = t.getArgumentTypes(); 277 for (int i = args.length ; i-- > 0 ; ) { 278 ok &= resolve(where, c, args[i]); 279 } 280 return ok; 281 } 282 return true; 283 } 284 285 /** 286 * Given its fully-qualified name, verify that a class is defined and accessible. 287 * Used to check components of qualified names in contexts where a class is expected. 288 * Like 'resolve', but is given a single type name, not a type descriptor. 289 */ 290 public boolean resolveByName(long where, ClassDefinition c, Identifier nm) { 291 return resolveByName(where, c, nm, false); 292 } 293 294 public boolean resolveExtendsByName(long where, ClassDefinition c, Identifier nm) { 295 return resolveByName(where, c, nm, true); 296 } 297 298 private boolean resolveByName(long where, ClassDefinition c, 299 Identifier nm, boolean isExtends) { 300 ClassDefinition def; 301 try { 302 if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) { 303 resolve(nm); // elicit complaints about ambiguity 304 } 305 def = getQualifiedClassDefinition(where, nm, c, isExtends); 306 ClassDeclaration decl = def.getClassDeclaration(); 307 if (!((!isExtends && c.canAccess(this, decl)) 308 || 309 (isExtends && c.extendsCanAccess(this, decl)))) { 310 error(where, "cant.access.class", def); 311 return true; // return false later 312 } 313 } catch (AmbiguousClass ee) { 314 error(where, "ambig.class", ee.name1, ee.name2); 315 return false; 316 } catch (ClassNotFound e) { 317 // For now, report "class.and.package" only when the code 318 // is going to fail anyway. 319 try { 320 if (e.name.isInner() && 321 getPackage(e.name.getTopName()).exists()) { 322 env.error(where, "class.and.package", 323 e.name.getTopName()); 324 } 325 } catch (IOException ee) { 326 env.error(where, "io.exception", "package check"); 327 } 328 error(where, "class.not.found", e.name, "type name"); 329 return false; 330 } 331 return true; 332 } 333 334 /** 335 * Like 'getClassDefinition(env)', but check access on each component. 336 * Currently called only by 'resolve' above. It is doubtful that calls 337 * to 'getClassDefinition(env)' are appropriate now. 338 */ 339 public final ClassDefinition 340 getQualifiedClassDefinition(long where, 341 Identifier nm, 342 ClassDefinition ctxClass, 343 boolean isExtends) throws ClassNotFound { 344 if (nm.isInner()) { 345 ClassDefinition c = getClassDefinition(nm.getTopName()); 346 Identifier tail = nm.getFlatName(); 347 walkTail: 348 while (tail.isQualified()) { 349 tail = tail.getTail(); 350 Identifier head = tail.getHead(); 351 // System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail); 352 String hname = head.toString(); 353 // Handle synthesized names of local and anonymous classes. 354 // See 'getClassDefinition(env)' above. 355 if (hname.length() > 0 356 && Character.isDigit(hname.charAt(0))) { 357 ClassDefinition localClass = c.getLocalClass(hname); 358 if (localClass != null) { 359 c = localClass; 360 continue walkTail; 361 } 362 } else { 363 for (MemberDefinition f = c.getFirstMatch(head); 364 f != null; f = f.getNextMatch()) { 365 if (f.isInnerClass()) { 366 ClassDeclaration rdecl = c.getClassDeclaration(); 367 c = f.getInnerClass(); 368 ClassDeclaration fdecl = c.getClassDeclaration(); 369 // This check is presumably applicable even if the 370 // original source-code name (expanded by 'resolveNames') 371 // was a simple, unqualified name. Hopefully, JLS 2e 372 // will clarify the matter. 373 if ((!isExtends 374 && !ctxClass.canAccess(env, fdecl)) 375 || 376 (isExtends 377 && !ctxClass.extendsCanAccess(env, fdecl))) { 378 // Reported error location is imprecise. 379 env.error(where, "no.type.access", head, rdecl, ctxClass); 380 } 381 // The JLS 6.6.2 restrictions on access to protected members 382 // depend in an essential way upon the syntactic form of the name. 383 // Since the compiler has previously expanded the class names 384 // here into fully-qualified form ('resolveNames'), this check 385 // cannot be performed here. Unfortunately, the original names 386 // are clobbered during 'basicCheck', which is also the phase that 387 // resolves the inheritance structure, required to implement the 388 // access restrictions. Pending a large-scale revision of the 389 // name-resolution machinery, we forgo this check, with the result 390 // that the JLS 6.6.2 restrictions are not enforced for some cases 391 // of qualified access to inner classes. Some qualified names are 392 // resolved elsewhere via a different mechanism, and will be 393 // treated correctly -- see 'FieldExpression.checkCommon'. 394 /*---------------------------------------* 395 if (f.isProtected()) { 396 Type rty = Type.tClass(rdecl.getName()); // hack 397 if (!ctxClass.protectedAccess(env, f, rty)) { 398 // Reported error location is imprecise. 399 env.error(where, "invalid.protected.type.use", 400 head, ctxClass, rty); 401 } 402 } 403 *---------------------------------------*/ 404 continue walkTail; 405 } 406 } 407 } 408 throw new ClassNotFound(Identifier.lookupInner(c.getName(), head)); 409 } 410 //System.out.println("FOUND " + c + " FOR " + nm); 411 return c; 412 } 413 return getClassDeclaration(nm).getClassDefinition(this); 414 } 415 416 /** 417 * Resolve the names within a type, returning the adjusted type. 418 * Adjust class names to reflect scoping. 419 * Do not report errors. 420 * <p> 421 * NOTE: It would be convenient to check for errors here, such as 422 * verifying that each component of a qualified name exists and is 423 * accessible. Why must this be done in a separate phase? 424 * <p> 425 * If the 'synth' argument is true, indicating that the member whose 426 * type is being resolved is synthetic, names are resolved with respect 427 * to the package scope. (Fix for 4097882) 428 */ 429 public Type resolveNames(ClassDefinition c, Type t, boolean synth) { 430 if (tracing) dtEvent("Environment.resolveNames: " + c + ", " + t); 431 switch (t.getTypeCode()) { 432 case TC_CLASS: { 433 Identifier name = t.getClassName(); 434 Identifier rname; 435 if (synth) { 436 rname = resolvePackageQualifiedName(name); 437 } else { 438 rname = c.resolveName(this, name); 439 } 440 if (name != rname) { 441 t = Type.tClass(rname); 442 } 443 break; 444 } 445 446 case TC_ARRAY: 447 t = Type.tArray(resolveNames(c, t.getElementType(), synth)); 448 break; 449 450 case TC_METHOD: { 451 Type ret = t.getReturnType(); 452 Type rret = resolveNames(c, ret, synth); 453 Type args[] = t.getArgumentTypes(); 454 Type rargs[] = new Type[args.length]; 455 boolean changed = (ret != rret); 456 for (int i = args.length ; i-- > 0 ; ) { 457 Type arg = args[i]; 458 Type rarg = resolveNames(c, arg, synth); 459 rargs[i] = rarg; 460 if (arg != rarg) { 461 changed = true; 462 } 463 } 464 if (changed) { 465 t = Type.tMethod(rret, rargs); 466 } 467 break; 468 } 469 } 470 return t; 471 } 472 473 /** 474 * Resolve a class name, using only package and import directives. 475 * Report no errors. 476 * <p> 477 */ 478 public Identifier resolveName(Identifier name) { 479 // This logic is pretty exactly parallel to that of 480 // ClassDefinition.resolveName(). 481 if (name.isQualified()) { 482 // Try to resolve the first identifier component, 483 // because inner class names take precedence over 484 // package prefixes. (Cf. ClassDefinition.resolveName.) 485 Identifier rhead = resolveName(name.getHead()); 486 487 if (rhead.hasAmbigPrefix()) { 488 // The first identifier component refers to an 489 // ambiguous class. Limp on. We throw away the 490 // rest of the classname as it is irrelevant. 491 // (part of solution for 4059855). 492 return rhead; 493 } 494 495 if (!this.classExists(rhead)) { 496 return this.resolvePackageQualifiedName(name); 497 } 498 try { 499 return this.getClassDefinition(rhead). 500 resolveInnerClass(this, name.getTail()); 501 } catch (ClassNotFound ee) { 502 // return partially-resolved name someone else can fail on 503 return Identifier.lookupInner(rhead, name.getTail()); 504 } 505 } 506 try { 507 return resolve(name); 508 } catch (AmbiguousClass ee) { 509 // Don't force a resolution of the name if it is ambiguous. 510 // Forcing the resolution would tack the current package 511 // name onto the front of the class, which would be wrong. 512 // Instead, mark the name as ambiguous and let a later stage 513 // find the error by calling env.resolve(name). 514 // (part of solution for 4059855). 515 516 if (name.hasAmbigPrefix()) { 517 return name; 518 } else { 519 return name.addAmbigPrefix(); 520 } 521 } catch (ClassNotFound ee) { 522 // last chance to make something halfway sensible 523 Imports imports = getImports(); 524 if (imports != null) 525 return imports.forceResolve(this, name); 526 } 527 return name; 528 } 529 530 /** 531 * Discover if name consists of a package prefix, followed by the 532 * name of a class (that actually exists), followed possibly by 533 * some inner class names. If we can't find a class that exists, 534 * return the name unchanged. 535 * <p> 536 * This routine is used after a class name fails to 537 * be resolved by means of imports or inner classes. 538 * However, import processing uses this routine directly, 539 * since import names must be exactly qualified to start with. 540 */ 541 public final Identifier resolvePackageQualifiedName(Identifier name) { 542 Identifier tail = null; 543 for (;;) { 544 if (classExists(name)) { 545 break; 546 } 547 if (!name.isQualified()) { 548 name = (tail == null) ? name : Identifier.lookup(name, tail); 549 tail = null; 550 break; 551 } 552 Identifier nm = name.getName(); 553 tail = (tail == null)? nm: Identifier.lookup(nm, tail); 554 name = name.getQualifier(); 555 } 556 if (tail != null) 557 name = Identifier.lookupInner(name, tail); 558 return name; 559 } 560 561 /** 562 * Resolve a class name, using only package and import directives. 563 */ 564 public Identifier resolve(Identifier nm) throws ClassNotFound { 565 if (env == null) return nm; // a pretty useless no-op 566 return env.resolve(nm); 567 } 568 569 /** 570 * Get the imports used to resolve class names. 571 */ 572 public Imports getImports() { 573 if (env == null) return null; // lame default 574 return env.getImports(); 575 } 576 577 /** 578 * Create a new class. 579 */ 580 public ClassDefinition makeClassDefinition(Environment origEnv, long where, 581 IdentifierToken name, 582 String doc, int modifiers, 583 IdentifierToken superClass, 584 IdentifierToken interfaces[], 585 ClassDefinition outerClass) { 586 if (env == null) return null; // lame default 587 return env.makeClassDefinition(origEnv, where, name, 588 doc, modifiers, 589 superClass, interfaces, outerClass); 590 } 591 592 /** 593 * Create a new field. 594 */ 595 public MemberDefinition makeMemberDefinition(Environment origEnv, long where, 596 ClassDefinition clazz, 597 String doc, int modifiers, 598 Type type, Identifier name, 599 IdentifierToken argNames[], 600 IdentifierToken expIds[], 601 Object value) { 602 if (env == null) return null; // lame default 603 return env.makeMemberDefinition(origEnv, where, clazz, doc, modifiers, 604 type, name, argNames, expIds, value); 605 } 606 607 /** 608 * Returns true if the given method is applicable to the given arguments 609 */ 610 611 public boolean isApplicable(MemberDefinition m, Type args[]) throws ClassNotFound { 612 Type mType = m.getType(); 613 if (!mType.isType(TC_METHOD)) 614 return false; 615 Type mArgs[] = mType.getArgumentTypes(); 616 if (args.length != mArgs.length) 617 return false; 618 for (int i = args.length ; --i >= 0 ;) 619 if (!isMoreSpecific(args[i], mArgs[i])) 620 return false; 621 return true; 622 } 623 624 625 /** 626 * Returns true if "best" is in every argument at least as good as "other" 627 */ 628 public boolean isMoreSpecific(MemberDefinition best, MemberDefinition other) 629 throws ClassNotFound { 630 Type bestType = best.getClassDeclaration().getType(); 631 Type otherType = other.getClassDeclaration().getType(); 632 boolean result = isMoreSpecific(bestType, otherType) 633 && isApplicable(other, best.getType().getArgumentTypes()); 634 // System.out.println("isMoreSpecific: " + best + "/" + other 635 // + " => " + result); 636 return result; 637 } 638 639 /** 640 * Returns true if "from" is a more specific type than "to" 641 */ 642 643 public boolean isMoreSpecific(Type from, Type to) throws ClassNotFound { 644 return implicitCast(from, to); 645 } 646 647 /** 648 * Return true if an implicit cast from this type to 649 * the given type is allowed. 650 */ 651 public boolean implicitCast(Type from, Type to) throws ClassNotFound { 652 if (from == to) 653 return true; 654 655 int toTypeCode = to.getTypeCode(); 656 657 switch(from.getTypeCode()) { 658 case TC_BYTE: 659 if (toTypeCode == TC_SHORT) 660 return true; 661 case TC_SHORT: 662 case TC_CHAR: 663 if (toTypeCode == TC_INT) return true; 664 case TC_INT: 665 if (toTypeCode == TC_LONG) return true; 666 case TC_LONG: 667 if (toTypeCode == TC_FLOAT) return true; 668 case TC_FLOAT: 669 if (toTypeCode == TC_DOUBLE) return true; 670 case TC_DOUBLE: 671 default: 672 return false; 673 674 case TC_NULL: 675 return to.inMask(TM_REFERENCE); 676 677 case TC_ARRAY: 678 if (!to.isType(TC_ARRAY)) { 679 return (to == Type.tObject || to == Type.tCloneable 680 || to == Type.tSerializable); 681 } else { 682 // both are arrays. recurse down both until one isn't an array 683 do { 684 from = from.getElementType(); 685 to = to.getElementType(); 686 } while (from.isType(TC_ARRAY) && to.isType(TC_ARRAY)); 687 if ( from.inMask(TM_ARRAY|TM_CLASS) 688 && to.inMask(TM_ARRAY|TM_CLASS)) { 689 return isMoreSpecific(from, to); 690 } else { 691 return (from.getTypeCode() == to.getTypeCode()); 692 } 693 } 694 695 case TC_CLASS: 696 if (toTypeCode == TC_CLASS) { 697 ClassDefinition fromDef = getClassDefinition(from); 698 ClassDefinition toDef = getClassDefinition(to); 699 return toDef.implementedBy(this, 700 fromDef.getClassDeclaration()); 701 } else { 702 return false; 703 } 704 } 705 } 706 707 708 /** 709 * Return true if an explicit cast from this type to 710 * the given type is allowed. 711 */ 712 public boolean explicitCast(Type from, Type to) throws ClassNotFound { 713 if (implicitCast(from, to)) { 714 return true; 715 } 716 if (from.inMask(TM_NUMBER)) { 717 return to.inMask(TM_NUMBER); 718 } 719 if (from.isType(TC_CLASS) && to.isType(TC_CLASS)) { 720 ClassDefinition fromClass = getClassDefinition(from); 721 ClassDefinition toClass = getClassDefinition(to); 722 if (toClass.isFinal()) { 723 return fromClass.implementedBy(this, 724 toClass.getClassDeclaration()); 725 } 726 if (fromClass.isFinal()) { 727 return toClass.implementedBy(this, 728 fromClass.getClassDeclaration()); 729 } 730 731 // The code here used to omit this case. If both types 732 // involved in a cast are interfaces, then JLS 5.5 requires 733 // that we do a simple test -- make sure none of the methods 734 // in toClass and fromClass have the same signature but 735 // different return types. (bug number 4028359) 736 if (toClass.isInterface() && fromClass.isInterface()) { 737 return toClass.couldImplement(fromClass); 738 } 739 740 return toClass.isInterface() || 741 fromClass.isInterface() || 742 fromClass.superClassOf(this, toClass.getClassDeclaration()); 743 } 744 if (to.isType(TC_ARRAY)) { 745 if (from.isType(TC_ARRAY)) { 746 Type t1 = from.getElementType(); 747 Type t2 = to.getElementType(); 748 while ((t1.getTypeCode() == TC_ARRAY) 749 && (t2.getTypeCode() == TC_ARRAY)) { 750 t1 = t1.getElementType(); 751 t2 = t2.getElementType(); 752 } 753 if (t1.inMask(TM_ARRAY|TM_CLASS) && 754 t2.inMask(TM_ARRAY|TM_CLASS)) { 755 return explicitCast(t1, t2); 756 } 757 } else if (from == Type.tObject || from == Type.tCloneable 758 || from == Type.tSerializable) 759 return true; 760 } 761 return false; 762 } 763 764 /** 765 * Flags. 766 */ 767 public int getFlags() { 768 return env.getFlags(); 769 } 770 771 /** 772 * Debugging flags. There used to be a method debug() 773 * that has been replaced because -g has changed meaning 774 * (it now cooperates with -O and line number, variable 775 * range and source file info can be toggled separately). 776 */ 777 public final boolean debug_lines() { 778 return (getFlags() & F_DEBUG_LINES) != 0; 779 } 780 public final boolean debug_vars() { 781 return (getFlags() & F_DEBUG_VARS) != 0; 782 } 783 public final boolean debug_source() { 784 return (getFlags() & F_DEBUG_SOURCE) != 0; 785 } 786 787 /** 788 * Optimization flags. There used to be a method optimize() 789 * that has been replaced because -O has changed meaning in 790 * javac to be replaced with -O and -O:interclass. 791 */ 792 public final boolean opt() { 793 return (getFlags() & F_OPT) != 0; 794 } 795 public final boolean opt_interclass() { 796 return (getFlags() & F_OPT_INTERCLASS) != 0; 797 } 798 799 /** 800 * Verbose 801 */ 802 public final boolean verbose() { 803 return (getFlags() & F_VERBOSE) != 0; 804 } 805 806 /** 807 * Dump debugging stuff 808 */ 809 public final boolean dump() { 810 return (getFlags() & F_DUMP) != 0; 811 } 812 813 /** 814 * Verbose 815 */ 816 public final boolean warnings() { 817 return (getFlags() & F_WARNINGS) != 0; 818 } 819 820 /** 821 * Dependencies 822 */ 823 public final boolean dependencies() { 824 return (getFlags() & F_DEPENDENCIES) != 0; 825 } 826 827 /** 828 * Print Dependencies to stdout 829 */ 830 public final boolean print_dependencies() { 831 return (getFlags() & F_PRINT_DEPENDENCIES) != 0; 832 } 833 834 /** 835 * Deprecation warnings are enabled. 836 */ 837 public final boolean deprecation() { 838 return (getFlags() & F_DEPRECATION) != 0; 839 } 840 841 /** 842 * Do not support virtual machines before version 1.2. 843 * This option is not supported and is only here for testing purposes. 844 */ 845 public final boolean version12() { 846 return (getFlags() & F_VERSION12) != 0; 847 } 848 849 /** 850 * Floating point is strict by default 851 */ 852 public final boolean strictdefault() { 853 return (getFlags() & F_STRICTDEFAULT) != 0; 854 } 855 856 /** 857 * Release resources, if any. 858 */ 859 public void shutdown() { 860 if (env != null) { 861 env.shutdown(); 862 } 863 } 864 865 /** 866 * Issue an error. 867 * source - the input source, usually a file name string 868 * offset - the offset in the source of the error 869 * err - the error number (as defined in this interface) 870 * arg1 - an optional argument to the error (null if not applicable) 871 * arg2 - a second optional argument to the error (null if not applicable) 872 * arg3 - a third optional argument to the error (null if not applicable) 873 */ 874 public void error(Object source, long where, String err, Object arg1, Object arg2, Object arg3) { 875 env.error(source, where, err, arg1, arg2, arg3); 876 } 877 public final void error(long where, String err, Object arg1, Object arg2, Object arg3) { 878 error(source, where, err, arg1, arg2, arg3); 879 } 880 public final void error(long where, String err, Object arg1, Object arg2) { 881 error(source, where, err, arg1, arg2, null); 882 } 883 public final void error(long where, String err, Object arg1) { 884 error(source, where, err, arg1, null, null); 885 } 886 public final void error(long where, String err) { 887 error(source, where, err, null, null, null); 888 } 889 890 /** 891 * Output a string. This can either be an error message or something 892 * for debugging. This should be used instead of println. 893 */ 894 public void output(String msg) { 895 env.output(msg); 896 } 897 898 private static boolean debugging = (System.getProperty("javac.debug") != null); 899 900 public static void debugOutput(Object msg) { 901 if (Environment.debugging) 902 System.out.println(msg.toString()); 903 } 904 905 /** 906 * set character encoding name 907 */ 908 public void setCharacterEncoding(String encoding) { 909 this.encoding = encoding; 910 } 911 912 /** 913 * Return character encoding name 914 */ 915 public String getCharacterEncoding() { 916 return encoding; 917 } 918 919 /** 920 * Return major version to use in generated class files. 921 */ 922 public short getMajorVersion() { 923 if (env==null) return JAVA_DEFAULT_VERSION; // needed for javah 924 return env.getMajorVersion(); 925 } 926 927 /** 928 * Return minor version to use in generated class files. 929 */ 930 public short getMinorVersion() { 931 if (env==null) return JAVA_DEFAULT_MINOR_VERSION; // needed for javah 932 return env.getMinorVersion(); 933 } 934 935 // JCOV 936 /** 937 * get coverage flag 938 */ 939 public final boolean coverage() { 940 return (getFlags() & F_COVERAGE) != 0; 941 } 942 943 /** 944 * get flag of generation the coverage data file 945 */ 946 public final boolean covdata() { 947 return (getFlags() & F_COVDATA) != 0; 948 } 949 950 /** 951 * Return the coverage data file 952 */ 953 public File getcovFile() { 954 return env.getcovFile(); 955 } 956 957 // end JCOV 958 959 /** 960 * Debug tracing. 961 * Currently, this code is used only for tracing the loading and 962 * checking of classes, particularly the demand-driven aspects. 963 * This code should probably be integrated with 'debugOutput' above, 964 * but we need to give more thought to the issue of classifying debugging 965 * messages and allowing those only those of interest to be enabled. 966 * 967 * Calls to these methods are generally conditioned on the final variable 968 * 'Constants.tracing', which allows the calls to be completely omitted 969 * in a production release to avoid space and time overhead. 970 */ 971 972 private static boolean dependtrace = 973 (System.getProperty("javac.trace.depend") != null); 974 975 public void dtEnter(String s) { 976 if (dependtrace) System.out.println(">>> " + s); 977 } 978 979 public void dtExit(String s) { 980 if (dependtrace) System.out.println("<<< " + s); 981 } 982 983 public void dtEvent(String s) { 984 if (dependtrace) System.out.println(s); 985 } 986 987 /** 988 * Enable diagnostic dump of class modifier bits, including those 989 * in InnerClasses attributes, as they are written to the classfile. 990 * In the future, may also enable dumping field and method modifiers. 991 */ 992 993 private static boolean dumpmodifiers = 994 (System.getProperty("javac.dump.modifiers") != null); 995 996 public boolean dumpModifiers() { return dumpmodifiers; } 997 998 }