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 @SuppressWarnings("fallthrough") 652 public boolean implicitCast(Type from, Type to) throws ClassNotFound { 653 if (from == to) 654 return true; 655 656 int toTypeCode = to.getTypeCode(); 657 658 switch(from.getTypeCode()) { 659 case TC_BYTE: 660 if (toTypeCode == TC_SHORT) 661 return true; 662 case TC_SHORT: 663 case TC_CHAR: 664 if (toTypeCode == TC_INT) return true; 665 case TC_INT: 666 if (toTypeCode == TC_LONG) return true; 667 case TC_LONG: 668 if (toTypeCode == TC_FLOAT) return true; 669 case TC_FLOAT: 670 if (toTypeCode == TC_DOUBLE) return true; 671 case TC_DOUBLE: 672 default: 673 return false; 674 675 case TC_NULL: 676 return to.inMask(TM_REFERENCE); 677 678 case TC_ARRAY: 679 if (!to.isType(TC_ARRAY)) { 680 return (to == Type.tObject || to == Type.tCloneable 681 || to == Type.tSerializable); 682 } else { 683 // both are arrays. recurse down both until one isn't an array 684 do { 685 from = from.getElementType(); 686 to = to.getElementType(); 687 } while (from.isType(TC_ARRAY) && to.isType(TC_ARRAY)); 688 if ( from.inMask(TM_ARRAY|TM_CLASS) 689 && to.inMask(TM_ARRAY|TM_CLASS)) { 690 return isMoreSpecific(from, to); 691 } else { 692 return (from.getTypeCode() == to.getTypeCode()); 693 } 694 } 695 696 case TC_CLASS: 697 if (toTypeCode == TC_CLASS) { 698 ClassDefinition fromDef = getClassDefinition(from); 699 ClassDefinition toDef = getClassDefinition(to); 700 return toDef.implementedBy(this, 701 fromDef.getClassDeclaration()); 702 } else { 703 return false; 704 } 705 } 706 } 707 708 709 /** 710 * Return true if an explicit cast from this type to 711 * the given type is allowed. 712 */ 713 public boolean explicitCast(Type from, Type to) throws ClassNotFound { 714 if (implicitCast(from, to)) { 715 return true; 716 } 717 if (from.inMask(TM_NUMBER)) { 718 return to.inMask(TM_NUMBER); 719 } 720 if (from.isType(TC_CLASS) && to.isType(TC_CLASS)) { 721 ClassDefinition fromClass = getClassDefinition(from); 722 ClassDefinition toClass = getClassDefinition(to); 723 if (toClass.isFinal()) { 724 return fromClass.implementedBy(this, 725 toClass.getClassDeclaration()); 726 } 727 if (fromClass.isFinal()) { 728 return toClass.implementedBy(this, 729 fromClass.getClassDeclaration()); 730 } 731 732 // The code here used to omit this case. If both types 733 // involved in a cast are interfaces, then JLS 5.5 requires 734 // that we do a simple test -- make sure none of the methods 735 // in toClass and fromClass have the same signature but 736 // different return types. (bug number 4028359) 737 if (toClass.isInterface() && fromClass.isInterface()) { 738 return toClass.couldImplement(fromClass); 739 } 740 741 return toClass.isInterface() || 742 fromClass.isInterface() || 743 fromClass.superClassOf(this, toClass.getClassDeclaration()); 744 } 745 if (to.isType(TC_ARRAY)) { 746 if (from.isType(TC_ARRAY)) { 747 Type t1 = from.getElementType(); 748 Type t2 = to.getElementType(); 749 while ((t1.getTypeCode() == TC_ARRAY) 750 && (t2.getTypeCode() == TC_ARRAY)) { 751 t1 = t1.getElementType(); 752 t2 = t2.getElementType(); 753 } 754 if (t1.inMask(TM_ARRAY|TM_CLASS) && 755 t2.inMask(TM_ARRAY|TM_CLASS)) { 756 return explicitCast(t1, t2); 757 } 758 } else if (from == Type.tObject || from == Type.tCloneable 759 || from == Type.tSerializable) 760 return true; 761 } 762 return false; 763 } 764 765 /** 766 * Flags. 767 */ 768 public int getFlags() { 769 return env.getFlags(); 770 } 771 772 /** 773 * Debugging flags. There used to be a method debug() 774 * that has been replaced because -g has changed meaning 775 * (it now cooperates with -O and line number, variable 776 * range and source file info can be toggled separately). 777 */ 778 public final boolean debug_lines() { 779 return (getFlags() & F_DEBUG_LINES) != 0; 780 } 781 public final boolean debug_vars() { 782 return (getFlags() & F_DEBUG_VARS) != 0; 783 } 784 public final boolean debug_source() { 785 return (getFlags() & F_DEBUG_SOURCE) != 0; 786 } 787 788 /** 789 * Optimization flags. There used to be a method optimize() 790 * that has been replaced because -O has changed meaning in 791 * javac to be replaced with -O and -O:interclass. 792 */ 793 public final boolean opt() { 794 return (getFlags() & F_OPT) != 0; 795 } 796 public final boolean opt_interclass() { 797 return (getFlags() & F_OPT_INTERCLASS) != 0; 798 } 799 800 /** 801 * Verbose 802 */ 803 public final boolean verbose() { 804 return (getFlags() & F_VERBOSE) != 0; 805 } 806 807 /** 808 * Dump debugging stuff 809 */ 810 public final boolean dump() { 811 return (getFlags() & F_DUMP) != 0; 812 } 813 814 /** 815 * Verbose 816 */ 817 public final boolean warnings() { 818 return (getFlags() & F_WARNINGS) != 0; 819 } 820 821 /** 822 * Dependencies 823 */ 824 public final boolean dependencies() { 825 return (getFlags() & F_DEPENDENCIES) != 0; 826 } 827 828 /** 829 * Print Dependencies to stdout 830 */ 831 public final boolean print_dependencies() { 832 return (getFlags() & F_PRINT_DEPENDENCIES) != 0; 833 } 834 835 /** 836 * Deprecation warnings are enabled. 837 */ 838 public final boolean deprecation() { 839 return (getFlags() & F_DEPRECATION) != 0; 840 } 841 842 /** 843 * Do not support virtual machines before version 1.2. 844 * This option is not supported and is only here for testing purposes. 845 */ 846 public final boolean version12() { 847 return (getFlags() & F_VERSION12) != 0; 848 } 849 850 /** 851 * Floating point is strict by default 852 */ 853 public final boolean strictdefault() { 854 return (getFlags() & F_STRICTDEFAULT) != 0; 855 } 856 857 /** 858 * Release resources, if any. 859 */ 860 public void shutdown() { 861 if (env != null) { 862 env.shutdown(); 863 } 864 } 865 866 /** 867 * Issue an error. 868 * source - the input source, usually a file name string 869 * offset - the offset in the source of the error 870 * err - the error number (as defined in this interface) 871 * arg1 - an optional argument to the error (null if not applicable) 872 * arg2 - a second optional argument to the error (null if not applicable) 873 * arg3 - a third optional argument to the error (null if not applicable) 874 */ 875 public void error(Object source, long where, String err, Object arg1, Object arg2, Object arg3) { 876 env.error(source, where, err, arg1, arg2, arg3); 877 } 878 public final void error(long where, String err, Object arg1, Object arg2, Object arg3) { 879 error(source, where, err, arg1, arg2, arg3); 880 } 881 public final void error(long where, String err, Object arg1, Object arg2) { 882 error(source, where, err, arg1, arg2, null); 883 } 884 public final void error(long where, String err, Object arg1) { 885 error(source, where, err, arg1, null, null); 886 } 887 public final void error(long where, String err) { 888 error(source, where, err, null, null, null); 889 } 890 891 /** 892 * Output a string. This can either be an error message or something 893 * for debugging. This should be used instead of println. 894 */ 895 public void output(String msg) { 896 env.output(msg); 897 } 898 899 private static boolean debugging = (System.getProperty("javac.debug") != null); 900 901 public static void debugOutput(Object msg) { 902 if (Environment.debugging) 903 System.out.println(msg.toString()); 904 } 905 906 /** 907 * set character encoding name 908 */ 909 public void setCharacterEncoding(String encoding) { 910 this.encoding = encoding; 911 } 912 913 /** 914 * Return character encoding name 915 */ 916 public String getCharacterEncoding() { 917 return encoding; 918 } 919 920 /** 921 * Return major version to use in generated class files. 922 */ 923 public short getMajorVersion() { 924 if (env==null) return JAVA_DEFAULT_VERSION; // needed for javah 925 return env.getMajorVersion(); 926 } 927 928 /** 929 * Return minor version to use in generated class files. 930 */ 931 public short getMinorVersion() { 932 if (env==null) return JAVA_DEFAULT_MINOR_VERSION; // needed for javah 933 return env.getMinorVersion(); 934 } 935 936 // JCOV 937 /** 938 * get coverage flag 939 */ 940 public final boolean coverage() { 941 return (getFlags() & F_COVERAGE) != 0; 942 } 943 944 /** 945 * get flag of generation the coverage data file 946 */ 947 public final boolean covdata() { 948 return (getFlags() & F_COVDATA) != 0; 949 } 950 951 /** 952 * Return the coverage data file 953 */ 954 public File getcovFile() { 955 return env.getcovFile(); 956 } 957 958 // end JCOV 959 960 /** 961 * Debug tracing. 962 * Currently, this code is used only for tracing the loading and 963 * checking of classes, particularly the demand-driven aspects. 964 * This code should probably be integrated with 'debugOutput' above, 965 * but we need to give more thought to the issue of classifying debugging 966 * messages and allowing those only those of interest to be enabled. 967 * 968 * Calls to these methods are generally conditioned on the final variable 969 * 'Constants.tracing', which allows the calls to be completely omitted 970 * in a production release to avoid space and time overhead. 971 */ 972 973 private static boolean dependtrace = 974 (System.getProperty("javac.trace.depend") != null); 975 976 public void dtEnter(String s) { 977 if (dependtrace) System.out.println(">>> " + s); 978 } 979 980 public void dtExit(String s) { 981 if (dependtrace) System.out.println("<<< " + s); 982 } 983 984 public void dtEvent(String s) { 985 if (dependtrace) System.out.println(s); 986 } 987 988 /** 989 * Enable diagnostic dump of class modifier bits, including those 990 * in InnerClasses attributes, as they are written to the classfile. 991 * In the future, may also enable dumping field and method modifiers. 992 */ 993 994 private static boolean dumpmodifiers = 995 (System.getProperty("javac.dump.modifiers") != null); 996 997 public boolean dumpModifiers() { return dumpmodifiers; } 998 999 }