Thu, 05 Jan 2017 18:58:06 +0000
8168774: Polymorhic signature method check crashes javac
Summary: Check for polysig method assumes arity is greater than zero
Reviewed-by: vromero
duke@1 | 1 | /* |
jjg@1492 | 2 | * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
duke@1 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@1 | 4 | * |
duke@1 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@1 | 6 | * under the terms of the GNU General Public License version 2 only, as |
ohair@554 | 7 | * published by the Free Software Foundation. Oracle designates this |
duke@1 | 8 | * particular file as subject to the "Classpath" exception as provided |
ohair@554 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
duke@1 | 10 | * |
duke@1 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@1 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@1 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@1 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@1 | 15 | * accompanied this code). |
duke@1 | 16 | * |
duke@1 | 17 | * You should have received a copy of the GNU General Public License version |
duke@1 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@1 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@1 | 20 | * |
ohair@554 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ohair@554 | 22 | * or visit www.oracle.com if you need additional information or have any |
ohair@554 | 23 | * questions. |
duke@1 | 24 | */ |
duke@1 | 25 | |
duke@1 | 26 | package com.sun.tools.javac.code; |
duke@1 | 27 | |
duke@1 | 28 | import java.util.*; |
jjg@1357 | 29 | |
jjg@1357 | 30 | import javax.lang.model.element.ElementVisitor; |
duke@1 | 31 | |
duke@1 | 32 | import com.sun.tools.javac.code.Symbol.*; |
duke@1 | 33 | import com.sun.tools.javac.code.Type.*; |
duke@1 | 34 | import com.sun.tools.javac.jvm.*; |
jjg@1357 | 35 | import com.sun.tools.javac.util.*; |
jjg@1357 | 36 | import com.sun.tools.javac.util.List; |
jjg@1357 | 37 | import static com.sun.tools.javac.code.Flags.*; |
duke@1 | 38 | import static com.sun.tools.javac.jvm.ByteCodes.*; |
jjg@1374 | 39 | import static com.sun.tools.javac.code.TypeTag.*; |
duke@1 | 40 | |
duke@1 | 41 | /** A class that defines all predefined constants and operators |
duke@1 | 42 | * as well as special classes such as java.lang.Object, which need |
duke@1 | 43 | * to be known to the compiler. All symbols are held in instance |
duke@1 | 44 | * fields. This makes it possible to work in multiple concurrent |
duke@1 | 45 | * projects, which might use different class files for library classes. |
duke@1 | 46 | * |
jjg@581 | 47 | * <p><b>This is NOT part of any supported API. |
jjg@581 | 48 | * If you write code that depends on this, you do so at your own risk. |
duke@1 | 49 | * This code and its internal interfaces are subject to change or |
duke@1 | 50 | * deletion without notice.</b> |
duke@1 | 51 | */ |
duke@1 | 52 | public class Symtab { |
duke@1 | 53 | /** The context key for the symbol table. */ |
duke@1 | 54 | protected static final Context.Key<Symtab> symtabKey = |
duke@1 | 55 | new Context.Key<Symtab>(); |
duke@1 | 56 | |
duke@1 | 57 | /** Get the symbol table instance. */ |
duke@1 | 58 | public static Symtab instance(Context context) { |
duke@1 | 59 | Symtab instance = context.get(symtabKey); |
duke@1 | 60 | if (instance == null) |
duke@1 | 61 | instance = new Symtab(context); |
duke@1 | 62 | return instance; |
duke@1 | 63 | } |
duke@1 | 64 | |
duke@1 | 65 | /** Builtin types. |
duke@1 | 66 | */ |
vromero@1853 | 67 | public final JCPrimitiveType byteType = new JCPrimitiveType(BYTE, null); |
vromero@1853 | 68 | public final JCPrimitiveType charType = new JCPrimitiveType(CHAR, null); |
vromero@1853 | 69 | public final JCPrimitiveType shortType = new JCPrimitiveType(SHORT, null); |
vromero@1853 | 70 | public final JCPrimitiveType intType = new JCPrimitiveType(INT, null); |
vromero@1853 | 71 | public final JCPrimitiveType longType = new JCPrimitiveType(LONG, null); |
vromero@1853 | 72 | public final JCPrimitiveType floatType = new JCPrimitiveType(FLOAT, null); |
vromero@1853 | 73 | public final JCPrimitiveType doubleType = new JCPrimitiveType(DOUBLE, null); |
vromero@1853 | 74 | public final JCPrimitiveType booleanType = new JCPrimitiveType(BOOLEAN, null); |
duke@1 | 75 | public final Type botType = new BottomType(); |
vromero@1853 | 76 | public final JCVoidType voidType = new JCVoidType(); |
duke@1 | 77 | |
jjg@113 | 78 | private final Names names; |
duke@1 | 79 | private final ClassReader reader; |
jjg@86 | 80 | private final Target target; |
duke@1 | 81 | |
duke@1 | 82 | /** A symbol for the root package. |
duke@1 | 83 | */ |
duke@1 | 84 | public final PackageSymbol rootPackage; |
duke@1 | 85 | |
duke@1 | 86 | /** A symbol for the unnamed package. |
duke@1 | 87 | */ |
duke@1 | 88 | public final PackageSymbol unnamedPackage; |
duke@1 | 89 | |
duke@1 | 90 | /** A symbol that stands for a missing symbol. |
duke@1 | 91 | */ |
duke@1 | 92 | public final TypeSymbol noSymbol; |
duke@1 | 93 | |
duke@1 | 94 | /** The error symbol. |
duke@1 | 95 | */ |
duke@1 | 96 | public final ClassSymbol errSymbol; |
duke@1 | 97 | |
mcimadamore@676 | 98 | /** The unknown symbol. |
mcimadamore@676 | 99 | */ |
mcimadamore@676 | 100 | public final ClassSymbol unknownSymbol; |
mcimadamore@676 | 101 | |
jjg@110 | 102 | /** A value for the errType, with a originalType of noType */ |
duke@1 | 103 | public final Type errType; |
duke@1 | 104 | |
duke@1 | 105 | /** A value for the unknown type. */ |
duke@1 | 106 | public final Type unknownType; |
duke@1 | 107 | |
duke@1 | 108 | /** The builtin type of all arrays. */ |
duke@1 | 109 | public final ClassSymbol arrayClass; |
duke@1 | 110 | public final MethodSymbol arrayCloneMethod; |
duke@1 | 111 | |
duke@1 | 112 | /** VGJ: The (singleton) type of all bound types. */ |
duke@1 | 113 | public final ClassSymbol boundClass; |
duke@1 | 114 | |
duke@1 | 115 | /** The builtin type of all methods. */ |
duke@1 | 116 | public final ClassSymbol methodClass; |
duke@1 | 117 | |
duke@1 | 118 | /** Predefined types. |
duke@1 | 119 | */ |
duke@1 | 120 | public final Type objectType; |
duke@1 | 121 | public final Type classType; |
duke@1 | 122 | public final Type classLoaderType; |
duke@1 | 123 | public final Type stringType; |
duke@1 | 124 | public final Type stringBufferType; |
duke@1 | 125 | public final Type stringBuilderType; |
duke@1 | 126 | public final Type cloneableType; |
duke@1 | 127 | public final Type serializableType; |
rfield@1587 | 128 | public final Type serializedLambdaType; |
jrose@267 | 129 | public final Type methodHandleType; |
rfield@1380 | 130 | public final Type methodHandleLookupType; |
mcimadamore@1336 | 131 | public final Type methodTypeType; |
jjg@1230 | 132 | public final Type nativeHeaderType; |
duke@1 | 133 | public final Type throwableType; |
duke@1 | 134 | public final Type errorType; |
mcimadamore@951 | 135 | public final Type interruptedExceptionType; |
duke@1 | 136 | public final Type illegalArgumentExceptionType; |
duke@1 | 137 | public final Type exceptionType; |
duke@1 | 138 | public final Type runtimeExceptionType; |
duke@1 | 139 | public final Type classNotFoundExceptionType; |
duke@1 | 140 | public final Type noClassDefFoundErrorType; |
duke@1 | 141 | public final Type noSuchFieldErrorType; |
duke@1 | 142 | public final Type assertionErrorType; |
duke@1 | 143 | public final Type cloneNotSupportedExceptionType; |
duke@1 | 144 | public final Type annotationType; |
duke@1 | 145 | public final TypeSymbol enumSym; |
duke@1 | 146 | public final Type listType; |
duke@1 | 147 | public final Type collectionsType; |
duke@1 | 148 | public final Type comparableType; |
vromero@1620 | 149 | public final Type comparatorType; |
duke@1 | 150 | public final Type arraysType; |
duke@1 | 151 | public final Type iterableType; |
duke@1 | 152 | public final Type iteratorType; |
duke@1 | 153 | public final Type annotationTargetType; |
duke@1 | 154 | public final Type overrideType; |
duke@1 | 155 | public final Type retentionType; |
duke@1 | 156 | public final Type deprecatedType; |
duke@1 | 157 | public final Type suppressWarningsType; |
duke@1 | 158 | public final Type inheritedType; |
jjg@1569 | 159 | public final Type profileType; |
duke@1 | 160 | public final Type proprietaryType; |
jjg@86 | 161 | public final Type systemType; |
darcy@609 | 162 | public final Type autoCloseableType; |
mcimadamore@795 | 163 | public final Type trustMeType; |
rfield@1380 | 164 | public final Type lambdaMetafactory; |
jjg@1492 | 165 | public final Type repeatableType; |
jfranck@1313 | 166 | public final Type documentedType; |
jfranck@1313 | 167 | public final Type elementTypeType; |
mcimadamore@1497 | 168 | public final Type functionalInterfaceType; |
duke@1 | 169 | |
duke@1 | 170 | /** The symbol representing the length field of an array. |
duke@1 | 171 | */ |
duke@1 | 172 | public final VarSymbol lengthVar; |
duke@1 | 173 | |
duke@1 | 174 | /** The null check operator. */ |
duke@1 | 175 | public final OperatorSymbol nullcheck; |
duke@1 | 176 | |
duke@1 | 177 | /** The symbol representing the final finalize method on enums */ |
duke@1 | 178 | public final MethodSymbol enumFinalFinalize; |
duke@1 | 179 | |
darcy@609 | 180 | /** The symbol representing the close method on TWR AutoCloseable type */ |
darcy@609 | 181 | public final MethodSymbol autoCloseableClose; |
darcy@609 | 182 | |
duke@1 | 183 | /** The predefined type that belongs to a tag. |
duke@1 | 184 | */ |
jjg@1374 | 185 | public final Type[] typeOfTag = new Type[TypeTag.getTypeTagCount()]; |
duke@1 | 186 | |
duke@1 | 187 | /** The name of the class that belongs to a basix type tag. |
duke@1 | 188 | */ |
jjg@1374 | 189 | public final Name[] boxedName = new Name[TypeTag.getTypeTagCount()]; |
duke@1 | 190 | |
mcimadamore@1347 | 191 | /** A set containing all operator names. |
mcimadamore@1347 | 192 | */ |
mcimadamore@1347 | 193 | public final Set<Name> operatorNames = new HashSet<Name>(); |
mcimadamore@1347 | 194 | |
duke@1 | 195 | /** A hashtable containing the encountered top-level and member classes, |
duke@1 | 196 | * indexed by flat names. The table does not contain local classes. |
duke@1 | 197 | * It should be updated from the outside to reflect classes defined |
duke@1 | 198 | * by compiled source files. |
duke@1 | 199 | */ |
duke@1 | 200 | public final Map<Name, ClassSymbol> classes = new HashMap<Name, ClassSymbol>(); |
duke@1 | 201 | |
duke@1 | 202 | /** A hashtable containing the encountered packages. |
duke@1 | 203 | * the table should be updated from outside to reflect packages defined |
duke@1 | 204 | * by compiled source files. |
duke@1 | 205 | */ |
duke@1 | 206 | public final Map<Name, PackageSymbol> packages = new HashMap<Name, PackageSymbol>(); |
duke@1 | 207 | |
duke@1 | 208 | public void initType(Type type, ClassSymbol c) { |
duke@1 | 209 | type.tsym = c; |
vromero@1853 | 210 | typeOfTag[type.getTag().ordinal()] = type; |
duke@1 | 211 | } |
duke@1 | 212 | |
duke@1 | 213 | public void initType(Type type, String name) { |
duke@1 | 214 | initType( |
duke@1 | 215 | type, |
duke@1 | 216 | new ClassSymbol( |
duke@1 | 217 | PUBLIC, names.fromString(name), type, rootPackage)); |
duke@1 | 218 | } |
duke@1 | 219 | |
duke@1 | 220 | public void initType(Type type, String name, String bname) { |
duke@1 | 221 | initType(type, name); |
vromero@1853 | 222 | boxedName[type.getTag().ordinal()] = names.fromString("java.lang." + bname); |
duke@1 | 223 | } |
duke@1 | 224 | |
duke@1 | 225 | /** The class symbol that owns all predefined symbols. |
duke@1 | 226 | */ |
duke@1 | 227 | public final ClassSymbol predefClass; |
duke@1 | 228 | |
duke@1 | 229 | /** Enter a constant into symbol table. |
duke@1 | 230 | * @param name The constant's name. |
duke@1 | 231 | * @param type The constant's type. |
duke@1 | 232 | */ |
duke@1 | 233 | private VarSymbol enterConstant(String name, Type type) { |
duke@1 | 234 | VarSymbol c = new VarSymbol( |
duke@1 | 235 | PUBLIC | STATIC | FINAL, |
duke@1 | 236 | names.fromString(name), |
duke@1 | 237 | type, |
duke@1 | 238 | predefClass); |
duke@1 | 239 | c.setData(type.constValue()); |
duke@1 | 240 | predefClass.members().enter(c); |
duke@1 | 241 | return c; |
duke@1 | 242 | } |
duke@1 | 243 | |
duke@1 | 244 | /** Enter a binary operation into symbol table. |
duke@1 | 245 | * @param name The name of the operator. |
duke@1 | 246 | * @param left The type of the left operand. |
duke@1 | 247 | * @param right The type of the left operand. |
duke@1 | 248 | * @param res The operation's result type. |
duke@1 | 249 | * @param opcode The operation's bytecode instruction. |
duke@1 | 250 | */ |
duke@1 | 251 | private void enterBinop(String name, |
duke@1 | 252 | Type left, Type right, Type res, |
duke@1 | 253 | int opcode) { |
duke@1 | 254 | predefClass.members().enter( |
duke@1 | 255 | new OperatorSymbol( |
mcimadamore@1347 | 256 | makeOperatorName(name), |
duke@1 | 257 | new MethodType(List.of(left, right), res, |
duke@1 | 258 | List.<Type>nil(), methodClass), |
duke@1 | 259 | opcode, |
duke@1 | 260 | predefClass)); |
duke@1 | 261 | } |
duke@1 | 262 | |
duke@1 | 263 | /** Enter a binary operation, as above but with two opcodes, |
jjg@1326 | 264 | * which get encoded as |
jjg@1326 | 265 | * {@code (opcode1 << ByteCodeTags.preShift) + opcode2 }. |
duke@1 | 266 | * @param opcode1 First opcode. |
duke@1 | 267 | * @param opcode2 Second opcode. |
duke@1 | 268 | */ |
duke@1 | 269 | private void enterBinop(String name, |
duke@1 | 270 | Type left, Type right, Type res, |
duke@1 | 271 | int opcode1, int opcode2) { |
duke@1 | 272 | enterBinop( |
duke@1 | 273 | name, left, right, res, (opcode1 << ByteCodes.preShift) | opcode2); |
duke@1 | 274 | } |
duke@1 | 275 | |
duke@1 | 276 | /** Enter a unary operation into symbol table. |
duke@1 | 277 | * @param name The name of the operator. |
duke@1 | 278 | * @param arg The type of the operand. |
duke@1 | 279 | * @param res The operation's result type. |
duke@1 | 280 | * @param opcode The operation's bytecode instruction. |
duke@1 | 281 | */ |
duke@1 | 282 | private OperatorSymbol enterUnop(String name, |
duke@1 | 283 | Type arg, |
duke@1 | 284 | Type res, |
duke@1 | 285 | int opcode) { |
duke@1 | 286 | OperatorSymbol sym = |
mcimadamore@1347 | 287 | new OperatorSymbol(makeOperatorName(name), |
duke@1 | 288 | new MethodType(List.of(arg), |
duke@1 | 289 | res, |
duke@1 | 290 | List.<Type>nil(), |
duke@1 | 291 | methodClass), |
duke@1 | 292 | opcode, |
duke@1 | 293 | predefClass); |
duke@1 | 294 | predefClass.members().enter(sym); |
duke@1 | 295 | return sym; |
duke@1 | 296 | } |
duke@1 | 297 | |
mcimadamore@1347 | 298 | /** |
mcimadamore@1347 | 299 | * Create a new operator name from corresponding String representation |
mcimadamore@1347 | 300 | * and add the name to the set of known operator names. |
mcimadamore@1347 | 301 | */ |
mcimadamore@1347 | 302 | private Name makeOperatorName(String name) { |
mcimadamore@1347 | 303 | Name opName = names.fromString(name); |
mcimadamore@1347 | 304 | operatorNames.add(opName); |
mcimadamore@1347 | 305 | return opName; |
mcimadamore@1347 | 306 | } |
mcimadamore@1347 | 307 | |
duke@1 | 308 | /** Enter a class into symbol table. |
jjg@1358 | 309 | * @param s The name of the class. |
duke@1 | 310 | */ |
duke@1 | 311 | private Type enterClass(String s) { |
duke@1 | 312 | return reader.enterClass(names.fromString(s)).type; |
duke@1 | 313 | } |
duke@1 | 314 | |
jjg@86 | 315 | public void synthesizeEmptyInterfaceIfMissing(final Type type) { |
jjg@86 | 316 | final Completer completer = type.tsym.completer; |
jjg@86 | 317 | if (completer != null) { |
jjg@86 | 318 | type.tsym.completer = new Completer() { |
jjg@86 | 319 | public void complete(Symbol sym) throws CompletionFailure { |
jjg@86 | 320 | try { |
jjg@86 | 321 | completer.complete(sym); |
jjg@86 | 322 | } catch (CompletionFailure e) { |
jjg@86 | 323 | sym.flags_field |= (PUBLIC | INTERFACE); |
jjg@86 | 324 | ((ClassType) sym.type).supertype_field = objectType; |
jjg@86 | 325 | } |
jjg@86 | 326 | } |
jjg@86 | 327 | }; |
jjg@86 | 328 | } |
jjg@86 | 329 | } |
jjg@86 | 330 | |
jjg@86 | 331 | public void synthesizeBoxTypeIfMissing(final Type type) { |
vromero@1853 | 332 | ClassSymbol sym = reader.enterClass(boxedName[type.getTag().ordinal()]); |
jjg@86 | 333 | final Completer completer = sym.completer; |
jjg@86 | 334 | if (completer != null) { |
jjg@86 | 335 | sym.completer = new Completer() { |
jjg@86 | 336 | public void complete(Symbol sym) throws CompletionFailure { |
jjg@86 | 337 | try { |
jjg@86 | 338 | completer.complete(sym); |
jjg@86 | 339 | } catch (CompletionFailure e) { |
jjg@86 | 340 | sym.flags_field |= PUBLIC; |
jjg@86 | 341 | ((ClassType) sym.type).supertype_field = objectType; |
jjg@86 | 342 | Name n = target.boxWithConstructors() ? names.init : names.valueOf; |
jjg@86 | 343 | MethodSymbol boxMethod = |
jjg@86 | 344 | new MethodSymbol(PUBLIC | STATIC, |
jjg@86 | 345 | n, |
jjg@86 | 346 | new MethodType(List.of(type), sym.type, |
jjg@86 | 347 | List.<Type>nil(), methodClass), |
jjg@86 | 348 | sym); |
jjg@86 | 349 | sym.members().enter(boxMethod); |
jjg@86 | 350 | MethodSymbol unboxMethod = |
jjg@86 | 351 | new MethodSymbol(PUBLIC, |
jjg@86 | 352 | type.tsym.name.append(names.Value), // x.intValue() |
jjg@86 | 353 | new MethodType(List.<Type>nil(), type, |
jjg@86 | 354 | List.<Type>nil(), methodClass), |
jjg@86 | 355 | sym); |
jjg@86 | 356 | sym.members().enter(unboxMethod); |
jjg@86 | 357 | } |
jjg@86 | 358 | } |
jjg@86 | 359 | }; |
jjg@86 | 360 | } |
jjg@86 | 361 | |
jjg@86 | 362 | } |
jjg@86 | 363 | |
jjg@1569 | 364 | // Enter a synthetic class that is used to mark classes in ct.sym. |
jjg@1569 | 365 | // This class does not have a class file. |
jjg@1569 | 366 | private Type enterSyntheticAnnotation(String name) { |
jjg@1569 | 367 | ClassType type = (ClassType)enterClass(name); |
jjg@1569 | 368 | ClassSymbol sym = (ClassSymbol)type.tsym; |
jjg@1569 | 369 | sym.completer = null; |
jjg@1569 | 370 | sym.flags_field = PUBLIC|ACYCLIC|ANNOTATION|INTERFACE; |
jjg@1569 | 371 | sym.erasure_field = type; |
jjg@1569 | 372 | sym.members_field = new Scope(sym); |
jjg@1569 | 373 | type.typarams_field = List.nil(); |
jjg@1569 | 374 | type.allparams_field = List.nil(); |
jjg@1569 | 375 | type.supertype_field = annotationType; |
jjg@1569 | 376 | type.interfaces_field = List.nil(); |
jjg@1569 | 377 | return type; |
jjg@1569 | 378 | } |
jjg@1569 | 379 | |
duke@1 | 380 | /** Constructor; enters all predefined identifiers and operators |
duke@1 | 381 | * into symbol table. |
duke@1 | 382 | */ |
duke@1 | 383 | protected Symtab(Context context) throws CompletionFailure { |
duke@1 | 384 | context.put(symtabKey, this); |
duke@1 | 385 | |
jjg@113 | 386 | names = Names.instance(context); |
jjg@86 | 387 | target = Target.instance(context); |
duke@1 | 388 | |
duke@1 | 389 | // Create the unknown type |
vromero@1853 | 390 | unknownType = new UnknownType(); |
duke@1 | 391 | |
duke@1 | 392 | // create the basic builtin symbols |
duke@1 | 393 | rootPackage = new PackageSymbol(names.empty, null); |
mcimadamore@136 | 394 | final JavacMessages messages = JavacMessages.instance(context); |
duke@1 | 395 | unnamedPackage = new PackageSymbol(names.empty, rootPackage) { |
duke@1 | 396 | public String toString() { |
duke@1 | 397 | return messages.getLocalizedString("compiler.misc.unnamed.package"); |
duke@1 | 398 | } |
duke@1 | 399 | }; |
jfranck@1689 | 400 | noSymbol = new TypeSymbol(Kinds.NIL, 0, names.empty, Type.noType, rootPackage) { |
jjg@900 | 401 | public <R, P> R accept(ElementVisitor<R, P> v, P p) { |
jjg@900 | 402 | return v.visitUnknown(this, p); |
jjg@900 | 403 | } |
jjg@900 | 404 | }; |
duke@1 | 405 | |
duke@1 | 406 | // create the error symbols |
duke@1 | 407 | errSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.any, null, rootPackage); |
jjg@900 | 408 | errType = new ErrorType(errSymbol, Type.noType); |
jjg@900 | 409 | |
mcimadamore@676 | 410 | unknownSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.fromString("<any?>"), null, rootPackage); |
jjg@900 | 411 | unknownSymbol.members_field = new Scope.ErrorScope(unknownSymbol); |
jjg@900 | 412 | unknownSymbol.type = unknownType; |
duke@1 | 413 | |
duke@1 | 414 | // initialize builtin types |
duke@1 | 415 | initType(byteType, "byte", "Byte"); |
duke@1 | 416 | initType(shortType, "short", "Short"); |
duke@1 | 417 | initType(charType, "char", "Character"); |
duke@1 | 418 | initType(intType, "int", "Integer"); |
duke@1 | 419 | initType(longType, "long", "Long"); |
duke@1 | 420 | initType(floatType, "float", "Float"); |
duke@1 | 421 | initType(doubleType, "double", "Double"); |
duke@1 | 422 | initType(booleanType, "boolean", "Boolean"); |
duke@1 | 423 | initType(voidType, "void", "Void"); |
duke@1 | 424 | initType(botType, "<nulltype>"); |
duke@1 | 425 | initType(errType, errSymbol); |
mcimadamore@676 | 426 | initType(unknownType, unknownSymbol); |
duke@1 | 427 | |
duke@1 | 428 | // the builtin class of all arrays |
duke@1 | 429 | arrayClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Array, noSymbol); |
duke@1 | 430 | |
duke@1 | 431 | // VGJ |
duke@1 | 432 | boundClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Bound, noSymbol); |
jjg@900 | 433 | boundClass.members_field = new Scope.ErrorScope(boundClass); |
duke@1 | 434 | |
duke@1 | 435 | // the builtin class of all methods |
duke@1 | 436 | methodClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Method, noSymbol); |
jjg@900 | 437 | methodClass.members_field = new Scope.ErrorScope(boundClass); |
duke@1 | 438 | |
duke@1 | 439 | // Create class to hold all predefined constants and operations. |
duke@1 | 440 | predefClass = new ClassSymbol(PUBLIC|ACYCLIC, names.empty, rootPackage); |
mcimadamore@858 | 441 | Scope scope = new Scope(predefClass); |
duke@1 | 442 | predefClass.members_field = scope; |
duke@1 | 443 | |
duke@1 | 444 | // Enter symbols for basic types. |
duke@1 | 445 | scope.enter(byteType.tsym); |
duke@1 | 446 | scope.enter(shortType.tsym); |
duke@1 | 447 | scope.enter(charType.tsym); |
duke@1 | 448 | scope.enter(intType.tsym); |
duke@1 | 449 | scope.enter(longType.tsym); |
duke@1 | 450 | scope.enter(floatType.tsym); |
duke@1 | 451 | scope.enter(doubleType.tsym); |
duke@1 | 452 | scope.enter(booleanType.tsym); |
duke@1 | 453 | scope.enter(errType.tsym); |
duke@1 | 454 | |
jjg@110 | 455 | // Enter symbol for the errSymbol |
jjg@110 | 456 | scope.enter(errSymbol); |
jjg@110 | 457 | |
duke@1 | 458 | classes.put(predefClass.fullname, predefClass); |
duke@1 | 459 | |
duke@1 | 460 | reader = ClassReader.instance(context); |
duke@1 | 461 | reader.init(this); |
duke@1 | 462 | |
duke@1 | 463 | // Enter predefined classes. |
duke@1 | 464 | objectType = enterClass("java.lang.Object"); |
duke@1 | 465 | classType = enterClass("java.lang.Class"); |
duke@1 | 466 | stringType = enterClass("java.lang.String"); |
duke@1 | 467 | stringBufferType = enterClass("java.lang.StringBuffer"); |
duke@1 | 468 | stringBuilderType = enterClass("java.lang.StringBuilder"); |
duke@1 | 469 | cloneableType = enterClass("java.lang.Cloneable"); |
duke@1 | 470 | throwableType = enterClass("java.lang.Throwable"); |
duke@1 | 471 | serializableType = enterClass("java.io.Serializable"); |
rfield@1587 | 472 | serializedLambdaType = enterClass("java.lang.invoke.SerializedLambda"); |
mcimadamore@857 | 473 | methodHandleType = enterClass("java.lang.invoke.MethodHandle"); |
rfield@1380 | 474 | methodHandleLookupType = enterClass("java.lang.invoke.MethodHandles$Lookup"); |
mcimadamore@1336 | 475 | methodTypeType = enterClass("java.lang.invoke.MethodType"); |
duke@1 | 476 | errorType = enterClass("java.lang.Error"); |
duke@1 | 477 | illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException"); |
mcimadamore@951 | 478 | interruptedExceptionType = enterClass("java.lang.InterruptedException"); |
duke@1 | 479 | exceptionType = enterClass("java.lang.Exception"); |
duke@1 | 480 | runtimeExceptionType = enterClass("java.lang.RuntimeException"); |
duke@1 | 481 | classNotFoundExceptionType = enterClass("java.lang.ClassNotFoundException"); |
duke@1 | 482 | noClassDefFoundErrorType = enterClass("java.lang.NoClassDefFoundError"); |
duke@1 | 483 | noSuchFieldErrorType = enterClass("java.lang.NoSuchFieldError"); |
duke@1 | 484 | assertionErrorType = enterClass("java.lang.AssertionError"); |
duke@1 | 485 | cloneNotSupportedExceptionType = enterClass("java.lang.CloneNotSupportedException"); |
duke@1 | 486 | annotationType = enterClass("java.lang.annotation.Annotation"); |
duke@1 | 487 | classLoaderType = enterClass("java.lang.ClassLoader"); |
duke@1 | 488 | enumSym = reader.enterClass(names.java_lang_Enum); |
duke@1 | 489 | enumFinalFinalize = |
duke@1 | 490 | new MethodSymbol(PROTECTED|FINAL|HYPOTHETICAL, |
duke@1 | 491 | names.finalize, |
duke@1 | 492 | new MethodType(List.<Type>nil(), voidType, |
duke@1 | 493 | List.<Type>nil(), methodClass), |
duke@1 | 494 | enumSym); |
duke@1 | 495 | listType = enterClass("java.util.List"); |
duke@1 | 496 | collectionsType = enterClass("java.util.Collections"); |
duke@1 | 497 | comparableType = enterClass("java.lang.Comparable"); |
vromero@1620 | 498 | comparatorType = enterClass("java.util.Comparator"); |
duke@1 | 499 | arraysType = enterClass("java.util.Arrays"); |
jjg@86 | 500 | iterableType = target.hasIterable() |
duke@1 | 501 | ? enterClass("java.lang.Iterable") |
duke@1 | 502 | : enterClass("java.util.Collection"); |
duke@1 | 503 | iteratorType = enterClass("java.util.Iterator"); |
duke@1 | 504 | annotationTargetType = enterClass("java.lang.annotation.Target"); |
duke@1 | 505 | overrideType = enterClass("java.lang.Override"); |
duke@1 | 506 | retentionType = enterClass("java.lang.annotation.Retention"); |
duke@1 | 507 | deprecatedType = enterClass("java.lang.Deprecated"); |
duke@1 | 508 | suppressWarningsType = enterClass("java.lang.SuppressWarnings"); |
duke@1 | 509 | inheritedType = enterClass("java.lang.annotation.Inherited"); |
jjg@1492 | 510 | repeatableType = enterClass("java.lang.annotation.Repeatable"); |
jfranck@1313 | 511 | documentedType = enterClass("java.lang.annotation.Documented"); |
jfranck@1313 | 512 | elementTypeType = enterClass("java.lang.annotation.ElementType"); |
jjg@86 | 513 | systemType = enterClass("java.lang.System"); |
darcy@609 | 514 | autoCloseableType = enterClass("java.lang.AutoCloseable"); |
darcy@609 | 515 | autoCloseableClose = new MethodSymbol(PUBLIC, |
darcy@609 | 516 | names.close, |
darcy@609 | 517 | new MethodType(List.<Type>nil(), voidType, |
darcy@609 | 518 | List.of(exceptionType), methodClass), |
darcy@609 | 519 | autoCloseableType.tsym); |
mcimadamore@795 | 520 | trustMeType = enterClass("java.lang.SafeVarargs"); |
jjg@1407 | 521 | nativeHeaderType = enterClass("java.lang.annotation.Native"); |
rfield@1380 | 522 | lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory"); |
mcimadamore@1497 | 523 | functionalInterfaceType = enterClass("java.lang.FunctionalInterface"); |
jjg@86 | 524 | |
mcimadamore@951 | 525 | synthesizeEmptyInterfaceIfMissing(autoCloseableType); |
jjg@86 | 526 | synthesizeEmptyInterfaceIfMissing(cloneableType); |
jjg@86 | 527 | synthesizeEmptyInterfaceIfMissing(serializableType); |
rfield@1380 | 528 | synthesizeEmptyInterfaceIfMissing(lambdaMetafactory); |
rfield@1587 | 529 | synthesizeEmptyInterfaceIfMissing(serializedLambdaType); |
jjg@86 | 530 | synthesizeBoxTypeIfMissing(doubleType); |
jjg@86 | 531 | synthesizeBoxTypeIfMissing(floatType); |
mcimadamore@357 | 532 | synthesizeBoxTypeIfMissing(voidType); |
duke@1 | 533 | |
jjg@582 | 534 | // Enter a synthetic class that is used to mark internal |
duke@1 | 535 | // proprietary classes in ct.sym. This class does not have a |
duke@1 | 536 | // class file. |
jjg@1569 | 537 | proprietaryType = enterSyntheticAnnotation("sun.Proprietary+Annotation"); |
jjg@1569 | 538 | |
jjg@1569 | 539 | // Enter a synthetic class that is used to provide profile info for |
jjg@1569 | 540 | // classes in ct.sym. This class does not have a class file. |
jjg@1569 | 541 | profileType = enterSyntheticAnnotation("jdk.Profile+Annotation"); |
jjg@1569 | 542 | MethodSymbol m = new MethodSymbol(PUBLIC | ABSTRACT, names.value, intType, profileType.tsym); |
jjg@1569 | 543 | profileType.tsym.members().enter(m); |
duke@1 | 544 | |
duke@1 | 545 | // Enter a class for arrays. |
duke@1 | 546 | // The class implements java.lang.Cloneable and java.io.Serializable. |
duke@1 | 547 | // It has a final length field and a clone method. |
duke@1 | 548 | ClassType arrayClassType = (ClassType)arrayClass.type; |
duke@1 | 549 | arrayClassType.supertype_field = objectType; |
duke@1 | 550 | arrayClassType.interfaces_field = List.of(cloneableType, serializableType); |
mcimadamore@858 | 551 | arrayClass.members_field = new Scope(arrayClass); |
duke@1 | 552 | lengthVar = new VarSymbol( |
duke@1 | 553 | PUBLIC | FINAL, |
duke@1 | 554 | names.length, |
duke@1 | 555 | intType, |
duke@1 | 556 | arrayClass); |
duke@1 | 557 | arrayClass.members().enter(lengthVar); |
duke@1 | 558 | arrayCloneMethod = new MethodSymbol( |
duke@1 | 559 | PUBLIC, |
duke@1 | 560 | names.clone, |
duke@1 | 561 | new MethodType(List.<Type>nil(), objectType, |
duke@1 | 562 | List.<Type>nil(), methodClass), |
duke@1 | 563 | arrayClass); |
duke@1 | 564 | arrayClass.members().enter(arrayCloneMethod); |
duke@1 | 565 | |
duke@1 | 566 | // Enter operators. |
vromero@1845 | 567 | /* Internally we use +++, --- for unary +, - to reduce +, - operators |
vromero@1845 | 568 | * overloading |
vromero@1845 | 569 | */ |
vromero@1845 | 570 | enterUnop("+++", doubleType, doubleType, nop); |
vromero@1845 | 571 | enterUnop("+++", floatType, floatType, nop); |
vromero@1845 | 572 | enterUnop("+++", longType, longType, nop); |
vromero@1845 | 573 | enterUnop("+++", intType, intType, nop); |
duke@1 | 574 | |
vromero@1845 | 575 | enterUnop("---", doubleType, doubleType, dneg); |
vromero@1845 | 576 | enterUnop("---", floatType, floatType, fneg); |
vromero@1845 | 577 | enterUnop("---", longType, longType, lneg); |
vromero@1845 | 578 | enterUnop("---", intType, intType, ineg); |
duke@1 | 579 | |
duke@1 | 580 | enterUnop("~", longType, longType, lxor); |
duke@1 | 581 | enterUnop("~", intType, intType, ixor); |
duke@1 | 582 | |
duke@1 | 583 | enterUnop("++", doubleType, doubleType, dadd); |
duke@1 | 584 | enterUnop("++", floatType, floatType, fadd); |
duke@1 | 585 | enterUnop("++", longType, longType, ladd); |
duke@1 | 586 | enterUnop("++", intType, intType, iadd); |
duke@1 | 587 | enterUnop("++", charType, charType, iadd); |
duke@1 | 588 | enterUnop("++", shortType, shortType, iadd); |
duke@1 | 589 | enterUnop("++", byteType, byteType, iadd); |
duke@1 | 590 | |
duke@1 | 591 | enterUnop("--", doubleType, doubleType, dsub); |
duke@1 | 592 | enterUnop("--", floatType, floatType, fsub); |
duke@1 | 593 | enterUnop("--", longType, longType, lsub); |
duke@1 | 594 | enterUnop("--", intType, intType, isub); |
duke@1 | 595 | enterUnop("--", charType, charType, isub); |
duke@1 | 596 | enterUnop("--", shortType, shortType, isub); |
duke@1 | 597 | enterUnop("--", byteType, byteType, isub); |
duke@1 | 598 | |
duke@1 | 599 | enterUnop("!", booleanType, booleanType, bool_not); |
duke@1 | 600 | nullcheck = enterUnop("<*nullchk*>", objectType, objectType, nullchk); |
duke@1 | 601 | |
duke@1 | 602 | // string concatenation |
duke@1 | 603 | enterBinop("+", stringType, objectType, stringType, string_add); |
duke@1 | 604 | enterBinop("+", objectType, stringType, stringType, string_add); |
duke@1 | 605 | enterBinop("+", stringType, stringType, stringType, string_add); |
duke@1 | 606 | enterBinop("+", stringType, intType, stringType, string_add); |
duke@1 | 607 | enterBinop("+", stringType, longType, stringType, string_add); |
duke@1 | 608 | enterBinop("+", stringType, floatType, stringType, string_add); |
duke@1 | 609 | enterBinop("+", stringType, doubleType, stringType, string_add); |
duke@1 | 610 | enterBinop("+", stringType, booleanType, stringType, string_add); |
duke@1 | 611 | enterBinop("+", stringType, botType, stringType, string_add); |
duke@1 | 612 | enterBinop("+", intType, stringType, stringType, string_add); |
duke@1 | 613 | enterBinop("+", longType, stringType, stringType, string_add); |
duke@1 | 614 | enterBinop("+", floatType, stringType, stringType, string_add); |
duke@1 | 615 | enterBinop("+", doubleType, stringType, stringType, string_add); |
duke@1 | 616 | enterBinop("+", booleanType, stringType, stringType, string_add); |
duke@1 | 617 | enterBinop("+", botType, stringType, stringType, string_add); |
duke@1 | 618 | |
duke@1 | 619 | // these errors would otherwise be matched as string concatenation |
duke@1 | 620 | enterBinop("+", botType, botType, botType, error); |
duke@1 | 621 | enterBinop("+", botType, intType, botType, error); |
duke@1 | 622 | enterBinop("+", botType, longType, botType, error); |
duke@1 | 623 | enterBinop("+", botType, floatType, botType, error); |
duke@1 | 624 | enterBinop("+", botType, doubleType, botType, error); |
duke@1 | 625 | enterBinop("+", botType, booleanType, botType, error); |
duke@1 | 626 | enterBinop("+", botType, objectType, botType, error); |
duke@1 | 627 | enterBinop("+", intType, botType, botType, error); |
duke@1 | 628 | enterBinop("+", longType, botType, botType, error); |
duke@1 | 629 | enterBinop("+", floatType, botType, botType, error); |
duke@1 | 630 | enterBinop("+", doubleType, botType, botType, error); |
duke@1 | 631 | enterBinop("+", booleanType, botType, botType, error); |
duke@1 | 632 | enterBinop("+", objectType, botType, botType, error); |
duke@1 | 633 | |
duke@1 | 634 | enterBinop("+", doubleType, doubleType, doubleType, dadd); |
duke@1 | 635 | enterBinop("+", floatType, floatType, floatType, fadd); |
duke@1 | 636 | enterBinop("+", longType, longType, longType, ladd); |
duke@1 | 637 | enterBinop("+", intType, intType, intType, iadd); |
duke@1 | 638 | |
duke@1 | 639 | enterBinop("-", doubleType, doubleType, doubleType, dsub); |
duke@1 | 640 | enterBinop("-", floatType, floatType, floatType, fsub); |
duke@1 | 641 | enterBinop("-", longType, longType, longType, lsub); |
duke@1 | 642 | enterBinop("-", intType, intType, intType, isub); |
duke@1 | 643 | |
duke@1 | 644 | enterBinop("*", doubleType, doubleType, doubleType, dmul); |
duke@1 | 645 | enterBinop("*", floatType, floatType, floatType, fmul); |
duke@1 | 646 | enterBinop("*", longType, longType, longType, lmul); |
duke@1 | 647 | enterBinop("*", intType, intType, intType, imul); |
duke@1 | 648 | |
duke@1 | 649 | enterBinop("/", doubleType, doubleType, doubleType, ddiv); |
duke@1 | 650 | enterBinop("/", floatType, floatType, floatType, fdiv); |
duke@1 | 651 | enterBinop("/", longType, longType, longType, ldiv); |
duke@1 | 652 | enterBinop("/", intType, intType, intType, idiv); |
duke@1 | 653 | |
duke@1 | 654 | enterBinop("%", doubleType, doubleType, doubleType, dmod); |
duke@1 | 655 | enterBinop("%", floatType, floatType, floatType, fmod); |
duke@1 | 656 | enterBinop("%", longType, longType, longType, lmod); |
duke@1 | 657 | enterBinop("%", intType, intType, intType, imod); |
duke@1 | 658 | |
duke@1 | 659 | enterBinop("&", booleanType, booleanType, booleanType, iand); |
duke@1 | 660 | enterBinop("&", longType, longType, longType, land); |
duke@1 | 661 | enterBinop("&", intType, intType, intType, iand); |
duke@1 | 662 | |
duke@1 | 663 | enterBinop("|", booleanType, booleanType, booleanType, ior); |
duke@1 | 664 | enterBinop("|", longType, longType, longType, lor); |
duke@1 | 665 | enterBinop("|", intType, intType, intType, ior); |
duke@1 | 666 | |
duke@1 | 667 | enterBinop("^", booleanType, booleanType, booleanType, ixor); |
duke@1 | 668 | enterBinop("^", longType, longType, longType, lxor); |
duke@1 | 669 | enterBinop("^", intType, intType, intType, ixor); |
duke@1 | 670 | |
duke@1 | 671 | enterBinop("<<", longType, longType, longType, lshll); |
duke@1 | 672 | enterBinop("<<", intType, longType, intType, ishll); |
duke@1 | 673 | enterBinop("<<", longType, intType, longType, lshl); |
duke@1 | 674 | enterBinop("<<", intType, intType, intType, ishl); |
duke@1 | 675 | |
duke@1 | 676 | enterBinop(">>", longType, longType, longType, lshrl); |
duke@1 | 677 | enterBinop(">>", intType, longType, intType, ishrl); |
duke@1 | 678 | enterBinop(">>", longType, intType, longType, lshr); |
duke@1 | 679 | enterBinop(">>", intType, intType, intType, ishr); |
duke@1 | 680 | |
duke@1 | 681 | enterBinop(">>>", longType, longType, longType, lushrl); |
duke@1 | 682 | enterBinop(">>>", intType, longType, intType, iushrl); |
duke@1 | 683 | enterBinop(">>>", longType, intType, longType, lushr); |
duke@1 | 684 | enterBinop(">>>", intType, intType, intType, iushr); |
duke@1 | 685 | |
duke@1 | 686 | enterBinop("<", doubleType, doubleType, booleanType, dcmpg, iflt); |
duke@1 | 687 | enterBinop("<", floatType, floatType, booleanType, fcmpg, iflt); |
duke@1 | 688 | enterBinop("<", longType, longType, booleanType, lcmp, iflt); |
duke@1 | 689 | enterBinop("<", intType, intType, booleanType, if_icmplt); |
duke@1 | 690 | |
duke@1 | 691 | enterBinop(">", doubleType, doubleType, booleanType, dcmpl, ifgt); |
duke@1 | 692 | enterBinop(">", floatType, floatType, booleanType, fcmpl, ifgt); |
duke@1 | 693 | enterBinop(">", longType, longType, booleanType, lcmp, ifgt); |
duke@1 | 694 | enterBinop(">", intType, intType, booleanType, if_icmpgt); |
duke@1 | 695 | |
duke@1 | 696 | enterBinop("<=", doubleType, doubleType, booleanType, dcmpg, ifle); |
duke@1 | 697 | enterBinop("<=", floatType, floatType, booleanType, fcmpg, ifle); |
duke@1 | 698 | enterBinop("<=", longType, longType, booleanType, lcmp, ifle); |
duke@1 | 699 | enterBinop("<=", intType, intType, booleanType, if_icmple); |
duke@1 | 700 | |
duke@1 | 701 | enterBinop(">=", doubleType, doubleType, booleanType, dcmpl, ifge); |
duke@1 | 702 | enterBinop(">=", floatType, floatType, booleanType, fcmpl, ifge); |
duke@1 | 703 | enterBinop(">=", longType, longType, booleanType, lcmp, ifge); |
duke@1 | 704 | enterBinop(">=", intType, intType, booleanType, if_icmpge); |
duke@1 | 705 | |
duke@1 | 706 | enterBinop("==", objectType, objectType, booleanType, if_acmpeq); |
duke@1 | 707 | enterBinop("==", booleanType, booleanType, booleanType, if_icmpeq); |
duke@1 | 708 | enterBinop("==", doubleType, doubleType, booleanType, dcmpl, ifeq); |
duke@1 | 709 | enterBinop("==", floatType, floatType, booleanType, fcmpl, ifeq); |
duke@1 | 710 | enterBinop("==", longType, longType, booleanType, lcmp, ifeq); |
duke@1 | 711 | enterBinop("==", intType, intType, booleanType, if_icmpeq); |
duke@1 | 712 | |
duke@1 | 713 | enterBinop("!=", objectType, objectType, booleanType, if_acmpne); |
duke@1 | 714 | enterBinop("!=", booleanType, booleanType, booleanType, if_icmpne); |
duke@1 | 715 | enterBinop("!=", doubleType, doubleType, booleanType, dcmpl, ifne); |
duke@1 | 716 | enterBinop("!=", floatType, floatType, booleanType, fcmpl, ifne); |
duke@1 | 717 | enterBinop("!=", longType, longType, booleanType, lcmp, ifne); |
duke@1 | 718 | enterBinop("!=", intType, intType, booleanType, if_icmpne); |
duke@1 | 719 | |
duke@1 | 720 | enterBinop("&&", booleanType, booleanType, booleanType, bool_and); |
duke@1 | 721 | enterBinop("||", booleanType, booleanType, booleanType, bool_or); |
duke@1 | 722 | } |
duke@1 | 723 | } |