< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java

Print this page
@@ -806,11 +806,11 @@
          for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
              ClassSymbol c = l.head;
              if (isTranslatedClassAvailable(c))
                  continue;
              // Create class definition tree.
-             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
+             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
                      c.outermostClass(), c.flatname, false);
              swapAccessConstructorTag(c, cdec.sym);
              translated.append(cdec);
          }
      }

@@ -1132,10 +1132,13 @@
          }
          JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
          switch (sym.kind) {
          case TYP:
              if (sym.owner.kind != PCK) {
+                 // Make sure not to lose type fidelity due to symbol sharing between projections
+                 boolean requireReferenceProjection =
+                         tree.hasTag(SELECT) && ((JCFieldAccess) tree).name == names.ref && tree.type.isReferenceProjection();
                  // Convert type idents to
                  // <flat name> or <package name> . <flat name>
                  Name flatname = Convert.shortName(sym.flatName());
                  while (base != null &&
                         TreeInfo.symbol(base) != null &&

@@ -1147,13 +1150,19 @@
                  if (tree.hasTag(IDENT)) {
                      ((JCIdent) tree).name = flatname;
                  } else if (base == null) {
                      tree = make.at(tree.pos).Ident(sym);
                      ((JCIdent) tree).name = flatname;
+                     if (requireReferenceProjection) {
+                         tree.setType(tree.type.referenceProjection());
+                     }
                  } else {
                      ((JCFieldAccess) tree).selected = base;
                      ((JCFieldAccess) tree).name = flatname;
+                     if (requireReferenceProjection) {
+                         tree.setType(tree.type.referenceProjection());
+                     }
                  }
              }
              break;
          case MTH: case VAR:
              if (sym.owner.kind == TYP) {

@@ -1278,11 +1287,11 @@
              Name flatname = names.fromString("" + topClass.getQualifiedName() +
                                              target.syntheticNameChar() +
                                              i);
              ClassSymbol ctag = chk.getCompiled(topModle, flatname);
              if (ctag == null)
-                 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
+                 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
              else if (!ctag.isAnonymous())
                  continue;
              // keep a record of all tags, to verify that all are generated as required
              accessConstrTags = accessConstrTags.prepend(ctag);
              return ctag;

@@ -1454,12 +1463,13 @@
              int index = 0;
              Name proxyName;
              do {
                  proxyName = proxyName(v.name, index++);
              } while (!proxyNames.add(proxyName));
+             final Type type = v.erasure(types);
              VarSymbol proxy = new VarSymbol(
-                 flags, proxyName, v.erasure(types), owner);
+                 flags, proxyName, type, owner);
              proxies.put(v, proxy);
              JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
              vd.vartype = access(vd.vartype);
              defs = defs.prepend(vd);
          }

@@ -1522,11 +1532,13 @@
      /** Definition for this$n field.
       *  @param pos        The source code position of the definition.
       *  @param owner      The class in which the definition goes.
       */
      JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
-         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
+         Type target = types.erasure(owner.enclClass().type.getEnclosingType());
+         long flags = FINAL | SYNTHETIC;
+         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
          return makeOuterThisVarDecl(pos, outerThis);
      }
  
      /** Return a list of trees that load the free variables in given list,
       *  in reverse order.

@@ -1705,11 +1717,11 @@
          return newBlock;
      }
  
      private JCStatement makeResourceCloseInvocation(JCExpression resource) {
          // convert to AutoCloseable if needed
-         if (types.asSuper(resource.type, syms.autoCloseableType.tsym) == null) {
+         if (types.asSuper(resource.type.referenceProjectionOrSelf(), syms.autoCloseableType.tsym) == null) {
              resource = convert(resource, syms.autoCloseableType);
          }
  
          // create resource.close() method invocation
          JCExpression resourceClose = makeCall(resource,

@@ -1857,11 +1869,11 @@
          Scope s = clazz.members();
          for (Symbol sym : s.getSymbols(NON_RECURSIVE))
              if (sym.kind == TYP &&
                  sym.name == names.empty &&
                  (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
-         return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;
+         return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
      }
  
      /** Create an attributed tree of the form left.name(). */
      private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
          Assert.checkNonNull(left.type);

@@ -1909,11 +1921,11 @@
      /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
       */
      private ClassSymbol assertionsDisabledClass() {
          if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
  
-         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;
+         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
  
          return assertionsDisabledClassCache;
      }
  
      // This code is not particularly robust if the user has

@@ -2089,11 +2101,12 @@
      }
  
      /** Visitor method: Translate a single node, boxing or unboxing if needed.
       */
      public <T extends JCExpression> T translate(T tree, Type type) {
-         return (tree == null) ? null : boxIfNeeded(translate(tree), type);
+         return (tree == null) ? null :
+                 applyPrimitiveConversionsAsNeeded(boxIfNeeded(translate(tree), type), type);
      }
  
      /** Visitor method: Translate tree.
       */
      public <T extends JCTree> T translate(T tree, JCExpression enclOp) {

@@ -2228,11 +2241,11 @@
              seen = unseen;
          }
  
          // Convert a protected modifier to public, mask static modifier.
          if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
-         tree.mods.flags &= ClassFlags;
+         tree.mods.flags &= AdjustedClassFlags;
  
          // Convert name to flat representation, replacing '.' by '$'.
          tree.name = Convert.shortName(currentClass.flatName());
  
          // Add free variables proxy definitions to class.

@@ -3107,10 +3120,24 @@
              if (!anyChanges) return _args;
          }
          return result.toList();
      }
  
+     /** Apply primitive value/reference conversions as needed */
+     @SuppressWarnings("unchecked")
+     <T extends JCExpression> T applyPrimitiveConversionsAsNeeded(T tree, Type type) {
+         boolean haveValue = tree.type.isPrimitiveClass();
+         if (haveValue == type.isPrimitiveClass())
+             return tree;
+         // For narrowing conversion, insert a cast which should trigger a null check
+         // For widening conversions, insert a cast if emitting a unified class file.
+         return (T) make.TypeCast(type, tree);
+ 
+     }
+ 
+ 
+ 
      /** Expand a boxing or unboxing conversion if needed. */
      @SuppressWarnings("unchecked") // XXX unchecked
      <T extends JCExpression> T boxIfNeeded(T tree, Type type) {
          boolean havePrimitive = tree.type.isPrimitive();
          if (havePrimitive == type.isPrimitive())

@@ -3505,11 +3532,11 @@
           * where #i is a freshly named synthetic local variable.
           */
          private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
              make_at(tree.expr.pos());
              Type iteratorTarget = syms.objectType;
-             Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type),
+             Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type.referenceProjectionOrSelf()),
                                                syms.iterableType.tsym);
              if (iterableType.getTypeArguments().nonEmpty())
                  iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
              Type eType = types.skipTypeVars(tree.expr.type, false);
              tree.expr.type = types.erasure(eType);

@@ -3518,11 +3545,11 @@
              Symbol iterator = lookupMethod(tree.expr.pos(),
                                             names.iterator,
                                             eType,
                                             List.nil());
              VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
-                                             types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)),
+                                             types.erasure(types.asSuper(iterator.type.getReturnType().referenceProjectionOrSelf(), syms.iteratorType.tsym)),
                                              currentMethodSym);
  
               JCStatement init = make.
                  VarDef(itvar, make.App(make.Select(tree.expr, iterator)
                       .setType(types.erasure(iterator.type))));

@@ -3595,10 +3622,27 @@
          tree.cond = translate(tree.cond, syms.booleanType);
          tree.body = translate(tree.body);
          result = tree;
      }
  
+     public void visitWithField(JCWithField tree) {
+         Type fieldType = tree.field.type;
+         tree.field = translate(tree.field, tree);
+         tree.value = translate(tree.value, fieldType); // important to use pre-translation type.
+ 
+         // If translated field is an Apply, we are
+         // seeing an access method invocation. In this case, append
+         // right hand side as last argument of the access method.
+         if (tree.field.hasTag(APPLY)) {
+             JCMethodInvocation app = (JCMethodInvocation) tree.field;
+             app.args = List.of(tree.value).prependList(app.args);
+             result = app;
+         } else {
+             result = tree;
+         }
+     }
+ 
      public void visitForLoop(JCForLoop tree) {
          tree.init = translate(tree.init);
          if (tree.cond != null)
              tree.cond = translate(tree.cond, syms.booleanType);
          tree.step = translate(tree.step);

@@ -4073,19 +4117,27 @@
          // is a default interface subclassed by the current class.
          boolean qualifiedSuperAccess =
              tree.selected.hasTag(SELECT) &&
              TreeInfo.name(tree.selected) == names._super &&
              !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
+         /* JDK-8269956: Where a reflective (class) literal is needed, the unqualified Point.class is
+          * always the "primary" mirror - representing the primitive reference runtime type - thereby
+          * always matching the behavior of Object::getClass
+          */
+         boolean needPrimaryMirror = tree.name == names._class && tree.selected.type.isReferenceProjection();
          tree.selected = translate(tree.selected);
+         if (needPrimaryMirror && tree.selected.type.isPrimitiveClass()) {
+             tree.selected.setType(tree.selected.type.referenceProjection());
+         }
          if (tree.name == names._class) {
              result = classOf(tree.selected);
          }
          else if (tree.name == names._super &&
                  types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
              //default super call!! Not a classic qualified super call
              TypeSymbol supSym = tree.selected.type.tsym;
-             Assert.checkNonNull(types.asSuper(currentClass.type, supSym));
+             Assert.checkNonNull(types.asSuper(currentClass.type.referenceProjectionOrSelf(), supSym));
              result = tree;
          }
          else if (tree.name == names._this || tree.name == names._super) {
              result = makeThis(tree.pos(), tree.selected.type.tsym);
          }
< prev index next >