src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
author Dusan Balek <dbalek@netbeans.org>
Mon, 31 Jul 2017 11:07:41 +0200
changeset 5955 f54cccaf6e6c
parent 5947 554b3c813685
child 5958 b5d5effa0977
permissions -rw-r--r--
Mergin jlahoda's fix of #8182450: javac aborts when generating ct.sym intermittently - Initialize the module system model even in presence of missing/broken module-infos; BadClassFiles should not immediatelly abort compilation anymore, but should be handled as if the classfile did not exist.
duke@0
     1
/*
vromero@5651
     2
 * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
duke@0
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0
     4
 *
duke@0
     5
 * This code is free software; you can redistribute it and/or modify it
duke@0
     6
 * under the terms of the GNU General Public License version 2 only, as
ohair@961
     7
 * published by the Free Software Foundation.  Oracle designates this
duke@0
     8
 * particular file as subject to the "Classpath" exception as provided
ohair@961
     9
 * by Oracle in the LICENSE file that accompanied this code.
duke@0
    10
 *
duke@0
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
duke@0
    14
 * version 2 for more details (a copy is included in the LICENSE file that
duke@0
    15
 * accompanied this code).
duke@0
    16
 *
duke@0
    17
 * You should have received a copy of the GNU General Public License version
duke@0
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0
    20
 *
ohair@961
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@961
    22
 * or visit www.oracle.com if you need additional information or have any
ohair@961
    23
 * questions.
duke@0
    24
 */
duke@0
    25
duke@0
    26
package com.sun.tools.javac.comp;
duke@0
    27
duke@0
    28
import java.util.*;
jjg@2372
    29
ohrstrom@2227
    30
import javax.tools.JavaFileManager;
dbalek@2330
    31
import javax.lang.model.element.ElementKind;
duke@0
    32
duke@0
    33
import com.sun.tools.javac.code.*;
jlahoda@3135
    34
import com.sun.tools.javac.code.Attribute.Compound;
jlahoda@5433
    35
import com.sun.tools.javac.code.Directive.ExportsDirective;
jlahoda@5433
    36
import com.sun.tools.javac.code.Directive.RequiresDirective;
jjg@4454
    37
import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
duke@0
    38
import com.sun.tools.javac.jvm.*;
sadayapalam@4445
    39
import com.sun.tools.javac.resources.CompilerProperties.Errors;
sadayapalam@4445
    40
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
jlahoda@5433
    41
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
duke@0
    42
import com.sun.tools.javac.tree.*;
duke@0
    43
import com.sun.tools.javac.util.*;
sadayapalam@4546
    44
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
duke@0
    45
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
duke@0
    46
import com.sun.tools.javac.util.List;
duke@0
    47
duke@0
    48
import com.sun.tools.javac.code.Lint;
duke@0
    49
import com.sun.tools.javac.code.Lint.LintCategory;
jlahoda@4103
    50
import com.sun.tools.javac.code.Scope.WriteableScope;
duke@0
    51
import com.sun.tools.javac.code.Type.*;
duke@0
    52
import com.sun.tools.javac.code.Symbol.*;
mcimadamore@2190
    53
import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
mcimadamore@2431
    54
import com.sun.tools.javac.comp.Infer.FreeTypeListener;
mcimadamore@2361
    55
import com.sun.tools.javac.tree.JCTree.*;
duke@0
    56
duke@0
    57
import static com.sun.tools.javac.code.Flags.*;
jjg@1972
    58
import static com.sun.tools.javac.code.Flags.ANNOTATION;
jjg@1972
    59
import static com.sun.tools.javac.code.Flags.SYNCHRONIZED;
duke@0
    60
import static com.sun.tools.javac.code.Kinds.*;
emc@4248
    61
import static com.sun.tools.javac.code.Kinds.Kind.*;
jlahoda@4103
    62
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
jjg@2213
    63
import static com.sun.tools.javac.code.TypeTag.*;
jjg@2213
    64
import static com.sun.tools.javac.code.TypeTag.WILDCARD;
duke@0
    65
jjg@1972
    66
import static com.sun.tools.javac.tree.JCTree.Tag.*;
jjg@1132
    67
duke@0
    68
/** Type checking helper class for the attribution phase.
duke@0
    69
 *
jjg@971
    70
 *  <p><b>This is NOT part of any supported API.
jjg@971
    71
 *  If you write code that depends on this, you do so at your own risk.
duke@0
    72
 *  This code and its internal interfaces are subject to change or
duke@0
    73
 *  deletion without notice.</b>
duke@0
    74
 */
duke@0
    75
public class Check {
briangoetz@3808
    76
    protected static final Context.Key<Check> checkKey = new Context.Key<>();
duke@0
    77
jjg@294
    78
    private final Names names;
duke@0
    79
    private final Log log;
mcimadamore@2062
    80
    private final Resolve rs;
duke@0
    81
    private final Symtab syms;
mcimadamore@1122
    82
    private final Enter enter;
mcimadamore@2190
    83
    private final DeferredAttr deferredAttr;
duke@0
    84
    private final Infer infer;
duke@0
    85
    private final Types types;
jjg@4454
    86
    private final TypeAnnotations typeAnnotations;
mcimadamore@268
    87
    private final JCDiagnostic.Factory diags;
ohrstrom@2227
    88
    private final JavaFileManager fileManager;
sadayapalam@4445
    89
    private final Source source;
jjg@2470
    90
    private final Profile profile;
vromero@5460
    91
    private final boolean warnOnAnyAccessToMembers;
duke@0
    92
duke@0
    93
    // The set of lint options currently in effect. It is initialized
duke@0
    94
    // from the context, and then is set/reset as needed by Attr as it
duke@0
    95
    // visits all the various parts of the trees during attribution.
duke@0
    96
    private Lint lint;
duke@0
    97
mcimadamore@1244
    98
    // The method being analyzed in Attr - it is set/reset as needed by
mcimadamore@1244
    99
    // Attr as it visits new method declarations.
mcimadamore@1244
   100
    private MethodSymbol method;
mcimadamore@1244
   101
duke@0
   102
    public static Check instance(Context context) {
duke@0
   103
        Check instance = context.get(checkKey);
duke@0
   104
        if (instance == null)
duke@0
   105
            instance = new Check(context);
duke@0
   106
        return instance;
duke@0
   107
    }
duke@0
   108
duke@0
   109
    protected Check(Context context) {
duke@0
   110
        context.put(checkKey, this);
duke@0
   111
jjg@294
   112
        names = Names.instance(context);
jjg@2372
   113
        dfltTargetMeta = new Name[] { names.PACKAGE, names.TYPE,
jjg@2372
   114
            names.FIELD, names.METHOD, names.CONSTRUCTOR,
jjg@2372
   115
            names.ANNOTATION_TYPE, names.LOCAL_VARIABLE, names.PARAMETER};
duke@0
   116
        log = Log.instance(context);
mcimadamore@2062
   117
        rs = Resolve.instance(context);
duke@0
   118
        syms = Symtab.instance(context);
mcimadamore@1122
   119
        enter = Enter.instance(context);
mcimadamore@2190
   120
        deferredAttr = DeferredAttr.instance(context);
duke@0
   121
        infer = Infer.instance(context);
jjg@2470
   122
        types = Types.instance(context);
jjg@4454
   123
        typeAnnotations = TypeAnnotations.instance(context);
mcimadamore@268
   124
        diags = JCDiagnostic.Factory.instance(context);
duke@0
   125
        Options options = Options.instance(context);
duke@0
   126
        lint = Lint.instance(context);
ohrstrom@2227
   127
        fileManager = context.get(JavaFileManager.class);
duke@0
   128
sadayapalam@4445
   129
        source = Source.instance(context);
mcimadamore@1244
   130
        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
mcimadamore@2234
   131
        allowDefaultMethods = source.allowDefaultMethods();
mcimadamore@2260
   132
        allowStrictMethodClashCheck = source.allowStrictMethodClashCheck();
darcy@4063
   133
        allowPrivateSafeVarargs = source.allowPrivateSafeVarargs();
sadayapalam@4445
   134
        allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation();
vromero@5460
   135
        warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers");
duke@0
   136
jjg@688
   137
        Target target = Target.instance(context);
jjg@688
   138
        syntheticNameChar = target.syntheticNameChar();
jjg@688
   139
jjg@2470
   140
        profile = Profile.instance(context);
jjg@2470
   141
duke@0
   142
        boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION);
jjg@5468
   143
        boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL);
duke@0
   144
        boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED);
ntoda@4105
   145
        boolean enforceMandatoryWarnings = true;
duke@0
   146
jjg@234
   147
        deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated,
jjg@1008
   148
                enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION);
jjg@5468
   149
        removalHandler = new MandatoryWarningHandler(log, verboseRemoval,
jjg@5468
   150
                enforceMandatoryWarnings, "removal", LintCategory.REMOVAL);
jjg@234
   151
        uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked,
jjg@1008
   152
                enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED);
vromero@4965
   153
        sunApiHandler = new MandatoryWarningHandler(log, false,
jjg@1008
   154
                enforceMandatoryWarnings, "sunapi", null);
mcimadamore@1317
   155
jlahoda@3044
   156
        deferredLintHandler = DeferredLintHandler.instance(context);
duke@0
   157
    }
duke@0
   158
mcimadamore@1244
   159
    /** Switch: simplified varargs enabled?
mcimadamore@1244
   160
     */
mcimadamore@1244
   161
    boolean allowSimplifiedVarargs;
mcimadamore@1244
   162
mcimadamore@2234
   163
    /** Switch: default methods enabled?
mcimadamore@2234
   164
     */
mcimadamore@2234
   165
    boolean allowDefaultMethods;
mcimadamore@2234
   166
mcimadamore@2234
   167
    /** Switch: should unrelated return types trigger a method clash?
mcimadamore@2234
   168
     */
mcimadamore@2234
   169
    boolean allowStrictMethodClashCheck;
mcimadamore@2234
   170
darcy@4063
   171
    /** Switch: can the @SafeVarargs annotation be applied to private methods?
darcy@4063
   172
     */
darcy@4063
   173
    boolean allowPrivateSafeVarargs;
darcy@4063
   174
sadayapalam@4445
   175
    /** Switch: can diamond inference be used in anonymous instance creation ?
sadayapalam@4445
   176
     */
sadayapalam@4445
   177
    boolean allowDiamondWithAnonymousClassCreation;
sadayapalam@4445
   178
jjg@688
   179
    /** Character for synthetic names
jjg@688
   180
     */
jjg@688
   181
    char syntheticNameChar;
jjg@688
   182
alanb@5016
   183
    /** A table mapping flat names of all compiled classes for each module in this run
alanb@5016
   184
     *  to their symbols; maintained from outside.
duke@0
   185
     */
alanb@5016
   186
    private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>();
duke@0
   187
duke@0
   188
    /** A handler for messages about deprecated usage.
duke@0
   189
     */
duke@0
   190
    private MandatoryWarningHandler deprecationHandler;
duke@0
   191
jjg@5468
   192
    /** A handler for messages about deprecated-for-removal usage.
jjg@5468
   193
     */
jjg@5468
   194
    private MandatoryWarningHandler removalHandler;
jjg@5468
   195
duke@0
   196
    /** A handler for messages about unchecked or unsafe usage.
duke@0
   197
     */
duke@0
   198
    private MandatoryWarningHandler uncheckedHandler;
duke@0
   199
jjg@972
   200
    /** A handler for messages about using proprietary API.
jjg@667
   201
     */
jjg@667
   202
    private MandatoryWarningHandler sunApiHandler;
duke@0
   203
mcimadamore@1317
   204
    /** A handler for deferred lint warnings.
mcimadamore@1317
   205
     */
mcimadamore@1317
   206
    private DeferredLintHandler deferredLintHandler;
mcimadamore@1317
   207
duke@0
   208
/* *************************************************************************
duke@0
   209
 * Errors and Warnings
duke@0
   210
 **************************************************************************/
duke@0
   211
duke@0
   212
    Lint setLint(Lint newLint) {
duke@0
   213
        Lint prev = lint;
duke@0
   214
        lint = newLint;
duke@0
   215
        return prev;
duke@0
   216
    }
duke@0
   217
mcimadamore@1244
   218
    MethodSymbol setMethod(MethodSymbol newMethod) {
mcimadamore@1244
   219
        MethodSymbol prev = method;
mcimadamore@1244
   220
        method = newMethod;
mcimadamore@1244
   221
        return prev;
mcimadamore@1244
   222
    }
mcimadamore@1244
   223
duke@0
   224
    /** Warn about deprecated symbol.
duke@0
   225
     *  @param pos        Position to be used for error reporting.
duke@0
   226
     *  @param sym        The deprecated symbol.
duke@0
   227
     */
duke@0
   228
    void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
jjg@5468
   229
        if (sym.isDeprecatedForRemoval()) {
jjg@5468
   230
            if (!lint.isSuppressed(LintCategory.REMOVAL)) {
alanb@5550
   231
                if (sym.kind == MDL) {
alanb@5550
   232
                    removalHandler.report(pos, "has.been.deprecated.for.removal.module", sym);
alanb@5550
   233
                } else {
alanb@5550
   234
                    removalHandler.report(pos, "has.been.deprecated.for.removal", sym, sym.location());
alanb@5550
   235
                }
jjg@5468
   236
            }
jjg@5468
   237
        } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) {
alanb@5550
   238
            if (sym.kind == MDL) {
alanb@5550
   239
                deprecationHandler.report(pos, "has.been.deprecated.module", sym);
alanb@5550
   240
            } else {
alanb@5550
   241
                deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location());
alanb@5550
   242
            }
jjg@5468
   243
        }
duke@0
   244
    }
duke@0
   245
duke@0
   246
    /** Warn about unchecked operation.
duke@0
   247
     *  @param pos        Position to be used for error reporting.
duke@0
   248
     *  @param msg        A string describing the problem.
duke@0
   249
     */
duke@0
   250
    public void warnUnchecked(DiagnosticPosition pos, String msg, Object... args) {
duke@0
   251
        if (!lint.isSuppressed(LintCategory.UNCHECKED))
duke@0
   252
            uncheckedHandler.report(pos, msg, args);
duke@0
   253
    }
duke@0
   254
mcimadamore@970
   255
    /** Warn about unsafe vararg method decl.
mcimadamore@970
   256
     *  @param pos        Position to be used for error reporting.
mcimadamore@970
   257
     */
mcimadamore@1244
   258
    void warnUnsafeVararg(DiagnosticPosition pos, String key, Object... args) {
mcimadamore@1244
   259
        if (lint.isEnabled(LintCategory.VARARGS) && allowSimplifiedVarargs)
mcimadamore@1244
   260
            log.warning(LintCategory.VARARGS, pos, key, args);
mcimadamore@970
   261
    }
mcimadamore@970
   262
jjg@898
   263
    public void warnStatic(DiagnosticPosition pos, String msg, Object... args) {
jjg@898
   264
        if (lint.isEnabled(LintCategory.STATIC))
jjg@1008
   265
            log.warning(LintCategory.STATIC, pos, msg, args);
jjg@898
   266
    }
jjg@898
   267
jlahoda@4081
   268
    /** Warn about division by integer constant zero.
jlahoda@4081
   269
     *  @param pos        Position to be used for error reporting.
jlahoda@4081
   270
     */
jlahoda@4081
   271
    void warnDivZero(DiagnosticPosition pos) {
jlahoda@4081
   272
        if (lint.isEnabled(LintCategory.DIVZERO))
jlahoda@4081
   273
            log.warning(LintCategory.DIVZERO, pos, "div.zero");
jlahoda@4081
   274
    }
jlahoda@4081
   275
duke@0
   276
    /**
duke@0
   277
     * Report any deferred diagnostics.
duke@0
   278
     */
duke@0
   279
    public void reportDeferredDiagnostics() {
duke@0
   280
        deprecationHandler.reportDeferredDiagnostic();
jjg@5468
   281
        removalHandler.reportDeferredDiagnostic();
duke@0
   282
        uncheckedHandler.reportDeferredDiagnostic();
jjg@667
   283
        sunApiHandler.reportDeferredDiagnostic();
duke@0
   284
    }
duke@0
   285
duke@0
   286
duke@0
   287
    /** Report a failure to complete a class.
duke@0
   288
     *  @param pos        Position to be used for error reporting.
duke@0
   289
     *  @param ex         The failure to report.
duke@0
   290
     */
duke@0
   291
    public Type completionError(DiagnosticPosition pos, CompletionFailure ex) {
mcimadamore@2522
   292
        log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, "cant.access", ex.sym, ex.getDetailValue());
dbalek@5955
   293
        return syms.errType;
duke@0
   294
    }
duke@0
   295
duke@0
   296
    /** Report an error that wrong type tag was found.
duke@0
   297
     *  @param pos        Position to be used for error reporting.
duke@0
   298
     *  @param required   An internationalized string describing the type tag
duke@0
   299
     *                    required.
duke@0
   300
     *  @param found      The type that was found.
duke@0
   301
     */
duke@0
   302
    Type typeTagError(DiagnosticPosition pos, Object required, Object found) {
jrose@557
   303
        // this error used to be raised by the parser,
jrose@557
   304
        // but has been delayed to this point:
jjg@2213
   305
        if (found instanceof Type && ((Type)found).hasTag(VOID)) {
jrose@557
   306
            log.error(pos, "illegal.start.of.type");
jrose@557
   307
            return syms.errType;
jrose@557
   308
        }
duke@0
   309
        log.error(pos, "type.found.req", found, required);
jjg@289
   310
        return types.createErrorType(found instanceof Type ? (Type)found : syms.errType);
duke@0
   311
    }
duke@0
   312
duke@0
   313
    /** Report an error that symbol cannot be referenced before super
duke@0
   314
     *  has been called.
duke@0
   315
     *  @param pos        Position to be used for error reporting.
duke@0
   316
     *  @param sym        The referenced symbol.
duke@0
   317
     */
duke@0
   318
    void earlyRefError(DiagnosticPosition pos, Symbol sym) {
duke@0
   319
        log.error(pos, "cant.ref.before.ctor.called", sym);
duke@0
   320
    }
duke@0
   321
duke@0
   322
    /** Report duplicate declaration error.
duke@0
   323
     */
duke@0
   324
    void duplicateError(DiagnosticPosition pos, Symbol sym) {
duke@0
   325
        if (!sym.type.isErroneous()) {
dmeetry@1678
   326
            Symbol location = sym.location();
dmeetry@1678
   327
            if (location.kind == MTH &&
dmeetry@1678
   328
                    ((MethodSymbol)location).isStaticOrInstanceInit()) {
dmeetry@1678
   329
                log.error(pos, "already.defined.in.clinit", kindName(sym), sym,
dmeetry@1678
   330
                        kindName(sym.location()), kindName(sym.location().enclClass()),
dmeetry@1678
   331
                        sym.location().enclClass());
dmeetry@1678
   332
            } else {
dmeetry@1678
   333
                log.error(pos, "already.defined", kindName(sym), sym,
dmeetry@1678
   334
                        kindName(sym.location()), sym.location());
dmeetry@1678
   335
            }
duke@0
   336
        }
duke@0
   337
    }
duke@0
   338
duke@0
   339
    /** Report array/varargs duplicate declaration
duke@0
   340
     */
duke@0
   341
    void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
duke@0
   342
        if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
duke@0
   343
            log.error(pos, "array.and.varargs", sym1, sym2, sym2.location());
duke@0
   344
        }
duke@0
   345
    }
duke@0
   346
duke@0
   347
/* ************************************************************************
duke@0
   348
 * duplicate declaration checking
duke@0
   349
 *************************************************************************/
duke@0
   350
duke@0
   351
    /** Check that variable does not hide variable with same name in
duke@0
   352
     *  immediately enclosing local scope.
duke@0
   353
     *  @param pos           Position for error reporting.
duke@0
   354
     *  @param v             The symbol.
duke@0
   355
     *  @param s             The scope.
duke@0
   356
     */
duke@0
   357
    void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) {
jlahoda@4103
   358
        for (Symbol sym : s.getSymbolsByName(v.name)) {
jlahoda@4103
   359
            if (sym.owner != v.owner) break;
jlahoda@4103
   360
            if (sym.kind == VAR &&
emc@4248
   361
                sym.owner.kind.matches(KindSelector.VAL_MTH) &&
jlahoda@4103
   362
                v.name != names.error) {
jlahoda@4103
   363
                duplicateError(pos, sym);
jlahoda@4103
   364
                return;
duke@0
   365
            }
duke@0
   366
        }
duke@0
   367
    }
duke@0
   368
duke@0
   369
    /** Check that a class or interface does not hide a class or
duke@0
   370
     *  interface with same name in immediately enclosing local scope.
duke@0
   371
     *  @param pos           Position for error reporting.
duke@0
   372
     *  @param c             The symbol.
duke@0
   373
     *  @param s             The scope.
duke@0
   374
     */
duke@0
   375
    void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) {
jlahoda@4103
   376
        for (Symbol sym : s.getSymbolsByName(c.name)) {
jlahoda@4103
   377
            if (sym.owner != c.owner) break;
jlahoda@4103
   378
            if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR) &&
emc@4248
   379
                sym.owner.kind.matches(KindSelector.VAL_MTH) &&
jlahoda@4103
   380
                c.name != names.error) {
jlahoda@4103
   381
                duplicateError(pos, sym);
jlahoda@4103
   382
                return;
duke@0
   383
            }
duke@0
   384
        }
duke@0
   385
    }
duke@0
   386
duke@0
   387
    /** Check that class does not have the same name as one of
duke@0
   388
     *  its enclosing classes, or as a class defined in its enclosing scope.
duke@0
   389
     *  return true if class is unique in its enclosing scope.
duke@0
   390
     *  @param pos           Position for error reporting.
duke@0
   391
     *  @param name          The class name.
duke@0
   392
     *  @param s             The enclosing scope.
duke@0
   393
     */
duke@0
   394
    boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) {
jlahoda@4103
   395
        for (Symbol sym : s.getSymbolsByName(name, NON_RECURSIVE)) {
dbalek@4426
   396
            if (sym.kind == TYP) {
dbalek@4426
   397
                if (sym.name != names.error)
dbalek@4426
   398
                    duplicateError(pos, sym);
duke@0
   399
                return false;
duke@0
   400
            }
duke@0
   401
        }
duke@0
   402
        for (Symbol sym = s.owner; sym != null; sym = sym.owner) {
duke@0
   403
            if (sym.kind == TYP && sym.name == name && sym.name != names.error) {
duke@0
   404
                duplicateError(pos, sym);
duke@0
   405
                return true;
duke@0
   406
            }
duke@0
   407
        }
duke@0
   408
        return true;
duke@0
   409
    }
duke@0
   410
duke@0
   411
/* *************************************************************************
duke@0
   412
 * Class name generation
duke@0
   413
 **************************************************************************/
duke@0
   414
sadayapalam@4632
   415
sadayapalam@4632
   416
    private Map<Pair<Name, Name>, Integer> localClassNameIndexes = new HashMap<>();
sadayapalam@4632
   417
duke@0
   418
    /** Return name of local class.
jjg@2197
   419
     *  This is of the form   {@code <enclClass> $ n <classname> }
duke@0
   420
     *  where
duke@0
   421
     *    enclClass is the flat name of the enclosing class,
duke@0
   422
     *    classname is the simple name of the local class
duke@0
   423
     */
duke@0
   424
    Name localClassName(ClassSymbol c) {
sadayapalam@4632
   425
        Name enclFlatname = c.owner.enclClass().flatname;
sadayapalam@4632
   426
        String enclFlatnameStr = enclFlatname.toString();
sadayapalam@4632
   427
        Pair<Name, Name> key = new Pair<>(enclFlatname, c.name);
sadayapalam@4632
   428
        Integer index = localClassNameIndexes.get(key);
sadayapalam@4632
   429
        for (int i = (index == null) ? 1 : index; ; i++) {
sadayapalam@4632
   430
            Name flatname = names.fromString(enclFlatnameStr
sadayapalam@4632
   431
                    + syntheticNameChar + i + c.name);
alanb@5016
   432
            if (getCompiled(c.packge().modle, flatname) == null) {
sadayapalam@4632
   433
                localClassNameIndexes.put(key, i + 1);
sadayapalam@4632
   434
                return flatname;
sadayapalam@4632
   435
            }
duke@0
   436
        }
duke@0
   437
    }
duke@0
   438
jlahoda@5
   439
    Name localClassName (final ClassSymbol enclClass, final Name name, final int index) {
jlahoda@5
   440
        Name flatname = names.
jlahoda@5
   441
            fromString("" + enclClass.flatname +
dbalek@721
   442
                       syntheticNameChar + index +
jlahoda@5
   443
                       name);
jlahoda@5
   444
        return flatname;
jlahoda@5
   445
    }
jlahoda@5
   446
sadayapalam@4632
   447
    void clearLocalClassNameIndexes(ClassSymbol c) {
vromero@5651
   448
        if (c.owner != null && c.owner.kind != NIL) {
vromero@5651
   449
            localClassNameIndexes.remove(new Pair<>(
vromero@5651
   450
                    c.owner.enclClass().flatname, c.name));
vromero@5651
   451
        }
sadayapalam@4632
   452
    }
sadayapalam@4632
   453
jlahoda@3928
   454
    public void newRound() {
jlahoda@3928
   455
        compiled.clear();
sadayapalam@4632
   456
        localClassNameIndexes.clear();
jlahoda@3928
   457
    }
jlahoda@3928
   458
alanb@5016
   459
    public void putCompiled(ClassSymbol csym) {
alanb@5016
   460
        compiled.put(Pair.of(csym.packge().modle, csym.flatname), csym);
alanb@5016
   461
    }
alanb@5016
   462
alanb@5016
   463
    public ClassSymbol getCompiled(ClassSymbol csym) {
alanb@5016
   464
        return compiled.get(Pair.of(csym.packge().modle, csym.flatname));
alanb@5016
   465
    }
alanb@5016
   466
alanb@5016
   467
    public ClassSymbol getCompiled(ModuleSymbol msym, Name flatname) {
alanb@5016
   468
        return compiled.get(Pair.of(msym, flatname));
alanb@5016
   469
    }
alanb@5016
   470
alanb@5016
   471
    public void removeCompiled(ClassSymbol csym) {
alanb@5016
   472
        compiled.remove(Pair.of(csym.packge().modle, csym.flatname));
alanb@5016
   473
    }
alanb@5016
   474
duke@0
   475
/* *************************************************************************
duke@0
   476
 * Type Checking
duke@0
   477
 **************************************************************************/
duke@0
   478
mcimadamore@2078
   479
    /**
mcimadamore@2078
   480
     * A check context is an object that can be used to perform compatibility
mcimadamore@2078
   481
     * checks - depending on the check context, meaning of 'compatibility' might
mcimadamore@2078
   482
     * vary significantly.
mcimadamore@2078
   483
     */
mcimadamore@2191
   484
    public interface CheckContext {
mcimadamore@2078
   485
        /**
mcimadamore@2078
   486
         * Is type 'found' compatible with type 'req' in given context
mcimadamore@2078
   487
         */
mcimadamore@2078
   488
        boolean compatible(Type found, Type req, Warner warn);
mcimadamore@2078
   489
        /**
mcimadamore@2078
   490
         * Report a check error
mcimadamore@2078
   491
         */
mcimadamore@2140
   492
        void report(DiagnosticPosition pos, JCDiagnostic details);
mcimadamore@2078
   493
        /**
mcimadamore@2078
   494
         * Obtain a warner for this check context
mcimadamore@2078
   495
         */
mcimadamore@2078
   496
        public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
mcimadamore@2176
   497
vromero@4571
   498
        public InferenceContext inferenceContext();
mcimadamore@2190
   499
mcimadamore@2190
   500
        public DeferredAttr.DeferredAttrContext deferredAttrContext();
mcimadamore@2078
   501
    }
mcimadamore@2078
   502
mcimadamore@2078
   503
    /**
mcimadamore@2078
   504
     * This class represent a check context that is nested within another check
mcimadamore@2078
   505
     * context - useful to check sub-expressions. The default behavior simply
mcimadamore@2078
   506
     * redirects all method calls to the enclosing check context leveraging
mcimadamore@2078
   507
     * the forwarding pattern.
mcimadamore@2078
   508
     */
mcimadamore@2078
   509
    static class NestedCheckContext implements CheckContext {
mcimadamore@2078
   510
        CheckContext enclosingContext;
mcimadamore@2078
   511
mcimadamore@2078
   512
        NestedCheckContext(CheckContext enclosingContext) {
mcimadamore@2078
   513
            this.enclosingContext = enclosingContext;
mcimadamore@2078
   514
        }
mcimadamore@2078
   515
mcimadamore@2078
   516
        public boolean compatible(Type found, Type req, Warner warn) {
mcimadamore@2078
   517
            return enclosingContext.compatible(found, req, warn);
mcimadamore@2078
   518
        }
mcimadamore@2078
   519
mcimadamore@2140
   520
        public void report(DiagnosticPosition pos, JCDiagnostic details) {
mcimadamore@2140
   521
            enclosingContext.report(pos, details);
mcimadamore@2078
   522
        }
mcimadamore@2078
   523
mcimadamore@2078
   524
        public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
mcimadamore@2078
   525
            return enclosingContext.checkWarner(pos, found, req);
mcimadamore@2078
   526
        }
mcimadamore@2176
   527
vromero@4571
   528
        public InferenceContext inferenceContext() {
mcimadamore@2176
   529
            return enclosingContext.inferenceContext();
mcimadamore@2176
   530
        }
mcimadamore@2190
   531
mcimadamore@2190
   532
        public DeferredAttrContext deferredAttrContext() {
mcimadamore@2190
   533
            return enclosingContext.deferredAttrContext();
mcimadamore@2190
   534
        }
mcimadamore@2078
   535
    }
mcimadamore@2078
   536
mcimadamore@2078
   537
    /**
mcimadamore@2078
   538
     * Check context to be used when evaluating assignment/return statements
mcimadamore@2078
   539
     */
mcimadamore@2078
   540
    CheckContext basicHandler = new CheckContext() {
mcimadamore@2140
   541
        public void report(DiagnosticPosition pos, JCDiagnostic details) {
mcimadamore@2140
   542
            log.error(pos, "prob.found.req", details);
mcimadamore@2078
   543
        }
mcimadamore@2078
   544
        public boolean compatible(Type found, Type req, Warner warn) {
mcimadamore@2078
   545
            return types.isAssignable(found, req, warn);
mcimadamore@2078
   546
        }
mcimadamore@2078
   547
mcimadamore@2078
   548
        public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
mcimadamore@2078
   549
            return convertWarner(pos, found, req);
mcimadamore@2078
   550
        }
mcimadamore@2176
   551
mcimadamore@2176
   552
        public InferenceContext inferenceContext() {
mcimadamore@2176
   553
            return infer.emptyContext;
mcimadamore@2176
   554
        }
mcimadamore@2190
   555
mcimadamore@2190
   556
        public DeferredAttrContext deferredAttrContext() {
mcimadamore@2190
   557
            return deferredAttr.emptyDeferredAttrContext;
mcimadamore@2190
   558
        }
vromero@3971
   559
vromero@3971
   560
        @Override
vromero@3971
   561
        public String toString() {
vromero@3971
   562
            return "CheckContext: basicHandler";
vromero@3971
   563
        }
mcimadamore@2078
   564
    };
mcimadamore@2078
   565
duke@0
   566
    /** Check that a given type is assignable to a given proto-type.
duke@0
   567
     *  If it is, return the type, otherwise return errType.
duke@0
   568
     *  @param pos        Position to be used for error reporting.
duke@0
   569
     *  @param found      The type that was found.
duke@0
   570
     *  @param req        The type that was required.
duke@0
   571
     */
jlahoda@5
   572
    public Type checkType(DiagnosticPosition pos, Type found, Type req) {
mcimadamore@2078
   573
        return checkType(pos, found, req, basicHandler);
darcy@1000
   574
    }
darcy@1000
   575
mcimadamore@2176
   576
    Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
vromero@4571
   577
        final InferenceContext inferenceContext = checkContext.inferenceContext();
vromero@4059
   578
        if (inferenceContext.free(req) || inferenceContext.free(found)) {
mcimadamore@5585
   579
            inferenceContext.addFreeTypeListener(List.of(req, found),
mcimadamore@5585
   580
                    solvedContext -> checkType(pos, solvedContext.asInstType(found), solvedContext.asInstType(req), checkContext));
mcimadamore@2176
   581
        }
jjg@2213
   582
        if (req.hasTag(ERROR))
duke@0
   583
            return req;
jjg@2213
   584
        if (req.hasTag(NONE))
duke@0
   585
            return found;
dbalek@2549
   586
        if (found == null || checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) {
duke@0
   587
            return found;
mcimadamore@2078
   588
        } else {
vromero@2810
   589
            if (found.isNumeric() && req.isNumeric()) {
mcimadamore@2140
   590
                checkContext.report(pos, diags.fragment("possible.loss.of.precision", found, req));
mcimadamore@2078
   591
                return types.createErrorType(found);
mcimadamore@2078
   592
            }
mcimadamore@2140
   593
            checkContext.report(pos, diags.fragment("inconvertible.types", found, req));
jjg@289
   594
            return types.createErrorType(found);
duke@0
   595
        }
duke@0
   596
    }
duke@0
   597
duke@0
   598
    /** Check that a given type can be cast to a given target type.
duke@0
   599
     *  Return the result of the cast.
duke@0
   600
     *  @param pos        Position to be used for error reporting.
duke@0
   601
     *  @param found      The type that is being cast.
duke@0
   602
     *  @param req        The target type of the cast.
duke@0
   603
     */
duke@0
   604
    Type checkCastable(DiagnosticPosition pos, Type found, Type req) {
mcimadamore@2078
   605
        return checkCastable(pos, found, req, basicHandler);
mcimadamore@2078
   606
    }
mcimadamore@2078
   607
    Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
mcimadamore@2112
   608
        if (types.isCastable(found, req, castWarner(pos, found, req))) {
duke@0
   609
            return req;
duke@0
   610
        } else {
mcimadamore@2140
   611
            checkContext.report(pos, diags.fragment("inconvertible.types", found, req));
mcimadamore@2078
   612
            return types.createErrorType(found);
duke@0
   613
        }
duke@0
   614
    }
mcimadamore@2077
   615
mcimadamore@2077
   616
    /** Check for redundant casts (i.e. where source type is a subtype of target type)
mcimadamore@2077
   617
     * The problem should only be reported for non-292 cast
mcimadamore@2077
   618
     */
jlahoda@3044
   619
    public void checkRedundantCast(Env<AttrContext> env, final JCTypeCast tree) {
jlahoda@3044
   620
        if (!tree.type.isErroneous()
mcimadamore@2191
   621
                && types.isSameType(tree.expr.type, tree.clazz.type)
jjg@2372
   622
                && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz))
mcimadamore@2191
   623
                && !is292targetTypeCast(tree)) {
mcimadamore@5585
   624
            deferredLintHandler.report(() -> {
mcimadamore@5585
   625
                if (lint.isEnabled(LintCategory.CAST))
mcimadamore@5585
   626
                    log.warning(LintCategory.CAST,
mcimadamore@5585
   627
                            tree.pos(), "redundant.cast", tree.clazz.type);
jlahoda@3044
   628
            });
mcimadamore@2077
   629
        }
mcimadamore@2077
   630
    }
mcimadamore@2077
   631
    //where
jjg@2372
   632
        private boolean is292targetTypeCast(JCTypeCast tree) {
jjg@2372
   633
            boolean is292targetTypeCast = false;
jjg@2372
   634
            JCExpression expr = TreeInfo.skipParens(tree.expr);
jjg@2372
   635
            if (expr.hasTag(APPLY)) {
jjg@2372
   636
                JCMethodInvocation apply = (JCMethodInvocation)expr;
jjg@2372
   637
                Symbol sym = TreeInfo.symbol(apply.meth);
jjg@2372
   638
                is292targetTypeCast = sym != null &&
jjg@2372
   639
                    sym.kind == MTH &&
jjg@2372
   640
                    (sym.flags() & HYPOTHETICAL) != 0;
mcimadamore@2077
   641
            }
jjg@2372
   642
            return is292targetTypeCast;
jjg@2372
   643
        }
mcimadamore@2077
   644
jjg@2372
   645
        private static final boolean ignoreAnnotatedCasts = true;
duke@0
   646
duke@0
   647
    /** Check that a type is within some bounds.
duke@0
   648
     *
jjg@2197
   649
     *  Used in TypeApply to verify that, e.g., X in {@code V<X>} is a valid
duke@0
   650
     *  type argument.
duke@0
   651
     *  @param a             The type that should be bounded by bs.
jjg@2197
   652
     *  @param bound         The bound.
duke@0
   653
     */
mcimadamore@2059
   654
    private boolean checkExtends(Type a, Type bound) {
mcimadamore@333
   655
         if (a.isUnbound()) {
mcimadamore@1286
   656
             return true;
jjg@2213
   657
         } else if (!a.hasTag(WILDCARD)) {
dlsmith@4010
   658
             a = types.cvarUpperBound(a);
mcimadamore@2059
   659
             return types.isSubtype(a, bound);
mcimadamore@333
   660
         } else if (a.isExtendsBound()) {
dlsmith@4010
   661
             return types.isCastable(bound, types.wildUpperBound(a), types.noWarnings);
mcimadamore@333
   662
         } else if (a.isSuperBound()) {
dlsmith@3976
   663
             return !types.notSoftSubtype(types.wildLowerBound(a), bound);
mcimadamore@333
   664
         }
mcimadamore@1286
   665
         return true;
mcimadamore@333
   666
     }
duke@0
   667
duke@0
   668
    /** Check that type is different from 'void'.
duke@0
   669
     *  @param pos           Position to be used for error reporting.
duke@0
   670
     *  @param t             The type to be checked.
duke@0
   671
     */
duke@0
   672
    Type checkNonVoid(DiagnosticPosition pos, Type t) {
jjg@2213
   673
        if (t.hasTag(VOID)) {
duke@0
   674
            log.error(pos, "void.not.allowed.here");
jjg@289
   675
            return types.createErrorType(t);
duke@0
   676
        } else {
duke@0
   677
            return t;
duke@0
   678
        }
duke@0
   679
    }
duke@0
   680
mcimadamore@2343
   681
    Type checkClassOrArrayType(DiagnosticPosition pos, Type t) {
mcimadamore@2343
   682
        if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) {
mcimadamore@2343
   683
            return typeTagError(pos,
mcimadamore@2343
   684
                                diags.fragment("type.req.class.array"),
mcimadamore@2343
   685
                                asTypeParam(t));
mcimadamore@2343
   686
        } else {
mcimadamore@2343
   687
            return t;
mcimadamore@2343
   688
        }
mcimadamore@2343
   689
    }
mcimadamore@2343
   690
duke@0
   691
    /** Check that type is a class or interface type.
duke@0
   692
     *  @param pos           Position to be used for error reporting.
duke@0
   693
     *  @param t             The type to be checked.
duke@0
   694
     */
duke@0
   695
    Type checkClassType(DiagnosticPosition pos, Type t) {
mcimadamore@2343
   696
        if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) {
duke@0
   697
            return typeTagError(pos,
mcimadamore@268
   698
                                diags.fragment("type.req.class"),
mcimadamore@2343
   699
                                asTypeParam(t));
mcimadamore@2343
   700
        } else {
duke@0
   701
            return t;
mcimadamore@2343
   702
        }
duke@0
   703
    }
mcimadamore@2343
   704
    //where
mcimadamore@2343
   705
        private Object asTypeParam(Type t) {
mcimadamore@2343
   706
            return (t.hasTag(TYPEVAR))
mcimadamore@2343
   707
                                    ? diags.fragment("type.parameter", t)
mcimadamore@2343
   708
                                    : t;
mcimadamore@2343
   709
        }
duke@0
   710
mcimadamore@2195
   711
    /** Check that type is a valid qualifier for a constructor reference expression
mcimadamore@2195
   712
     */
mcimadamore@2195
   713
    Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
mcimadamore@2343
   714
        t = checkClassOrArrayType(pos, t);
jjg@2213
   715
        if (t.hasTag(CLASS)) {
mcimadamore@2195
   716
            if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
mcimadamore@2536
   717
                log.error(pos, "abstract.cant.be.instantiated", t.tsym);
mcimadamore@2195
   718
                t = types.createErrorType(t);
mcimadamore@2195
   719
            } else if ((t.tsym.flags() & ENUM) != 0) {
mcimadamore@2195
   720
                log.error(pos, "enum.cant.be.instantiated");
mcimadamore@2195
   721
                t = types.createErrorType(t);
mcimadamore@2536
   722
            } else {
mcimadamore@2536
   723
                t = checkClassType(pos, t, true);
mcimadamore@2536
   724
            }
mcimadamore@2536
   725
        } else if (t.hasTag(ARRAY)) {
mcimadamore@2536
   726
            if (!types.isReifiable(((ArrayType)t).elemtype)) {
mcimadamore@2536
   727
                log.error(pos, "generic.array.creation");
mcimadamore@2536
   728
                t = types.createErrorType(t);
mcimadamore@2195
   729
            }
mcimadamore@2195
   730
        }
mcimadamore@2195
   731
        return t;
mcimadamore@2195
   732
    }
mcimadamore@2195
   733
duke@0
   734
    /** Check that type is a class or interface type.
duke@0
   735
     *  @param pos           Position to be used for error reporting.
duke@0
   736
     *  @param t             The type to be checked.
duke@0
   737
     *  @param noBounds    True if type bounds are illegal here.
duke@0
   738
     */
duke@0
   739
    Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) {
duke@0
   740
        t = checkClassType(pos, t);
duke@0
   741
        if (noBounds && t.isParameterized()) {
duke@0
   742
            List<Type> args = t.getTypeArguments();
duke@0
   743
            while (args.nonEmpty()) {
jjg@2213
   744
                if (args.head.hasTag(WILDCARD))
duke@0
   745
                    return typeTagError(pos,
jjg@994
   746
                                        diags.fragment("type.req.exact"),
duke@0
   747
                                        args.head);
duke@0
   748
                args = args.tail;
duke@0
   749
            }
duke@0
   750
        }
duke@0
   751
        return t;
duke@0
   752
    }
duke@0
   753
duke@0
   754
    /** Check that type is a reference type, i.e. a class, interface or array type
duke@0
   755
     *  or a type variable.
duke@0
   756
     *  @param pos           Position to be used for error reporting.
duke@0
   757
     *  @param t             The type to be checked.
duke@0
   758
     */
duke@0
   759
    Type checkRefType(DiagnosticPosition pos, Type t) {
jjg@2213
   760
        if (t.isReference())
duke@0
   761
            return t;
jjg@2213
   762
        else
duke@0
   763
            return typeTagError(pos,
mcimadamore@268
   764
                                diags.fragment("type.req.ref"),
duke@0
   765
                                t);
duke@0
   766
    }
duke@0
   767
jrose@557
   768
    /** Check that each type is a reference type, i.e. a class, interface or array type
jrose@557
   769
     *  or a type variable.
jrose@557
   770
     *  @param trees         Original trees, used for error reporting.
jrose@557
   771
     *  @param types         The types to be checked.
jrose@557
   772
     */
jrose@557
   773
    List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) {
jrose@557
   774
        List<JCExpression> tl = trees;
jrose@557
   775
        for (List<Type> l = types; l.nonEmpty(); l = l.tail) {
jrose@557
   776
            l.head = checkRefType(tl.head.pos(), l.head);
jrose@557
   777
            tl = tl.tail;
jrose@557
   778
        }
jrose@557
   779
        return types;
jrose@557
   780
    }
jrose@557
   781
duke@0
   782
    /** Check that type is a null or reference type.
duke@0
   783
     *  @param pos           Position to be used for error reporting.
duke@0
   784
     *  @param t             The type to be checked.
duke@0
   785
     */
duke@0
   786
    Type checkNullOrRefType(DiagnosticPosition pos, Type t) {
vromero@2810
   787
        if (t.isReference() || t.hasTag(BOT))
duke@0
   788
            return t;
jjg@2213
   789
        else
duke@0
   790
            return typeTagError(pos,
mcimadamore@268
   791
                                diags.fragment("type.req.ref"),
duke@0
   792
                                t);
duke@0
   793
    }
duke@0
   794
duke@0
   795
    /** Check that flag set does not contain elements of two conflicting sets. s
duke@0
   796
     *  Return true if it doesn't.
duke@0
   797
     *  @param pos           Position to be used for error reporting.
duke@0
   798
     *  @param flags         The set of flags to be checked.
duke@0
   799
     *  @param set1          Conflicting flags set #1.
duke@0
   800
     *  @param set2          Conflicting flags set #2.
duke@0
   801
     */
duke@0
   802
    boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) {
duke@0
   803
        if ((flags & set1) != 0 && (flags & set2) != 0) {
duke@0
   804
            log.error(pos,
duke@0
   805
                      "illegal.combination.of.modifiers",
mcimadamore@261
   806
                      asFlagSet(TreeInfo.firstFlag(flags & set1)),
mcimadamore@261
   807
                      asFlagSet(TreeInfo.firstFlag(flags & set2)));
duke@0
   808
            return false;
duke@0
   809
        } else
duke@0
   810
            return true;
duke@0
   811
    }
duke@0
   812
mcimadamore@1398
   813
    /** Check that usage of diamond operator is correct (i.e. diamond should not
mcimadamore@1398
   814
     * be used with non-generic classes or in anonymous class creation expressions)
mcimadamore@927
   815
     */
mcimadamore@1398
   816
    Type checkDiamond(JCNewClass tree, Type t) {
mcimadamore@1398
   817
        if (!TreeInfo.isDiamond(tree) ||
mcimadamore@1398
   818
                t.isErroneous()) {
mcimadamore@1398
   819
            return checkClassType(tree.clazz.pos(), t, true);
mcimadamore@1398
   820
        } else {
jlahoda@5330
   821
            if (tree.def != null && !allowDiamondWithAnonymousClassCreation) {
jlahoda@5330
   822
                log.error(DiagnosticFlag.SOURCE_LEVEL, tree.clazz.pos(),
jlahoda@5330
   823
                        Errors.CantApplyDiamond1(t, Fragments.DiamondAndAnonClassNotSupportedInSource(source.name)));
jlahoda@5330
   824
            }
jlahoda@5330
   825
            if (t.tsym.type.getTypeArguments().isEmpty()) {
jlahoda@5330
   826
                log.error(tree.clazz.pos(),
jlahoda@5330
   827
                    "cant.apply.diamond.1",
jlahoda@5330
   828
                    t, diags.fragment("diamond.non.generic", t));
jlahoda@5330
   829
                return types.createErrorType(t);
jlahoda@5330
   830
            } else if (tree.typeargs != null &&
jlahoda@5330
   831
                    tree.typeargs.nonEmpty()) {
jlahoda@5330
   832
                log.error(tree.clazz.pos(),
jlahoda@5330
   833
                    "cant.apply.diamond.1",
jlahoda@5330
   834
                    t, diags.fragment("diamond.and.explicit.params", t));
jlahoda@5330
   835
                return types.createErrorType(t);
jlahoda@5330
   836
            } else {
jlahoda@5330
   837
                return t;
jlahoda@5330
   838
            }
mcimadamore@927
   839
        }
mcimadamore@927
   840
    }
mcimadamore@927
   841
sadayapalam@4445
   842
    /** Check that the type inferred using the diamond operator does not contain
sadayapalam@4445
   843
     *  non-denotable types such as captured types or intersection types.
sadayapalam@4445
   844
     *  @param t the type inferred using the diamond operator
sadayapalam@4445
   845
     *  @return  the (possibly empty) list of non-denotable types.
sadayapalam@4445
   846
     */
sadayapalam@4445
   847
    List<Type> checkDiamondDenotable(ClassType t) {
sadayapalam@4445
   848
        ListBuffer<Type> buf = new ListBuffer<>();
sadayapalam@4617
   849
        for (Type arg : t.allparams()) {
sadayapalam@4445
   850
            if (!diamondTypeChecker.visit(arg, null)) {
sadayapalam@4445
   851
                buf.append(arg);
sadayapalam@4445
   852
            }
sadayapalam@4445
   853
        }
sadayapalam@4445
   854
        return buf.toList();
sadayapalam@4445
   855
    }
sadayapalam@4445
   856
        // where
sadayapalam@4445
   857
sadayapalam@4445
   858
        /** diamondTypeChecker: A type visitor that descends down the given type looking for non-denotable
sadayapalam@4445
   859
         *  types. The visit methods return false as soon as a non-denotable type is encountered and true
sadayapalam@4445
   860
         *  otherwise.
sadayapalam@4445
   861
         */
sadayapalam@4445
   862
        private static final Types.SimpleVisitor<Boolean, Void> diamondTypeChecker = new Types.SimpleVisitor<Boolean, Void>() {
sadayapalam@4445
   863
            @Override
sadayapalam@4445
   864
            public Boolean visitType(Type t, Void s) {
sadayapalam@4445
   865
                return true;
sadayapalam@4445
   866
            }
sadayapalam@4445
   867
            @Override
sadayapalam@4445
   868
            public Boolean visitClassType(ClassType t, Void s) {
sadayapalam@4445
   869
                if (t.isCompound()) {
sadayapalam@4445
   870
                    return false;
sadayapalam@4445
   871
                }
sadayapalam@4617
   872
                for (Type targ : t.allparams()) {
sadayapalam@4445
   873
                    if (!visit(targ, s)) {
sadayapalam@4445
   874
                        return false;
sadayapalam@4445
   875
                    }
sadayapalam@4445
   876
                }
sadayapalam@4445
   877
                return true;
sadayapalam@4445
   878
            }
sadayapalam@4481
   879
sadayapalam@4481
   880
            @Override
sadayapalam@4481
   881
            public Boolean visitTypeVar(TypeVar t, Void s) {
sadayapalam@4481
   882
                /* Any type variable mentioned in the inferred type must have been declared as a type parameter
sadayapalam@4617
   883
                  (i.e cannot have been produced by inference (18.4))
sadayapalam@4481
   884
                */
sadayapalam@4481
   885
                return t.tsym.owner.type.getTypeArguments().contains(t);
sadayapalam@4481
   886
            }
sadayapalam@4481
   887
sadayapalam@4445
   888
            @Override
sadayapalam@4445
   889
            public Boolean visitCapturedType(CapturedType t, Void s) {
sadayapalam@4617
   890
                /* Any type variable mentioned in the inferred type must have been declared as a type parameter
sadayapalam@4617
   891
                  (i.e cannot have been produced by capture conversion (5.1.10))
sadayapalam@4617
   892
                */
sadayapalam@4445
   893
                return false;
sadayapalam@4445
   894
            }
sadayapalam@4445
   895
sadayapalam@4445
   896
            @Override
sadayapalam@4445
   897
            public Boolean visitArrayType(ArrayType t, Void s) {
sadayapalam@4445
   898
                return visit(t.elemtype, s);
sadayapalam@4445
   899
            }
sadayapalam@4445
   900
sadayapalam@4445
   901
            @Override
sadayapalam@4445
   902
            public Boolean visitWildcardType(WildcardType t, Void s) {
sadayapalam@4445
   903
                return visit(t.type, s);
sadayapalam@4445
   904
            }
sadayapalam@4445
   905
        };
sadayapalam@4445
   906
mcimadamore@1244
   907
    void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) {
mcimadamore@970
   908
        MethodSymbol m = tree.sym;
mcimadamore@1244
   909
        if (!allowSimplifiedVarargs) return;
mcimadamore@1244
   910
        boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null;
mcimadamore@1244
   911
        Type varargElemType = null;
mcimadamore@970
   912
        if (m.isVarArgs()) {
mcimadamore@1244
   913
            varargElemType = types.elemtype(tree.params.last().type);
mcimadamore@1244
   914
        }
mcimadamore@1244
   915
        if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) {
mcimadamore@1244
   916
            if (varargElemType != null) {
mcimadamore@1244
   917
                log.error(tree,
mcimadamore@1244
   918
                        "varargs.invalid.trustme.anno",
darcy@4063
   919
                          syms.trustMeType.tsym,
darcy@4063
   920
                          allowPrivateSafeVarargs ?
darcy@4063
   921
                          diags.fragment("varargs.trustme.on.virtual.varargs", m) :
darcy@4063
   922
                          diags.fragment("varargs.trustme.on.virtual.varargs.final.only", m));
mcimadamore@1244
   923
            } else {
mcimadamore@1244
   924
                log.error(tree,
mcimadamore@1244
   925
                            "varargs.invalid.trustme.anno",
mcimadamore@1244
   926
                            syms.trustMeType.tsym,
mcimadamore@1244
   927
                            diags.fragment("varargs.trustme.on.non.varargs.meth", m));
mcimadamore@970
   928
            }
mcimadamore@1244
   929
        } else if (hasTrustMeAnno && varargElemType != null &&
mcimadamore@1244
   930
                            types.isReifiable(varargElemType)) {
mcimadamore@1244
   931
            warnUnsafeVararg(tree,
mcimadamore@1244
   932
                            "varargs.redundant.trustme.anno",
mcimadamore@1244
   933
                            syms.trustMeType.tsym,
mcimadamore@1244
   934
                            diags.fragment("varargs.trustme.on.reifiable.varargs", varargElemType));
mcimadamore@1244
   935
        }
mcimadamore@1244
   936
        else if (!hasTrustMeAnno && varargElemType != null &&
mcimadamore@1244
   937
                !types.isReifiable(varargElemType)) {
mcimadamore@1244
   938
            warnUnchecked(tree.params.head.pos(), "unchecked.varargs.non.reifiable.type", varargElemType);
mcimadamore@970
   939
        }
mcimadamore@970
   940
    }
mcimadamore@1244
   941
    //where
mcimadamore@1244
   942
        private boolean isTrustMeAllowedOnMethod(Symbol s) {
mcimadamore@1244
   943
            return (s.flags() & VARARGS) != 0 &&
mcimadamore@1244
   944
                (s.isConstructor() ||
darcy@4063
   945
                    (s.flags() & (STATIC | FINAL |
darcy@4063
   946
                                  (allowPrivateSafeVarargs ? PRIVATE : 0) )) != 0);
mcimadamore@1244
   947
        }
mcimadamore@970
   948
mcimadamore@2796
   949
    Type checkMethod(final Type mtype,
mcimadamore@2796
   950
            final Symbol sym,
mcimadamore@2796
   951
            final Env<AttrContext> env,
mcimadamore@2796
   952
            final List<JCExpression> argtrees,
mcimadamore@2796
   953
            final List<Type> argtypes,
mcimadamore@2796
   954
            final boolean useVarargs,
mcimadamore@2796
   955
            InferenceContext inferenceContext) {
mcimadamore@2062
   956
        // System.out.println("call   : " + env.tree);
mcimadamore@2062
   957
        // System.out.println("method : " + owntype);
mcimadamore@2062
   958
        // System.out.println("actuals: " + argtypes);
mcimadamore@2796
   959
        if (inferenceContext.free(mtype)) {
mcimadamore@5585
   960
            inferenceContext.addFreeTypeListener(List.of(mtype),
mcimadamore@5585
   961
                    solvedContext -> checkMethod(solvedContext.asInstType(mtype), sym, env, argtrees, argtypes, useVarargs, solvedContext));
mcimadamore@2796
   962
            return mtype;
mcimadamore@2796
   963
        }
mcimadamore@2796
   964
        Type owntype = mtype;
mcimadamore@2062
   965
        List<Type> formals = owntype.getParameterTypes();
kizune@2975
   966
        List<Type> nonInferred = sym.type.getParameterTypes();
kizune@2975
   967
        if (nonInferred.length() != formals.length()) nonInferred = formals;
mcimadamore@2062
   968
        Type last = useVarargs ? formals.last() : null;
kizune@2975
   969
        if (sym.name == names.init && sym.owner == syms.enumSym) {
kizune@2975
   970
            formals = formals.tail.tail;
kizune@2975
   971
            nonInferred = nonInferred.tail.tail;
kizune@2975
   972
        }
mcimadamore@2062
   973
        List<JCExpression> args = argtrees;
mcimadamore@2195
   974
        if (args != null) {
mcimadamore@2195
   975
            //this is null when type-checking a method reference
dbalek@3289
   976
            while (formals.head != last && args.head != null) {
mcimadamore@2062
   977
                JCTree arg = args.head;
kizune@2975
   978
                Warner warn = convertWarner(arg.pos(), arg.type, nonInferred.head);
mcimadamore@2195
   979
                assertConvertible(arg, arg.type, formals.head, warn);
mcimadamore@2062
   980
                args = args.tail;
mcimadamore@2195
   981
                formals = formals.tail;
kizune@2975
   982
                nonInferred = nonInferred.tail;
mcimadamore@2062
   983
            }
mcimadamore@2195
   984
            if (useVarargs) {
mcimadamore@2195
   985
                Type varArg = types.elemtype(last);
mcimadamore@2195
   986
                while (args.tail != null) {
mcimadamore@2195
   987
                    JCTree arg = args.head;
mcimadamore@2195
   988
                    Warner warn = convertWarner(arg.pos(), arg.type, varArg);
mcimadamore@2195
   989
                    assertConvertible(arg, arg.type, varArg, warn);
mcimadamore@2195
   990
                    args = args.tail;
mcimadamore@2195
   991
                }
ntoda@4105
   992
            } else if ((sym.flags() & (VARARGS | SIGNATURE_POLYMORPHIC)) == VARARGS) {
mcimadamore@2195
   993
                // non-varargs call to varargs method
mcimadamore@2195
   994
                Type varParam = owntype.getParameterTypes().last();
mcimadamore@2796
   995
                Type lastArg = argtypes.last();
mcimadamore@2195
   996
                if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
kizune@2975
   997
                    !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
mcimadamore@2195
   998
                    log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
kizune@2975
   999
                                types.elemtype(varParam), varParam);
mcimadamore@2195
  1000
            }
mcimadamore@2062
  1001
        }
mcimadamore@2062
  1002
        if (useVarargs) {
mcimadamore@2062
  1003
            Type argtype = owntype.getParameterTypes().last();
mcimadamore@2062
  1004
            if (!types.isReifiable(argtype) &&
kizune@2975
  1005
                (!allowSimplifiedVarargs ||
jlahoda@4379
  1006
                 sym.baseSymbol().attribute(syms.trustMeType.tsym) == null ||
kizune@2975
  1007
                 !isTrustMeAllowedOnMethod(sym))) {
mcimadamore@2062
  1008
                warnUnchecked(env.tree.pos(),
mcimadamore@2062
  1009
                                  "unchecked.generic.array.creation",
mcimadamore@2062
  1010
                                  argtype);
mcimadamore@2062
  1011
            }
vromero@2804
  1012
            if ((sym.baseSymbol().flags() & SIGNATURE_POLYMORPHIC) == 0) {
mcimadamore@2796
  1013
                TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype));
mcimadamore@2062
  1014
            }
mcimadamore@2062
  1015
         }
mcimadamore@2062
  1016
         return owntype;
mcimadamore@935
  1017
    }
mcimadamore@2062
  1018
    //where
kizune@2975
  1019
    private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) {
dbalek@3780
  1020
        if (actual == null || formal == null)
dbalek@3780
  1021
            return;
dbalek@3780
  1022
        
kizune@2975
  1023
        if (types.isConvertible(actual, formal, warn))
kizune@2975
  1024
            return;
kizune@2975
  1025
kizune@2975
  1026
        if (formal.isCompound()
kizune@2975
  1027
            && types.isSubtype(actual, types.supertype(formal))
kizune@2975
  1028
            && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
kizune@2975
  1029
            return;
kizune@2975
  1030
    }
mcimadamore@935
  1031
mcimadamore@1286
  1032
    /**
mcimadamore@1286
  1033
     * Check that type 't' is a valid instantiation of a generic class
mcimadamore@1286
  1034
     * (see JLS 4.5)
mcimadamore@1286
  1035
     *
mcimadamore@1286
  1036
     * @param t class type to be checked
mcimadamore@1286
  1037
     * @return true if 't' is well-formed
mcimadamore@1286
  1038
     */
mcimadamore@1286
  1039
    public boolean checkValidGenericType(Type t) {
mcimadamore@1286
  1040
        return firstIncompatibleTypeArg(t) == null;
mcimadamore@1286
  1041
    }
mcimadamore@1286
  1042
    //WHERE
mcimadamore@1286
  1043
        private Type firstIncompatibleTypeArg(Type type) {
mcimadamore@1286
  1044
            List<Type> formals = type.tsym.type.allparams();
mcimadamore@1286
  1045
            List<Type> actuals = type.allparams();
mcimadamore@1286
  1046
            List<Type> args = type.getTypeArguments();
mcimadamore@1286
  1047
            List<Type> forms = type.tsym.type.getTypeArguments();
briangoetz@3808
  1048
            ListBuffer<Type> bounds_buf = new ListBuffer<>();
mcimadamore@1286
  1049
mcimadamore@1286
  1050
            // For matching pairs of actual argument types `a' and
mcimadamore@1286
  1051
            // formal type parameters with declared bound `b' ...
mcimadamore@1286
  1052
            while (args.nonEmpty() && forms.nonEmpty()) {
mcimadamore@1286
  1053
                // exact type arguments needs to know their
mcimadamore@1286
  1054
                // bounds (for upper and lower bound
mcimadamore@2059
  1055
                // calculations).  So we create new bounds where
mcimadamore@2059
  1056
                // type-parameters are replaced with actuals argument types.
mcimadamore@2059
  1057
                bounds_buf.append(types.subst(forms.head.getUpperBound(), formals, actuals));
mcimadamore@1286
  1058
                args = args.tail;
mcimadamore@1286
  1059
                forms = forms.tail;
mcimadamore@1286
  1060
            }
mcimadamore@1286
  1061
mcimadamore@1286
  1062
            args = type.getTypeArguments();
mcimadamore@1286
  1063
            List<Type> tvars_cap = types.substBounds(formals,
mcimadamore@1286
  1064
                                      formals,
mcimadamore@1286
  1065
                                      types.capture(type).allparams());
mcimadamore@1286
  1066
            while (args.nonEmpty() && tvars_cap.nonEmpty()) {
mcimadamore@1286
  1067
                // Let the actual arguments know their bound
mcimadamore@1286
  1068
                args.head.withTypeVar((TypeVar)tvars_cap.head);
mcimadamore@1286
  1069
                args = args.tail;
mcimadamore@1286
  1070
                tvars_cap = tvars_cap.tail;
mcimadamore@1286
  1071
            }
mcimadamore@1286
  1072
mcimadamore@1286
  1073
            args = type.getTypeArguments();
mcimadamore@2059
  1074
            List<Type> bounds = bounds_buf.toList();
mcimadamore@1286
  1075
mcimadamore@2059
  1076
            while (args.nonEmpty() && bounds.nonEmpty()) {
mcimadamore@2059
  1077
                Type actual = args.head;
mcimadamore@1319
  1078
                if (!isTypeArgErroneous(actual) &&
mcimadamore@2059
  1079
                        !bounds.head.isErroneous() &&
mcimadamore@2059
  1080
                        !checkExtends(actual, bounds.head)) {
mcimadamore@1286
  1081
                    return args.head;
mcimadamore@1286
  1082
                }
mcimadamore@1286
  1083
                args = args.tail;
mcimadamore@2059
  1084
                bounds = bounds.tail;
mcimadamore@1286
  1085
            }
mcimadamore@1286
  1086
mcimadamore@1286
  1087
            args = type.getTypeArguments();
mcimadamore@2059
  1088
            bounds = bounds_buf.toList();
mcimadamore@1286
  1089
mcimadamore@1286
  1090
            for (Type arg : types.capture(type).getTypeArguments()) {
jjg@2213
  1091
                if (arg.hasTag(TYPEVAR) &&
mcimadamore@1297
  1092
                        arg.getUpperBound().isErroneous() &&
mcimadamore@2059
  1093
                        !bounds.head.isErroneous() &&
mcimadamore@1319
  1094
                        !isTypeArgErroneous(args.head)) {
mcimadamore@1286
  1095
                    return args.head;
mcimadamore@1286
  1096
                }
mcimadamore@2059
  1097
                bounds = bounds.tail;
mcimadamore@1319
  1098
                args = args.tail;
mcimadamore@1286
  1099
            }
mcimadamore@1286
  1100
mcimadamore@1286
  1101
            return null;
mcimadamore@1286
  1102
        }
mcimadamore@1319
  1103
        //where
mcimadamore@1319
  1104
        boolean isTypeArgErroneous(Type t) {
mcimadamore@1319
  1105
            return isTypeArgErroneous.visit(t);
mcimadamore@1319
  1106
        }
mcimadamore@1319
  1107
mcimadamore@1319
  1108
        Types.UnaryVisitor<Boolean> isTypeArgErroneous = new Types.UnaryVisitor<Boolean>() {
mcimadamore@1319
  1109
            public Boolean visitType(Type t, Void s) {
mcimadamore@1319
  1110
                return t.isErroneous();
mcimadamore@1319
  1111
            }
mcimadamore@1319
  1112
            @Override
mcimadamore@1319
  1113
            public Boolean visitTypeVar(TypeVar t, Void s) {
mcimadamore@1319
  1114
                return visit(t.getUpperBound());
mcimadamore@1319
  1115
            }
mcimadamore@1319
  1116
            @Override
mcimadamore@1319
  1117
            public Boolean visitCapturedType(CapturedType t, Void s) {
mcimadamore@1319
  1118
                return visit(t.getUpperBound()) ||
mcimadamore@1319
  1119
                        visit(t.getLowerBound());
mcimadamore@1319
  1120
            }
mcimadamore@1319
  1121
            @Override
mcimadamore@1319
  1122
            public Boolean visitWildcardType(WildcardType t, Void s) {
mcimadamore@1319
  1123
                return visit(t.type);
mcimadamore@1319
  1124
            }
mcimadamore@1319
  1125
        };
mcimadamore@1286
  1126
duke@0
  1127
    /** Check that given modifiers are legal for given symbol and
vromero@2436
  1128
     *  return modifiers together with any implicit modifiers for that symbol.
duke@0
  1129
     *  Warning: we can't use flags() here since this method
duke@0
  1130
     *  is called during class enter, when flags() would cause a premature
duke@0
  1131
     *  completion.
duke@0
  1132
     *  @param pos           Position to be used for error reporting.
duke@0
  1133
     *  @param flags         The set of modifiers given in a definition.
duke@0
  1134
     *  @param sym           The defined symbol.
duke@0
  1135
     */
duke@0
  1136
    long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) {
duke@0
  1137
        long mask;
duke@0
  1138
        long implicit = 0;
emc@3032
  1139
duke@0
  1140
        switch (sym.kind) {
duke@0
  1141
        case VAR:
pgovereau@4036
  1142
            if (TreeInfo.isReceiverParam(tree))
pgovereau@4036
  1143
                mask = ReceiverParamFlags;
dbalek@3529
  1144
            else if (sym.owner.kind != TYP && sym.owner.kind != ERR)
duke@0
  1145
                mask = LocalVarFlags;
duke@0
  1146
            else if ((sym.owner.flags_field & INTERFACE) != 0)
duke@0
  1147
                mask = implicit = InterfaceVarFlags;
duke@0
  1148
            else
duke@0
  1149
                mask = VarFlags;
duke@0
  1150
            break;
duke@0
  1151
        case MTH:
duke@0
  1152
            if (sym.name == names.init) {
duke@0
  1153
                if ((sym.owner.flags_field & ENUM) != 0) {
duke@0
  1154
                    // enum constructors cannot be declared public or
duke@0
  1155
                    // protected and must be implicitly or explicitly
duke@0
  1156
                    // private
duke@0
  1157
                    implicit = PRIVATE;
duke@0
  1158
                    mask = PRIVATE;
duke@0
  1159
                } else
duke@0
  1160
                    mask = ConstructorFlags;
mcimadamore@2210
  1161
            }  else if ((sym.owner.flags_field & INTERFACE) != 0) {
emc@3032
  1162
                if ((sym.owner.flags_field & ANNOTATION) != 0) {
emc@3032
  1163
                    mask = AnnotationTypeElementMask;
emc@3032
  1164
                    implicit = PUBLIC | ABSTRACT;
sadayapalam@4414
  1165
                } else if ((flags & (DEFAULT | STATIC | PRIVATE)) != 0) {
mcimadamore@2364
  1166
                    mask = InterfaceMethodMask;
sadayapalam@4414
  1167
                    implicit = (flags & PRIVATE) != 0 ? 0 : PUBLIC;
mcimadamore@2364
  1168
                    if ((flags & DEFAULT) != 0) {
mcimadamore@2364
  1169
                        implicit |= ABSTRACT;
mcimadamore@2364
  1170
                    }
mcimadamore@2210
  1171
                } else {
mcimadamore@2210
  1172
                    mask = implicit = InterfaceMethodFlags;
mcimadamore@2210
  1173
                }
emc@3032
  1174
            } else {
duke@0
  1175
                mask = MethodFlags;
duke@0
  1176
            }
duke@0
  1177
            // Imply STRICTFP if owner has STRICTFP set.
vromero@2661
  1178
            if (((flags|implicit) & Flags.ABSTRACT) == 0 ||
vromero@2661
  1179
                ((flags) & Flags.DEFAULT) != 0)
vromero@2436
  1180
                implicit |= sym.owner.flags_field & STRICTFP;
duke@0
  1181
            break;
duke@0
  1182
        case TYP:
dbalek@488
  1183
        case ERR:
duke@0
  1184
            if (sym.isLocal()) {
duke@0
  1185
                mask = LocalClassFlags;
duke@0
  1186
                if ((sym.owner.flags_field & STATIC) == 0 &&
duke@0
  1187
                    (flags & ENUM) != 0)
duke@0
  1188
                    log.error(pos, "enums.must.be.static");
dbalek@488
  1189
            } else if (sym.owner.kind == TYP || sym.owner.kind == ERR) {
duke@0
  1190
                mask = MemberClassFlags;
duke@0
  1191
                if (sym.owner.owner.kind == PCK ||
duke@0
  1192
                    (sym.owner.flags_field & STATIC) != 0)
duke@0
  1193
                    mask |= STATIC;
duke@0
  1194
                else if ((flags & ENUM) != 0)
duke@0
  1195
                    log.error(pos, "enums.must.be.static");
duke@0
  1196
                // Nested interfaces and enums are always STATIC (Spec ???)
duke@0
  1197
                if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC;
duke@0
  1198
            } else {
duke@0
  1199
                mask = ClassFlags;
duke@0
  1200
            }
duke@0
  1201
            // Interfaces are always ABSTRACT
duke@0
  1202
            if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
duke@0
  1203
duke@0
  1204
            if ((flags & ENUM) != 0) {
duke@0
  1205
                // enums can't be declared abstract or final
duke@0
  1206
                mask &= ~(ABSTRACT | FINAL);
duke@0
  1207
                implicit |= implicitEnumFinalFlag(tree);
duke@0
  1208
            }
duke@0
  1209
            // Imply STRICTFP if owner has STRICTFP set.
duke@0
  1210
            implicit |= sym.owner.flags_field & STRICTFP;
duke@0
  1211
            break;
duke@0
  1212
        default:
duke@0
  1213
            throw new AssertionError();
duke@0
  1214
        }
mcimadamore@2210
  1215
        long illegal = flags & ExtendedStandardFlags & ~mask;
duke@0
  1216
        if (illegal != 0) {
duke@0
  1217
            if ((illegal & INTERFACE) != 0) {
duke@0
  1218
                log.error(pos, "intf.not.allowed.here");
duke@0
  1219
                mask |= INTERFACE;
duke@0
  1220
            }
duke@0
  1221
            else {
duke@0
  1222
                log.error(pos,
mcimadamore@261
  1223
                          "mod.not.allowed.here", asFlagSet(illegal));
duke@0
  1224
            }
duke@0
  1225
        }
duke@0
  1226
        else if ((sym.kind == TYP ||
duke@0
  1227
                  // ISSUE: Disallowing abstract&private is no longer appropriate
duke@0
  1228
                  // in the presence of inner classes. Should it be deleted here?
duke@0
  1229
                  checkDisjoint(pos, flags,
duke@0
  1230
                                ABSTRACT,
dbalek@2330
  1231
                                PRIVATE | STATIC | DEFAULT))) {
dbalek@1607
  1232
            if (checkDisjoint(pos, flags,
dbalek@4426
  1233
                               STATIC | PRIVATE,
dbalek@2374
  1234
                               DEFAULT)) {
dbalek@1607
  1235
                if (checkDisjoint(pos, flags,
dbalek@2374
  1236
                                    ABSTRACT | INTERFACE,
dbalek@2374
  1237
                                    FINAL | NATIVE | SYNCHRONIZED)) {
dbalek@1607
  1238
                    if (checkDisjoint(pos, flags,
dbalek@2374
  1239
                                        PUBLIC,
dbalek@2374
  1240
                                        PRIVATE | PROTECTED)) {
dbalek@1607
  1241
                        if (checkDisjoint(pos, flags,
dbalek@2374
  1242
                                            PRIVATE,
dbalek@2374
  1243
                                            PUBLIC | PROTECTED)) {
dbalek@2374
  1244
                            if (checkDisjoint(pos, flags,
dbalek@2374
  1245
                                                FINAL,
dbalek@2374
  1246
                                                VOLATILE)) {
dbalek@2374
  1247
                                if ((sym.kind == TYP ||
dbalek@2374
  1248
                                        checkDisjoint(pos, flags,
dbalek@2374
  1249
                                                    ABSTRACT | NATIVE,
dbalek@2374
  1250
                                                    STRICTFP))) {
dbalek@2374
  1251
                                } else {
dbalek@2374
  1252
                                    flags &= ~STRICTFP;
dbalek@2374
  1253
                                }
dbalek@1607
  1254
                            } else {
dbalek@2374
  1255
                                flags &= ~VOLATILE;
dbalek@1607
  1256
                            }
dbalek@1607
  1257
                        } else {
dbalek@2374
  1258
                            flags &= ~(PUBLIC | PROTECTED);
dbalek@1607
  1259
                        }
dbalek@1607
  1260
                    } else {
dbalek@2374
  1261
                        flags &= ~(PRIVATE | PROTECTED);
dbalek@1607
  1262
                    }
dbalek@1607
  1263
                } else {
dbalek@2374
  1264
                    flags &= ~(FINAL | NATIVE | SYNCHRONIZED);
dbalek@1607
  1265
                }
dbalek@1607
  1266
            } else {
dbalek@2374
  1267
                flags &= ~DEFAULT;
dbalek@2374
  1268
            }
dbalek@1607
  1269
        } else {
dbalek@2374
  1270
            flags &= ~(PRIVATE | STATIC | DEFAULT);
duke@0
  1271
        }
mcimadamore@2210
  1272
        return flags & (mask | ~ExtendedStandardFlags) | implicit;
duke@0
  1273
    }
duke@0
  1274
duke@0
  1275
duke@0
  1276
    /** Determine if this enum should be implicitly final.
duke@0
  1277
     *
duke@0
  1278
     *  If the enum has no specialized enum contants, it is final.
duke@0
  1279
     *
duke@0
  1280
     *  If the enum does have specialized enum contants, it is
duke@0
  1281
     *  <i>not</i> final.
duke@0
  1282
     */
duke@0
  1283
    private long implicitEnumFinalFlag(JCTree tree) {
jjg@1972
  1284
        if (!tree.hasTag(CLASSDEF)) return 0;
duke@0
  1285
        class SpecialTreeVisitor extends JCTree.Visitor {
duke@0
  1286
            boolean specialized;
duke@0
  1287
            SpecialTreeVisitor() {
duke@0
  1288
                this.specialized = false;
briangoetz@3808
  1289
            }
duke@0
  1290
jjg@688
  1291
            @Override
duke@0
  1292
            public void visitTree(JCTree tree) { /* no-op */ }
duke@0
  1293
jjg@688
  1294
            @Override
duke@0
  1295
            public void visitVarDef(JCVariableDecl tree) {
duke@0
  1296
                if ((tree.mods.flags & ENUM) != 0) {
duke@0
  1297
                    if (tree.init instanceof JCNewClass &&
duke@0
  1298
                        ((JCNewClass) tree.init).def != null) {
duke@0
  1299
                        specialized = true;
duke@0
  1300
                    }
duke@0
  1301
                }
duke@0
  1302
            }
duke@0
  1303
        }
duke@0
  1304
duke@0
  1305
        SpecialTreeVisitor sts = new SpecialTreeVisitor();
duke@0
  1306
        JCClassDecl cdef = (JCClassDecl) tree;
duke@0
  1307
        for (JCTree defs: cdef.defs) {
duke@0
  1308
            defs.accept(sts);
duke@0
  1309
            if (sts.specialized) return 0;
duke@0
  1310
        }
duke@0
  1311
        return FINAL;
duke@0
  1312
    }
duke@0
  1313
duke@0
  1314
/* *************************************************************************
duke@0
  1315
 * Type Validation
duke@0
  1316
 **************************************************************************/
duke@0
  1317
duke@0
  1318
    /** Validate a type expression. That is,
duke@0
  1319
     *  check that all type arguments of a parametric type are within
jjg@2704
  1320
     *  their bounds. This must be done in a second phase after type attribution
duke@0
  1321
     *  since a class might have a subclass as type parameter bound. E.g:
duke@0
  1322
     *
jjg@2197
  1323
     *  <pre>{@code
duke@0
  1324
     *  class B<A extends C> { ... }
duke@0
  1325
     *  class C extends B<C> { ... }
jjg@2197
  1326
     *  }</pre>
duke@0
  1327
     *
duke@0
  1328
     *  and we can't make sure that the bound is already attributed because
duke@0
  1329
     *  of possible cycles.
mcimadamore@1042
  1330
     *
mcimadamore@1042
  1331
     * Visitor method: Validate a type expression, if it is not null, catching
duke@0
  1332
     *  and reporting any completion failures.
duke@0
  1333
     */
mcimadamore@300
  1334
    void validate(JCTree tree, Env<AttrContext> env) {
mcimadamore@1042
  1335
        validate(tree, env, true);
duke@0
  1336
    }
mcimadamore@1042
  1337
    void validate(JCTree tree, Env<AttrContext> env, boolean checkRaw) {
mcimadamore@1042
  1338
        new Validator(env).validateTree(tree, checkRaw, true);
mcimadamore@300
  1339
    }
duke@0
  1340
duke@0
  1341
    /** Visitor method: Validate a list of type expressions.
duke@0
  1342
     */
mcimadamore@300
  1343
    void validate(List<? extends JCTree> trees, Env<AttrContext> env) {
duke@0
  1344
        for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
mcimadamore@300
  1345
            validate(l.head, env);
duke@0
  1346
    }
duke@0
  1347
duke@0
  1348
    /** A visitor class for type validation.
duke@0
  1349
     */
duke@0
  1350
    class Validator extends JCTree.Visitor {
duke@0
  1351
jlahoda@3054
  1352
        boolean checkRaw;
mcimadamore@1042
  1353
        boolean isOuter;
mcimadamore@1042
  1354
        Env<AttrContext> env;
mcimadamore@1042
  1355
mcimadamore@1042
  1356
        Validator(Env<AttrContext> env) {
mcimadamore@1042
  1357
            this.env = env;
mcimadamore@1042
  1358
        }
mcimadamore@1042
  1359
jjg@688
  1360
        @Override
duke@0
  1361
        public void visitTypeArray(JCArrayTypeTree tree) {
jlahoda@3054
  1362
            validateTree(tree.elemtype, checkRaw, isOuter);
duke@0
  1363
        }
duke@0
  1364
jjg@688
  1365
        @Override
duke@0
  1366
        public void visitTypeApply(JCTypeApply tree) {
dbalek@2330
  1367
            if (tree.type != null && tree.type.hasTag(CLASS)) {
duke@0
  1368
                List<JCExpression> args = tree.arguments;
mcimadamore@337
  1369
                List<Type> forms = tree.type.tsym.type.getTypeArguments();
mcimadamore@1286
  1370
mcimadamore@1286
  1371
                Type incompatibleArg = firstIncompatibleTypeArg(tree.type);
mcimadamore@1286
  1372
                if (incompatibleArg != null) {
mcimadamore@1286
  1373
                    for (JCTree arg : tree.arguments) {
mcimadamore@1286
  1374
                        if (arg.type == incompatibleArg) {
mcimadamore@1298
  1375
                            log.error(arg, "not.within.bounds", incompatibleArg, forms.head);
mcimadamore@1286
  1376
                        }
mcimadamore@1298
  1377
                        forms = forms.tail;
mcimadamore@1298
  1378
                     }
mcimadamore@1298
  1379
                 }
mcimadamore@1298
  1380
mcimadamore@1298
  1381
                forms = tree.type.tsym.type.getTypeArguments();
duke@0
  1382
mcimadamore@1042
  1383
                boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class;
mcimadamore@1042
  1384
duke@0
  1385
                // For matching pairs of actual argument types `a' and
duke@0
  1386
                // formal type parameters with declared bound `b' ...
duke@0
  1387
                while (args.nonEmpty() && forms.nonEmpty()) {
mcimadamore@1042
  1388
                    validateTree(args.head,
mcimadamore@1042
  1389
                            !(isOuter && is_java_lang_Class),
mcimadamore@1042
  1390
                            false);
duke@0
  1391
                    args = args.tail;
duke@0
  1392
                    forms = forms.tail;
duke@0
  1393
                }
duke@0
  1394
duke@0
  1395
                // Check that this type is either fully parameterized, or
duke@0
  1396
                // not parameterized at all.
duke@0
  1397
                if (tree.type.getEnclosingType().isRaw())
duke@0
  1398
                    log.error(tree.pos(), "improperly.formed.type.inner.raw.param");
jjg@1972
  1399
                if (tree.clazz.hasTag(SELECT))
duke@0
  1400
                    visitSelectInternal((JCFieldAccess)tree.clazz);
duke@0
  1401
            }
duke@0
  1402
        }
duke@0
  1403
jjg@688
  1404
        @Override
duke@0
  1405
        public void visitTypeParameter(JCTypeParameter tree) {
mcimadamore@1042
  1406
            validateTrees(tree.bounds, true, isOuter);
duke@0
  1407
            checkClassBounds(tree.pos(), tree.type);
duke@0
  1408
        }
duke@0
  1409
duke@0
  1410
        @Override
duke@0
  1411
        public void visitWildcard(JCWildcard tree) {
duke@0
  1412
            if (tree.inner != null)
mcimadamore@1042
  1413
                validateTree(tree.inner, true, isOuter);
duke@0
  1414
        }
duke@0
  1415
jjg@688
  1416
        @Override
duke@0
  1417
        public void visitSelect(JCFieldAccess tree) {
jjg@2213
  1418
            if (tree.type.hasTag(CLASS)) {
duke@0
  1419
                visitSelectInternal(tree);
duke@0
  1420
duke@0
  1421
                // Check that this type is either fully parameterized, or
duke@0
  1422
                // not parameterized at all.
duke@0
  1423
                if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty())
duke@0
  1424
                    log.error(tree.pos(), "improperly.formed.type.param.missing");
duke@0
  1425
            }
duke@0
  1426
        }
mcimadamore@1317
  1427
duke@0
  1428
        public void visitSelectInternal(JCFieldAccess tree) {
mcimadamore@300
  1429
            if (tree.type.tsym.isStatic() &&
duke@0
  1430
                tree.selected.type.isParameterized()) {
duke@0
  1431
                // The enclosing type is not a class, so we are
duke@0
  1432
                // looking at a static member type.  However, the
duke@0
  1433
                // qualifying expression is parameterized.
duke@0
  1434
                log.error(tree.pos(), "cant.select.static.class.from.param.type");
duke@0
  1435
            } else {
duke@0
  1436
                // otherwise validate the rest of the expression
mcimadamore@300
  1437
                tree.selected.accept(this);
duke@0
  1438
            }
duke@0
  1439
        }
duke@0
  1440
jjg@2372
  1441
        @Override
jjg@2372
  1442
        public void visitAnnotatedType(JCAnnotatedType tree) {
jjg@2372
  1443
            tree.underlyingType.accept(this);
jjg@2372
  1444
        }
jjg@2372
  1445
jlahoda@3233
  1446
        @Override
jlahoda@3233
  1447
        public void visitTypeIdent(JCPrimitiveTypeTree that) {
jlahoda@3233
  1448
            if (that.type.hasTag(TypeTag.VOID)) {
jlahoda@3233
  1449
                log.error(that.pos(), "void.not.allowed.here");
jlahoda@3233
  1450
            }
jlahoda@3233
  1451
            super.visitTypeIdent(that);
jlahoda@3233
  1452
        }
jlahoda@3233
  1453
duke@0
  1454
        /** Default visitor method: do nothing.
duke@0
  1455
         */
jjg@688
  1456
        @Override
duke@0
  1457
        public void visitTree(JCTree tree) {
duke@0
  1458
        }
mcimadamore@300
  1459
mcimadamore@1042
  1460
        public void validateTree(JCTree tree, boolean checkRaw, boolean isOuter) {
jlahoda@3054
  1461
            if (tree != null) {
jlahoda@3054
  1462
                boolean prevCheckRaw = this.checkRaw;
jlahoda@3054
  1463
                this.checkRaw = checkRaw;
jlahoda@3054
  1464
                this.isOuter = isOuter;
jlahoda@3054
  1465
jlahoda@3054
  1466
                try {
mcimadamore@1042
  1467
                    tree.accept(this);
mcimadamore@1042
  1468
                    if (checkRaw)
mcimadamore@1042
  1469
                        checkRaw(tree, env);
jlahoda@3054
  1470
                } catch (CompletionFailure ex) {
jlahoda@3054
  1471
                    completionError(tree.pos(), ex);
jlahoda@3054
  1472
                } finally {
jlahoda@3054
  1473
                    this.checkRaw = prevCheckRaw;
mcimadamore@1042
  1474
                }
mcimadamore@1042
  1475
            }
mcimadamore@1042
  1476
        }
mcimadamore@1042
  1477
mcimadamore@1042
  1478
        public void validateTrees(List<? extends JCTree> trees, boolean checkRaw, boolean isOuter) {
mcimadamore@1042
  1479
            for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
mcimadamore@1042
  1480
                validateTree(l.head, checkRaw, isOuter);
mcimadamore@1042
  1481
        }
mcimadamore@2709
  1482
    }
mcimadamore@2709
  1483
mcimadamore@2709
  1484
    void checkRaw(JCTree tree, Env<AttrContext> env) {
mcimadamore@2709
  1485
        if (lint.isEnabled(LintCategory.RAW) &&
mcimadamore@2709
  1486
            tree.type.hasTag(CLASS) &&
mcimadamore@2709
  1487
            !TreeInfo.isDiamond(tree) &&
mcimadamore@2709
  1488
            !withinAnonConstr(env) &&
mcimadamore@2709
  1489
            tree.type.isRaw()) {
mcimadamore@2709
  1490
            log.warning(LintCategory.RAW,
mcimadamore@2709
  1491
                    tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type);
mcimadamore@1042
  1492
        }
mcimadamore@2709
  1493
    }
mcimadamore@2709
  1494
    //where
mcimadamore@2709
  1495
        private boolean withinAnonConstr(Env<AttrContext> env) {
mcimadamore@1943
  1496
            return env.enclClass.name.isEmpty() &&
mcimadamore@1943
  1497
                    env.enclMethod != null && env.enclMethod.name == names.init;
mcimadamore@1943
  1498
        }
duke@0
  1499
duke@0
  1500
/* *************************************************************************
duke@0
  1501
 * Exception checking
duke@0
  1502
 **************************************************************************/
duke@0
  1503
duke@0
  1504
    /* The following methods treat classes as sets that contain
duke@0
  1505
     * the class itself and all their subclasses
duke@0
  1506
     */
duke@0
  1507
duke@0
  1508
    /** Is given type a subtype of some of the types in given list?
duke@0
  1509
     */
duke@0
  1510
    boolean subset(Type t, List<Type> ts) {
dbalek@1881
  1511
        if (t == null)
dbalek@1881
  1512
            return false;
duke@0
  1513
        for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
duke@0
  1514
            if (types.isSubtype(t, l.head)) return true;
duke@0
  1515
        return false;
duke@0
  1516
    }
duke@0
  1517
duke@0
  1518
    /** Is given type a subtype or supertype of
duke@0
  1519
     *  some of the types in given list?
duke@0
  1520
     */
duke@0
  1521
    boolean intersects(Type t, List<Type> ts) {
dbalek@1881
  1522
        if (t == null)
dbalek@1881
  1523
            return false;
duke@0
  1524
        for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
duke@0
  1525
            if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true;
duke@0
  1526
        return false;
duke@0
  1527
    }
duke@0
  1528
duke@0
  1529
    /** Add type set to given type list, unless it is a subclass of some class
duke@0
  1530
     *  in the list.
duke@0
  1531
     */
duke@0
  1532
    List<Type> incl(Type t, List<Type> ts) {
dbalek@1881
  1533
        return (t == null || subset(t, ts)) ? ts : excl(t, ts).prepend(t);
duke@0
  1534
    }
duke@0
  1535
duke@0
  1536
    /** Remove type set from type set list.
duke@0
  1537
     */
duke@0
  1538
    List<Type> excl(Type t, List<Type> ts) {
dbalek@1881
  1539
        if (t == null || ts.isEmpty()) {
duke@0
  1540
            return ts;
duke@0
  1541
        } else {
duke@0
  1542
            List<Type> ts1 = excl(t, ts.tail);
duke@0
  1543
            if (types.isSubtype(ts.head, t)) return ts1;
duke@0
  1544
            else if (ts1 == ts.tail) return ts;
duke@0
  1545
            else return ts1.prepend(ts.head);
duke@0
  1546
        }
duke@0
  1547
    }
duke@0
  1548
duke@0
  1549
    /** Form the union of two type set lists.
duke@0
  1550
     */
duke@0
  1551
    List<Type> union(List<Type> ts1, List<Type> ts2) {
duke@0
  1552
        List<Type> ts = ts1;
duke@0
  1553
        for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
duke@0
  1554
            ts = incl(l.head, ts);
duke@0
  1555
        return ts;
duke@0
  1556
    }
duke@0
  1557
duke@0
  1558
    /** Form the difference of two type lists.
duke@0
  1559
     */
duke@0
  1560
    List<Type> diff(List<Type> ts1, List<Type> ts2) {
duke@0
  1561
        List<Type> ts = ts1;
duke@0
  1562
        for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
duke@0
  1563
            ts = excl(l.head, ts);
duke@0
  1564
        return ts;
duke@0
  1565
    }
duke@0
  1566
duke@0
  1567
    /** Form the intersection of two type lists.
duke@0
  1568
     */
duke@0
  1569
    public List<Type> intersect(List<Type> ts1, List<Type> ts2) {
duke@0
  1570
        List<Type> ts = List.nil();
duke@0
  1571
        for (List<Type> l = ts1; l.nonEmpty(); l = l.tail)
duke@0
  1572
            if (subset(l.head, ts2)) ts = incl(l.head, ts);
duke@0
  1573
        for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
duke@0
  1574
            if (subset(l.head, ts1)) ts = incl(l.head, ts);
duke@0
  1575
        return ts;
duke@0
  1576
    }
duke@0
  1577
duke@0
  1578
    /** Is exc an exception symbol that need not be declared?
duke@0
  1579
     */
duke@0
  1580
    boolean isUnchecked(ClassSymbol exc) {
duke@0
  1581
        return
duke@0
  1582
            exc.kind == ERR ||
duke@0
  1583
            exc.isSubClass(syms.errorType.tsym, types) ||
duke@0
  1584
            exc.isSubClass(syms.runtimeExceptionType.tsym, types);
duke@0
  1585
    }
duke@0
  1586
duke@0
  1587
    /** Is exc an exception type that need not be declared?
duke@0
  1588
     */
duke@0
  1589
    boolean isUnchecked(Type exc) {
duke@0
  1590
        return
dbalek@153
  1591
            (exc == null) ? true :
jjg@2213
  1592
            (exc.hasTag(TYPEVAR)) ? isUnchecked(types.supertype(exc)) :
jjg@2213
  1593
            (exc.hasTag(CLASS)) ? isUnchecked((ClassSymbol)exc.tsym) :
dbalek@2330
  1594
            exc.hasTag(BOT) || exc.hasTag(ERROR);
duke@0
  1595
    }
duke@0
  1596
duke@0
  1597
    /** Same, but handling completion failures.
duke@0
  1598
     */
duke@0
  1599
    boolean isUnchecked(DiagnosticPosition pos, Type exc) {
duke@0
  1600
        try {
duke@0
  1601
            return isUnchecked(exc);
duke@0
  1602
        } catch (CompletionFailure ex) {
duke@0
  1603
            completionError(pos, ex);
duke@0
  1604
            return true;
duke@0
  1605
        }
duke@0
  1606
    }
duke@0
  1607
duke@0
  1608
    /** Is exc handled by given exception list?
duke@0
  1609
     */
duke@0
  1610
    boolean isHandled(Type exc, List<Type> handled) {
duke@0
  1611
        return isUnchecked(exc) || subset(exc, handled);
duke@0
  1612
    }
duke@0
  1613
duke@0
  1614
    /** Return all exceptions in thrown list that are not in handled list.
duke@0
  1615
     *  @param thrown     The list of thrown exceptions.
duke@0
  1616
     *  @param handled    The list of handled exceptions.
duke@0
  1617
     */
mcimadamore@652
  1618
    List<Type> unhandled(List<Type> thrown, List<Type> handled) {
duke@0
  1619
        List<Type> unhandled = List.nil();
duke@0
  1620
        for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
duke@0
  1621
            if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head);
duke@0
  1622
        return unhandled;
duke@0
  1623
    }
duke@0
  1624
duke@0
  1625
/* *************************************************************************
duke@0
  1626
 * Overriding/Implementation checking
duke@0
  1627
 **************************************************************************/
duke@0
  1628
duke@0
  1629
    /** The level of access protection given by a flag set,
duke@0
  1630
     *  where PRIVATE is highest and PUBLIC is lowest.
duke@0
  1631
     */
duke@0
  1632
    static int protection(long flags) {
duke@0
  1633
        switch ((short)(flags & AccessFlags)) {
duke@0
  1634
        case PRIVATE: return 3;
duke@0
  1635
        case PROTECTED: return 1;
duke@0
  1636
        default:
duke@0
  1637
        case PUBLIC: return 0;
duke@0
  1638
        case 0: return 2;
duke@0
  1639
        }
duke@0
  1640
    }
duke@0
  1641
duke@0
  1642
    /** A customized "cannot override" error message.
duke@0
  1643
     *  @param m      The overriding method.
duke@0
  1644
     *  @param other  The overridden method.
duke@0
  1645
     *  @return       An internationalized string.
duke@0
  1646
     */
mcimadamore@268
  1647
    Object cannotOverride(MethodSymbol m, MethodSymbol other) {
duke@0
  1648
        String key;
duke@0
  1649
        if ((other.owner.flags() & INTERFACE) == 0)
duke@0
  1650
            key = "cant.override";
duke@0
  1651
        else if ((m.owner.flags() & INTERFACE) == 0)
duke@0
  1652
            key = "cant.implement";
duke@0
  1653
        else
duke@0
  1654
            key = "clashes.with";
mcimadamore@268
  1655
        return diags.fragment(key, m, m.location(), other, other.location());
duke@0
  1656
    }
duke@0
  1657
duke@0
  1658
    /** A customized "override" warning message.
duke@0
  1659
     *  @param m      The overriding method.
duke@0
  1660
     *  @param other  The overridden method.
duke@0
  1661
     *  @return       An internationalized string.
duke@0
  1662
     */
mcimadamore@268
  1663
    Object uncheckedOverrides(MethodSymbol m, MethodSymbol other) {
duke@0
  1664
        String key;
duke@0
  1665
        if ((other.owner.flags() & INTERFACE) == 0)
duke@0
  1666
            key = "unchecked.override";
duke@0
  1667
        else if ((m.owner.flags() & INTERFACE) == 0)
duke@0
  1668
            key = "unchecked.implement";
duke@0
  1669
        else
duke@0
  1670
            key = "unchecked.clash.with";
mcimadamore@268
  1671
        return diags.fragment(key, m, m.location(), other, other.location());
duke@0
  1672
    }
duke@0
  1673
duke@0
  1674
    /** A customized "override" warning message.
duke@0
  1675
     *  @param m      The overriding method.
duke@0
  1676
     *  @param other  The overridden method.
duke@0
  1677
     *  @return       An internationalized string.
duke@0
  1678
     */
mcimadamore@268
  1679
    Object varargsOverrides(MethodSymbol m, MethodSymbol other) {
duke@0
  1680
        String key;
duke@0
  1681
        if ((other.owner.flags() & INTERFACE) == 0)
duke@0
  1682
            key = "varargs.override";
duke@0
  1683
        else  if ((m.owner.flags() & INTERFACE) == 0)
duke@0
  1684
            key = "varargs.implement";
duke@0
  1685
        else
duke@0
  1686
            key = "varargs.clash.with";
mcimadamore@268
  1687
        return diags.fragment(key, m, m.location(), other, other.location());
duke@0
  1688
    }
duke@0
  1689
duke@0
  1690
    /** Check that this method conforms with overridden method 'other'.
duke@0
  1691
     *  where `origin' is the class where checking started.
duke@0
  1692
     *  Complications:
duke@0
  1693
     *  (1) Do not check overriding of synthetic methods
duke@0
  1694
     *      (reason: they might be final).
duke@0
  1695
     *      todo: check whether this is still necessary.
duke@0
  1696
     *  (2) Admit the case where an interface proxy throws fewer exceptions
duke@0
  1697
     *      than the method it implements. Augment the proxy methods with the
duke@0
  1698
     *      undeclared exceptions in this case.
duke@0
  1699
     *  (3) When generics are enabled, admit the case where an interface proxy
duke@0
  1700
     *      has a result type
duke@0
  1701
     *      extended by the result type of the method it implements.
duke@0
  1702
     *      Change the proxies result type to the smaller type in this case.
duke@0
  1703
     *
duke@0
  1704
     *  @param tree         The tree from which positions
duke@0
  1705
     *                      are extracted for errors.
duke@0
  1706
     *  @param m            The overriding method.
duke@0
  1707
     *  @param other        The overridden method.
duke@0
  1708
     *  @param origin       The class of which the overriding method
duke@0
  1709
     *                      is a member.
duke@0
  1710
     */
duke@0
  1711
    void checkOverride(JCTree tree,
duke@0
  1712
                       MethodSymbol m,
duke@0
  1713
                       MethodSymbol other,
duke@0
  1714
                       ClassSymbol origin) {
duke@0
  1715
        // Don't check overriding of synthetic methods or by bridge methods.
duke@0
  1716
        if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) {
duke@0
  1717
            return;
duke@0
  1718
        }
duke@0
  1719
duke@0
  1720
        // Error if static method overrides instance method (JLS 8.4.6.2).
duke@0
  1721
        if ((m.flags() & STATIC) != 0 &&
duke@0
  1722
                   (other.flags() & STATIC) == 0) {
duke@0
  1723
            log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.static",
duke@0
  1724
                      cannotOverride(m, other));
vromero@2497
  1725
            m.flags_field |= BAD_OVERRIDE;
duke@0
  1726
            return;
duke@0
  1727
        }
duke@0
  1728
duke@0
  1729
        // Error if instance method overrides static or final
duke@0
  1730
        // method (JLS 8.4.6.1).
duke@0
  1731
        if ((other.flags() & FINAL) != 0 ||
duke@0
  1732
                 (m.flags() & STATIC) == 0 &&
duke@0
  1733
                 (other.flags() & STATIC) != 0) {
duke@0
  1734
            log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth",
duke@0
  1735
                      cannotOverride(m, other),
mcimadamore@261
  1736
                      asFlagSet(other.flags() & (FINAL | STATIC)));
vromero@2497
  1737
            m.flags_field |= BAD_OVERRIDE;
duke@0
  1738
            return;
duke@0
  1739
        }
duke@0
  1740
duke@0
  1741
        if ((m.owner.flags() & ANNOTATION) != 0) {
duke@0
  1742
            // handled in validateAnnotationMethod
duke@0
  1743
            return;
duke@0
  1744
        }
duke@0
  1745
duke@0
  1746
        // Error if overriding method has weaker access (JLS 8.4.6.3).
sadayapalam@4414
  1747
        if (protection(m.flags()) > protection(other.flags())) {
duke@0
  1748
            log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.weaker.access",
duke@0
  1749
                      cannotOverride(m, other),
kizune@3914
  1750
                      (other.flags() & AccessFlags) == 0 ?
vromero@2826
  1751
                          "package" :
mcimadamore@261
  1752
                          asFlagSet(other.flags() & AccessFlags));
vromero@2497
  1753
            m.flags_field |= BAD_OVERRIDE;
duke@0
  1754
            return;
duke@0
  1755
        }
duke@0
  1756
duke@0
  1757
        Type mt = types.memberType(origin.type, m);
duke@0
  1758
        Type ot = types.memberType(origin.type, other);
duke@0
  1759
        // Error if overriding result type is different
duke@0
  1760
        // (or, in the case of generics mode, not a subtype) of
duke@0
  1761
        // overridden result type. We have to rename any type parameters
duke@0
  1762
        // before comparing types.
duke@0
  1763
        List<Type> mtvars = mt.getTypeArguments();
duke@0
  1764
        List<Type> otvars = ot.getTypeArguments();
duke@0
  1765
        Type mtres = mt.getReturnType();
duke@0
  1766
        Type otres = types.subst(ot.getReturnType(), otvars, mtvars);
duke@0
  1767
mcimadamore@1244
  1768
        overrideWarner.clear();
duke@0
  1769
        boolean resultTypesOK =
tbell@380
  1770
            types.returnTypeSubstitutable(mt, ot, otres, overrideWarner);
duke@0
  1771
        if (!resultTypesOK) {
sadayapalam@4681
  1772
            if ((m.flags() & STATIC) != 0 && (other.flags() & STATIC) != 0) {
sadayapalam@4681
  1773
                log.error(TreeInfo.diagnosticPositionFor(m, tree),
sadayapalam@4681
  1774
                        Errors.OverrideIncompatibleRet(Fragments.CantHide(m, m.location(), other,
sadayapalam@4681
  1775
                                        other.location()), mtres, otres));
sadayapalam@4681
  1776
                m.flags_field |= BAD_OVERRIDE;
sadayapalam@4681
  1777
            } else {
sadayapalam@4681
  1778
                log.error(TreeInfo.diagnosticPositionFor(m, tree),
sadayapalam@4681
  1779
                        "override.incompatible.ret",
sadayapalam@4681
  1780
                        cannotOverride(m, other),
sadayapalam@4681
  1781
                        mtres, otres);
sadayapalam@4681
  1782
                m.flags_field |= BAD_OVERRIDE;
sadayapalam@4681
  1783
            }
ntoda@4105
  1784
            return;
mcimadamore@1244
  1785
        } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
dbalek@1332
  1786
            warnDeferredUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
mcimadamore@652
  1787
                    "override.unchecked.ret",
mcimadamore@652
  1788
                    uncheckedOverrides(m, other),
mcimadamore@652
  1789
                    mtres, otres);
duke@0
  1790
        }
duke@0
  1791
duke@0
  1792
        // Error if overriding method throws an exception not reported
duke@0
  1793
        // by overridden method.
duke@0
  1794
        List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars);
mcimadamore@652
  1795
        List<Type> unhandledErased = unhandled(mt.getThrownTypes(), types.erasure(otthrown));
mcimadamore@652
  1796
        List<Type> unhandledUnerased = unhandled(mt.getThrownTypes(), otthrown);
mcimadamore@652
  1797
        if (unhandledErased.nonEmpty()) {
duke@0
  1798
            log.error(TreeInfo.diagnosticPositionFor(m, tree),
duke@0
  1799
                      "override.meth.doesnt.throw",
duke@0
  1800
                      cannotOverride(m, other),
mcimadamore@652
  1801
                      unhandledUnerased.head);
vromero@2497
  1802
            m.flags_field |= BAD_OVERRIDE;
mcimadamore@652
  1803
            return;
mcimadamore@652
  1804
        }
mcimadamore@652
  1805
        else if (unhandledUnerased.nonEmpty()) {
dbalek@1332
  1806
            warnDeferredUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
mcimadamore@652
  1807
                          "override.unchecked.thrown",
mcimadamore@652
  1808
                         cannotOverride(m, other),
mcimadamore@652
  1809
                         unhandledUnerased.head);
duke@0
  1810
            return;
duke@0
  1811
        }
duke@0
  1812
duke@0
  1813
        // Optional warning if varargs don't agree
duke@0
  1814
        if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)
mcimadamore@1244
  1815
            && lint.isEnabled(LintCategory.OVERRIDES)) {
duke@0
  1816
            log.warning(TreeInfo.diagnosticPositionFor(m, tree),
duke@0
  1817
                        ((m.flags() & Flags.VARARGS) != 0)
duke@0
  1818
                        ? "override.varargs.missing"
duke@0
  1819
                        : "override.varargs.extra",
duke@0
  1820
                        varargsOverrides(m, other));
duke@0
  1821
        }
duke@0
  1822
duke@0
  1823
        // Warn if instance method overrides bridge method (compiler spec ??)
duke@0
  1824
        if ((other.flags() & BRIDGE) != 0) {
duke@0
  1825
            log.warning(TreeInfo.diagnosticPositionFor(m, tree), "override.bridge",
duke@0
  1826
                        uncheckedOverrides(m, other));
duke@0
  1827
        }
duke@0
  1828
duke@0
  1829
        // Warn if a deprecated method overridden by a non-deprecated one.
mcimadamore@1317
  1830
        if (!isDeprecatedOverrideIgnorable(other, origin)) {
jlahoda@3864
  1831
            Lint prevLint = setLint(lint.augment(m));
jlahoda@3864
  1832
            try {
jlahoda@3864
  1833
                checkDeprecated(TreeInfo.diagnosticPositionFor(m, tree), m, other);
jlahoda@3864
  1834
            } finally {
jlahoda@3864
  1835
                setLint(prevLint);
jlahoda@3864
  1836
            }
duke@0
  1837
        }
duke@0
  1838
    }
duke@0
  1839
    // where
dbalek@1332
  1840
        private void warnDeferredUnchecked(final DiagnosticPosition pos, final String msg, final Object... args) {
dbalek@3084
  1841
            DiagnosticPosition prevPos = deferredLintHandler.setPos(pos);
dbalek@1332
  1842
            try {
dbalek@1332
  1843
                deferredLintHandler.report(new DeferredLintHandler.LintLogger() {
dbalek@1332
  1844
                    @Override
dbalek@1332
  1845
                    public void report() {
dbalek@1332
  1846
                        warnUnchecked(pos, msg, args);
dbalek@1332
  1847
                    }
dbalek@1332
  1848
                });
dbalek@1332
  1849
            } finally {
dbalek@1332
  1850
                deferredLintHandler.setPos(prevPos);
dbalek@1332
  1851
            }
dbalek@1332
  1852
        }
dbalek@1332
  1853
duke@0
  1854
        private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) {
duke@0
  1855
            // If the method, m, is defined in an interface, then ignore the issue if the method
duke@0
  1856
            // is only inherited via a supertype and also implemented in the supertype,
duke@0
  1857
            // because in that case, we will rediscover the issue when examining the method
duke@0
  1858
            // in the supertype.
duke@0
  1859
            // If the method, m, is not defined in an interface, then the only time we need to
duke@0
  1860
            // address the issue is when the method is the supertype implemementation: any other
duke@0
  1861
            // case, we will have dealt with when examining the supertype classes
duke@0
  1862
            ClassSymbol mc = m.enclClass();
duke@0
  1863
            Type st = types.supertype(origin.type);
jjg@2213
  1864
            if (!st.hasTag(CLASS))
duke@0
  1865
                return true;
duke@0
  1866
            MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false);
duke@0
  1867
duke@0
  1868
            if (mc != null && ((mc.flags() & INTERFACE) != 0)) {
duke@0
  1869
                List<Type> intfs = types.interfaces(origin.type);
duke@0
  1870
                return (intfs.contains(mc.type) ? false : (stimpl != null));
duke@0
  1871
            }
duke@0
  1872
            else
duke@0
  1873
                return (stimpl != m);
duke@0
  1874
        }
duke@0
  1875
duke@0
  1876
duke@0
  1877
    // used to check if there were any unchecked conversions
duke@0
  1878
    Warner overrideWarner = new Warner();
duke@0
  1879
duke@0
  1880
    /** Check that a class does not inherit two concrete methods
duke@0
  1881
     *  with the same signature.
duke@0
  1882
     *  @param pos          Position to be used for error reporting.
duke@0
  1883
     *  @param site         The class type to be checked.
duke@0
  1884
     */
duke@0
  1885
    public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) {
duke@0
  1886
        Type sup = types.supertype(site);
jjg@2213
  1887
        if (!sup.hasTag(CLASS)) return;
duke@0
  1888
duke@0
  1889
        for (Type t1 = sup;
jlahoda@2972
  1890
             t1.hasTag(CLASS) && t1.tsym.type.isParameterized();
duke@0
  1891
             t1 = types.supertype(t1)) {
jlahoda@4103
  1892
            for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) {
duke@0
  1893
                if (s1.kind != MTH ||
duke@0
  1894
                    (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
duke@0
  1895
                    !s1.isInheritedIn(site.tsym, types) ||
duke@0
  1896
                    ((MethodSymbol)s1).implementation(site.tsym,
duke@0
  1897
                                                      types,
duke@0
  1898
                                                      true) != s1)
duke@0
  1899
                    continue;
duke@0
  1900
                Type st1 = types.memberType(t1, s1);
duke@0
  1901
                int s1ArgsLength = st1.getParameterTypes().length();
duke@0
  1902
                if (st1 == s1.type) continue;
duke@0
  1903
duke@0
  1904
                for (Type t2 = sup;
jjg@2213
  1905
                     t2.hasTag(CLASS);
duke@0
  1906
                     t2 = types.supertype(t2)) {
jlahoda@4103
  1907
                    for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) {
duke@0
  1908
                        if (s2 == s1 ||
duke@0
  1909
                            s2.kind != MTH ||
duke@0
  1910
                            (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
duke@0
  1911
                            s2.type.getParameterTypes().length() != s1ArgsLength ||
duke@0
  1912
                            !s2.isInheritedIn(site.tsym, types) ||
duke@0
  1913
                            ((MethodSymbol)s2).implementation(site.tsym,
duke@0
  1914
                                                              types,
duke@0
  1915
                                                              true) != s2)
duke@0
  1916
                            continue;
duke@0
  1917
                        Type st2 = types.memberType(t2, s2);
duke@0
  1918
                        if (types.overrideEquivalent(st1, st2))
duke@0
  1919
                            log.error(pos, "concrete.inheritance.conflict",
duke@0
  1920
                                      s1, t1, s2, t2, sup);
duke@0
  1921
                    }
duke@0
  1922
                }
duke@0
  1923
            }
duke@0
  1924
        }
duke@0
  1925
    }
duke@0
  1926
duke@0
  1927
    /** Check that classes (or interfaces) do not each define an abstract
duke@0
  1928
     *  method with same name and arguments but incompatible return types.
duke@0
  1929
     *  @param pos          Position to be used for error reporting.
duke@0
  1930
     *  @param t1           The first argument type.
duke@0
  1931
     *  @param t2           The second argument type.
duke@0
  1932
     */
duke@0
  1933
    public boolean checkCompatibleAbstracts(DiagnosticPosition pos,
duke@0
  1934
                                            Type t1,
duke@0
  1935
                                            Type t2,
duke@0
  1936
                                            Type site) {
dlsmith@4035
  1937
        if ((site.tsym.flags() & COMPOUND) != 0) {
dlsmith@4035
  1938
            // special case for intersections: need to eliminate wildcards in supertypes
dlsmith@4035
  1939
            t1 = types.capture(t1);
dlsmith@4035
  1940
            t2 = types.capture(t2);
dlsmith@4035
  1941
        }
mcimadamore@1194
  1942
        return firstIncompatibility(pos, t1, t2, site) == null;
duke@0
  1943
    }
duke@0
  1944
duke@0
  1945
    /** Return the first method which is defined with same args
duke@0
  1946
     *  but different return types in two given interfaces, or null if none
duke@0
  1947
     *  exists.
duke@0
  1948
     *  @param t1     The first type.
duke@0
  1949
     *  @param t2     The second type.
duke@0
  1950
     *  @param site   The most derived type.
duke@0
  1951
     *  @returns symbol from t2 that conflicts with one in t1.
duke@0
  1952
     */
mcimadamore@1194
  1953
    private Symbol firstIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) {
briangoetz@3808
  1954
        Map<TypeSymbol,Type> interfaces1 = new HashMap<>();
duke@0
  1955
        closure(t1, interfaces1);
duke@0
  1956
        Map<TypeSymbol,Type> interfaces2;
duke@0
  1957
        if (t1 == t2)
duke@0
  1958
            interfaces2 = interfaces1;
duke@0
  1959
        else
briangoetz@3808
  1960
            closure(t2, interfaces1, interfaces2 = new HashMap<>());
duke@0
  1961
duke@0
  1962
        for (Type t3 : interfaces1.values()) {
duke@0
  1963
            for (Type t4 : interfaces2.values()) {
mcimadamore@1194
  1964
                Symbol s = firstDirectIncompatibility(pos, t3, t4, site);
duke@0
  1965
                if (s != null) return s;
duke@0
  1966
            }
duke@0
  1967
        }
duke@0
  1968
        return null;
duke@0
  1969
    }
duke@0
  1970
duke@0
  1971
    /** Compute all the supertypes of t, indexed by type symbol. */
duke@0
  1972
    private void closure(Type t, Map<TypeSymbol,Type> typeMap) {
jjg@2213
  1973
        if (!t.hasTag(CLASS)) return;
duke@0
  1974
        if (typeMap.put(t.tsym, t) == null) {
duke@0
  1975
            closure(types.supertype(t), typeMap);
duke@0
  1976
            for (Type i : types.interfaces(t))
duke@0
  1977
                closure(i, typeMap);
duke@0
  1978
        }
duke@0
  1979
    }
duke@0
  1980
duke@0
  1981
    /** Compute all the supertypes of t, indexed by type symbol (except thise in typesSkip). */
duke@0
  1982
    private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) {
jjg@2213
  1983
        if (!t.hasTag(CLASS)) return;
duke@0
  1984
        if (typesSkip.get(t.tsym) != null) return;
duke@0
  1985
        if (typeMap.put(t.tsym, t) == null) {
duke@0
  1986
            closure(types.supertype(t), typesSkip, typeMap);
duke@0
  1987
            for (Type i : types.interfaces(t))
duke@0
  1988
                closure(i, typesSkip, typeMap);
duke@0
  1989
        }
duke@0
  1990
    }
duke@0
  1991
duke@0
  1992
    /** Return the first method in t2 that conflicts with a method from t1. */
mcimadamore@1194
  1993
    private Symbol firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) {
jlahoda@4103
  1994
        for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) {
duke@0
  1995
            Type st1 = null;
mcimadamore@2284
  1996
            if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types) ||
mcimadamore@2284
  1997
                    (s1.flags() & SYNTHETIC) != 0) continue;
duke@0
  1998
            Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false);
duke@0
  1999
            if (impl != null && (impl.flags() & ABSTRACT) == 0) continue;
jlahoda@4103
  2000
            for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) {
duke@0
  2001
                if (s1 == s2) continue;
mcimadamore@2284
  2002
                if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types) ||
mcimadamore@2284
  2003
                        (s2.flags() & SYNTHETIC) != 0) continue;
duke@0
  2004
                if (st1 == null) st1 = types.memberType(t1, s1);
duke@0
  2005
                Type st2 = types.memberType(t2, s2);
duke@0
  2006
                if (types.overrideEquivalent(st1, st2)) {
duke@0
  2007
                    List<Type> tvars1 = st1.getTypeArguments();
duke@0
  2008
                    List<Type> tvars2 = st2.getTypeArguments();
duke@0
  2009
                    Type rt1 = st1.getReturnType();
duke@0
  2010
                    Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1);
duke@0
  2011
                    boolean compat =
duke@0
  2012
                        types.isSameType(rt1, rt2) ||
jjg@2213
  2013
                        !rt1.isPrimitiveOrVoid() &&
jjg@2213
  2014
                        !rt2.isPrimitiveOrVoid() &&
mcimadamore@2260
  2015
                        (types.covariantReturnType(rt1, rt2, types.noWarnings) ||
mcimadamore@2260
  2016
                         types.covariantReturnType(rt2, rt1, types.noWarnings)) ||
mcimadamore@233
  2017
                         checkCommonOverriderIn(s1,s2,site);
mcimadamore@1194
  2018
                    if (!compat) {
mcimadamore@1194
  2019
                        log.error(pos, "types.incompatible.diff.ret",
mcimadamore@1194
  2020
                            t1, t2, s2.name +
mcimadamore@1194
  2021
                            "(" + types.memberType(t2, s2).getParameterTypes() + ")");
mcimadamore@1194
  2022
                        return s2;
mcimadamore@1194
  2023
                    }
mcimadamore@1367
  2024
                } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2) &&
mcimadamore@1367
  2025
                        !checkCommonOverriderIn(s1, s2, site)) {
mcimadamore@1194
  2026
                    log.error(pos,
mcimadamore@1194
  2027
                            "name.clash.same.erasure.no.override",
mcimadamore@1194
  2028
                            s1, s1.location(),
mcimadamore@1194
  2029
                            s2, s2.location());
mcimadamore@1194
  2030
                    return s2;
duke@0
  2031
                }
duke@0
  2032
            }
duke@0
  2033
        }
duke@0
  2034
        return null;
duke@0
  2035
    }
mcimadamore@233
  2036
    //WHERE
mcimadamore@233
  2037
    boolean checkCommonOverriderIn(Symbol s1, Symbol s2, Type site) {
briangoetz@3808
  2038
        Map<TypeSymbol,Type> supertypes = new HashMap<>();
mcimadamore@233
  2039
        Type st1 = types.memberType(site, s1);
mcimadamore@233
  2040
        Type st2 = types.memberType(site, s2);
mcimadamore@233
  2041
        closure(site, supertypes);
mcimadamore@233
  2042
        for (Type t : supertypes.values()) {
jlahoda@4103
  2043
            for (Symbol s3 : t.tsym.members().getSymbolsByName(s1.name)) {
mcimadamore@233
  2044
                if (s3 == s1 || s3 == s2 || s3.kind != MTH || (s3.flags() & (BRIDGE|SYNTHETIC)) != 0) continue;
mcimadamore@233
  2045
                Type st3 = types.memberType(site,s3);
mcimadamore@2795
  2046
                if (types.overrideEquivalent(st3, st1) &&
mcimadamore@2795
  2047
                        types.overrideEquivalent(st3, st2) &&
mcimadamore@2795
  2048
                        types.returnTypeSubstitutable(st3, st1) &&
mcimadamore@2795
  2049
                        types.returnTypeSubstitutable(st3, st2)) {
mcimadamore@2795
  2050
                    return true;
mcimadamore@233
  2051
                }
mcimadamore@233
  2052
            }
mcimadamore@233
  2053
        }
mcimadamore@233
  2054
        return false;
mcimadamore@233
  2055
    }
duke@0
  2056
duke@0
  2057
    /** Check that a given method conforms with any method it overrides.
duke@0
  2058
     *  @param tree         The tree from which positions are extracted
duke@0
  2059
     *                      for errors.
duke@0
  2060
     *  @param m            The overriding method.
duke@0
  2061
     */
sadayapalam@4445
  2062
    void checkOverride(Env<AttrContext> env, JCMethodDecl tree, MethodSymbol m) {
duke@0
  2063
        ClassSymbol origin = (ClassSymbol)m.owner;
duke@0
  2064
        if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name))
duke@0
  2065
            if (m.overrides(syms.enumFinalFinalize, origin, types, false)) {
duke@0
  2066
                log.error(tree.pos(), "enum.no.finalize");
duke@0
  2067
                return;
duke@0
  2068
            }
jjg@2213
  2069
        for (Type t = origin.type; t.hasTag(CLASS);
duke@0
  2070
             t = types.supertype(t)) {
mcimadamore@1194
  2071
            if (t != origin.type) {
mcimadamore@1194
  2072
                checkOverride(tree, t, origin, m);
mcimadamore@1194
  2073
            }
mcimadamore@1194
  2074
            for (Type t2 : types.interfaces(t)) {
mcimadamore@1194
  2075
                checkOverride(tree, t2, origin, m);
duke@0
  2076
            }
duke@0
  2077
        }
jlahoda@3135
  2078
sadayapalam@4997
  2079
        final boolean explicitOverride = m.attribute(syms.overrideType.tsym) != null;
sadayapalam@4445
  2080
        // Check if this method must override a super method due to being annotated with @Override
sadayapalam@4445
  2081
        // or by virtue of being a member of a diamond inferred anonymous class. Latter case is to
sadayapalam@4445
  2082
        // be treated "as if as they were annotated" with @Override.
sadayapalam@4997
  2083
        boolean mustOverride = explicitOverride ||
sadayapalam@4445
  2084
                (env.info.isAnonymousDiamond && !m.isConstructor() && !m.isPrivate());
sadayapalam@4445
  2085
        if (mustOverride && !isOverrider(m)) {
jlahoda@3135
  2086
            DiagnosticPosition pos = tree.pos();
jlahoda@3135
  2087
            for (JCAnnotation a : tree.getModifiers().annotations) {
jlahoda@3135
  2088
                if (a.annotationType.type.tsym == syms.overrideType.tsym) {
jlahoda@3135
  2089
                    pos = a.pos();
jlahoda@3135
  2090
                    break;
jlahoda@3135
  2091
                }
jlahoda@3135
  2092
            }
sadayapalam@4997
  2093
            log.error(pos,
sadayapalam@4997
  2094
                      explicitOverride ? Errors.MethodDoesNotOverrideSuperclass :
sadayapalam@4997
  2095
                                Errors.AnonymousDiamondMethodDoesNotOverrideSuperclass(Fragments.DiamondAnonymousMethodsImplicitlyOverride));
jlahoda@3135
  2096
        }
duke@0
  2097
    }
duke@0
  2098
mcimadamore@1194
  2099
    void checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m) {
mcimadamore@1194
  2100
        TypeSymbol c = site.tsym;
jlahoda@4103
  2101
        for (Symbol sym : c.members().getSymbolsByName(m.name)) {
jlahoda@4103
  2102
            if (m.overrides(sym, origin, types, false)) {
jlahoda@4103
  2103
                if ((sym.flags() & ABSTRACT) == 0) {
jlahoda@4103
  2104
                    checkOverride(tree, m, (MethodSymbol)sym, origin);
mcimadamore@1194
  2105
                }
mcimadamore@1194
  2106
            }
mcimadamore@1194
  2107
        }
mcimadamore@1194
  2108
    }
mcimadamore@1194
  2109
mcimadamore@5585
  2110
    private Filter<Symbol> equalsHasCodeFilter = s -> MethodSymbol.implementation_filter.accepts(s) &&
mcimadamore@5585
  2111
            (s.flags() & BAD_OVERRIDE) == 0;
vromero@2516
  2112
vromero@2529
  2113
    public void checkClassOverrideEqualsAndHashIfNeeded(DiagnosticPosition pos,
vromero@2529
  2114
            ClassSymbol someClass) {
vromero@2529
  2115
        /* At present, annotations cannot possibly have a method that is override
vromero@2529
  2116
         * equivalent with Object.equals(Object) but in any case the condition is
vromero@2529
  2117
         * fine for completeness.
vromero@2529
  2118
         */
dbalek@2721
  2119
        if (syms.objectType.isErroneous() ||
dbalek@2721
  2120
            someClass == (ClassSymbol)syms.objectType.tsym ||
vromero@2529
  2121
            someClass.isInterface() || someClass.isEnum() ||
vromero@2529
  2122
            (someClass.flags() & ANNOTATION) != 0 ||
vromero@2529
  2123
            (someClass.flags() & ABSTRACT) != 0) return;
vromero@2529
  2124
        //anonymous inner classes implementing interfaces need especial treatment
vromero@2529
  2125
        if (someClass.isAnonymous()) {
vromero@2529
  2126
            List<Type> interfaces =  types.interfaces(someClass.type);
vromero@2529
  2127
            if (interfaces != null && !interfaces.isEmpty() &&
vromero@2529
  2128
                interfaces.head.tsym == syms.comparatorType.tsym) return;
vromero@2529
  2129
        }
vromero@2529
  2130
        checkClassOverrideEqualsAndHash(pos, someClass);
vromero@2529
  2131
    }
vromero@2529
  2132
vromero@2529
  2133
    private void checkClassOverrideEqualsAndHash(DiagnosticPosition pos,
vromero@2516
  2134
            ClassSymbol someClass) {
vromero@2497
  2135
        if (lint.isEnabled(LintCategory.OVERRIDES)) {
vromero@2516
  2136
            MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType
jlahoda@4103
  2137
                    .tsym.members().findFirst(names.equals);
vromero@2516
  2138
            MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType
jlahoda@4103
  2139
                    .tsym.members().findFirst(names.hashCode);
dbalek@2548
  2140
            MethodSymbol equalsImpl = types.implementation(equalsAtObject,
dbalek@2548
  2141
                    someClass, false, equalsHasCodeFilter);
dbalek@2548
  2142
            boolean overridesEquals = equalsImpl != null && equalsImpl.owner == someClass;
dbalek@2548
  2143
            MethodSymbol hasCodeImpl = types.implementation(hashCodeAtObject,
dbalek@2548
  2144
                    someClass, false, equalsHasCodeFilter);
dbalek@2548
  2145
            boolean overridesHashCode = hasCodeImpl != null && hasCodeImpl != hashCodeAtObject;
vromero@2516
  2146
vromero@2516
  2147
            if (overridesEquals && !overridesHashCode) {
vromero@2516
  2148
                log.warning(LintCategory.OVERRIDES, pos,
vromero@2529
  2149
                        "override.equals.but.not.hashcode", someClass);
vromero@2497
  2150
            }
vromero@2497
  2151
        }
vromero@2497
  2152
    }
vromero@2497
  2153
alanb@5580
  2154
    public void checkModuleName (JCModuleDecl tree) {
alanb@5580
  2155
        Name moduleName = tree.sym.name;
alanb@5580
  2156
        Assert.checkNonNull(moduleName);
alanb@5580
  2157
        if (lint.isEnabled(LintCategory.MODULE)) {
sadayapalam@5894
  2158
            JCExpression qualId = tree.qualId;
sadayapalam@5894
  2159
            while (qualId != null) {
sadayapalam@5894
  2160
                Name componentName;
sadayapalam@5894
  2161
                DiagnosticPosition pos;
sadayapalam@5894
  2162
                switch (qualId.getTag()) {
sadayapalam@5894
  2163
                    case SELECT:
sadayapalam@5894
  2164
                        JCFieldAccess selectNode = ((JCFieldAccess) qualId);
sadayapalam@5894
  2165
                        componentName = selectNode.name;
sadayapalam@5894
  2166
                        pos = selectNode.pos();
sadayapalam@5894
  2167
                        qualId = selectNode.selected;
sadayapalam@5894
  2168
                        break;
sadayapalam@5894
  2169
                    case IDENT:
sadayapalam@5894
  2170
                        componentName = ((JCIdent) qualId).name;
sadayapalam@5894
  2171
                        pos = qualId.pos();
sadayapalam@5894
  2172
                        qualId = null;
sadayapalam@5894
  2173
                        break;
sadayapalam@5894
  2174
                    default:
sadayapalam@5894
  2175
                        throw new AssertionError("Unexpected qualified identifier: " + qualId.toString());
sadayapalam@5894
  2176
                }
sadayapalam@5894
  2177
                if (componentName != null) {
sadayapalam@5894
  2178
                    String moduleNameComponentString = componentName.toString();
sadayapalam@5894
  2179
                    int nameLength = moduleNameComponentString.length();
sadayapalam@5894
  2180
                    if (nameLength > 0 && Character.isDigit(moduleNameComponentString.charAt(nameLength - 1))) {
sadayapalam@5894
  2181
                        log.warning(Lint.LintCategory.MODULE, pos, Warnings.PoorChoiceForModuleName(componentName));
sadayapalam@5894
  2182
                    }
sadayapalam@5894
  2183
                }
alanb@5580
  2184
            }
alanb@5580
  2185
        }
alanb@5580
  2186
    }
alanb@5580
  2187
mcimadamore@1194
  2188
    private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) {
mcimadamore@1348
  2189
        ClashFilter cf = new ClashFilter(origin.type);
mcimadamore@1348
  2190
        return (cf.accepts(s1) &&
mcimadamore@1348
  2191
                cf.accepts(s2) &&
mcimadamore@1348
  2192
                types.hasSameArgs(s1.erasure(types), s2.erasure(types)));
mcimadamore@1194
  2193
    }
mcimadamore@1194
  2194
mcimadamore@1194
  2195
duke@0
  2196
    /** Check that all abstract members of given class have definitions.
duke@0
  2197
     *  @param pos          Position to be used for error reporting.
duke@0
  2198
     *  @param c            The class.
duke@0
  2199
     */
duke@0
  2200
    void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) {
jlahoda@2382
  2201
        if (c.type == null || c.type.isErroneous()) {
jlahoda@2382
  2202
            return ;
jlahoda@2382
  2203
        }
jlahoda@4369
  2204
        MethodSymbol undef = types.firstUnimplementedAbstract(c);
jlahoda@4369
  2205
        if (undef != null) {
jlahoda@4369
  2206
            MethodSymbol undef1 =
jlahoda@4369
  2207
                new MethodSymbol(undef.flags(), undef.name,
jlahoda@4369
  2208
                                 types.memberType(c.type, undef), undef.owner);
jlahoda@4369
  2209
            log.error(pos, "does.not.override.abstract",
jlahoda@4369
  2210
                      c, undef1, undef1.location());
duke@0
  2211
        }
duke@0
  2212
    }
duke@0
  2213
mcimadamore@1122
  2214
    void checkNonCyclicDecl(JCClassDecl tree) {
mcimadamore@1122
  2215
        CycleChecker cc = new CycleChecker();
mcimadamore@1122
  2216
        cc.scan(tree);
mcimadamore@1122
  2217
        if (!cc.errorFound && !cc.partialCheck) {
mcimadamore@1122
  2218
            tree.sym.flags_field |= ACYCLIC;
mcimadamore@1122
  2219
        }
mcimadamore@1122
  2220
    }
mcimadamore@1122
  2221
mcimadamore@1122
  2222
    class CycleChecker extends TreeScanner {
mcimadamore@1122
  2223
mcimadamore@1122
  2224
        List<Symbol> seenClasses = List.nil();
mcimadamore@1122
  2225
        boolean errorFound = false;
mcimadamore@1122
  2226
        boolean partialCheck = false;
mcimadamore@1122
  2227
mcimadamore@1122
  2228
        private void checkSymbol(DiagnosticPosition pos, Symbol sym) {
mcimadamore@1122
  2229
            if (sym != null && sym.kind == TYP) {
mcimadamore@1122
  2230
                Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym);
mcimadamore@1122
  2231
                if (classEnv != null) {
mcimadamore@1122
  2232
                    DiagnosticSource prevSource = log.currentSource();
mcimadamore@1122
  2233
                    try {
mcimadamore@1122
  2234
                        log.useSource(classEnv.toplevel.sourcefile);
mcimadamore@1122
  2235
                        scan(classEnv.tree);
mcimadamore@1122
  2236
                    }
mcimadamore@1122
  2237
                    finally {
mcimadamore@1122
  2238
                        log.useSource(prevSource.getFile());
mcimadamore@1122
  2239
                    }
mcimadamore@1122
  2240
                } else if (sym.kind == TYP) {
mcimadamore@5586
  2241
                    checkClass(pos, sym, List.nil());
mcimadamore@1122
  2242
                }
mcimadamore@1122
  2243
            } else {
mcimadamore@1122
  2244
                //not completed yet
mcimadamore@1122
  2245
                partialCheck = true;
mcimadamore@1122
  2246
            }
mcimadamore@1122
  2247
        }
mcimadamore@1122
  2248
mcimadamore@1122
  2249
        @Override
mcimadamore@1122
  2250
        public void visitSelect(JCFieldAccess tree) {
mcimadamore@1122
  2251
            super.visitSelect(tree);
mcimadamore@1122
  2252
            checkSymbol(tree.pos(), tree.sym);
mcimadamore@1122
  2253
        }
mcimadamore@1122
  2254
mcimadamore@1122
  2255
        @Override
mcimadamore@1122
  2256
        public void visitIdent(JCIdent tree) {
mcimadamore@1122
  2257
            checkSymbol(tree.pos(), tree.sym);
mcimadamore@1122
  2258
        }
mcimadamore@1122
  2259
mcimadamore@1122
  2260
        @Override
mcimadamore@1122
  2261
        public void visitTypeApply(JCTypeApply tree) {
mcimadamore@1122
  2262
            scan(tree.clazz);
mcimadamore@1122
  2263
        }
mcimadamore@1122
  2264
mcimadamore@1122
  2265
        @Override
mcimadamore@1122
  2266
        public void visitTypeArray(JCArrayTypeTree tree) {
mcimadamore@1122
  2267
            scan(tree.elemtype);
mcimadamore@1122
  2268
        }
mcimadamore@1122
  2269
mcimadamore@1122
  2270
        @Override
mcimadamore@1122
  2271
        public void visitClassDef(JCClassDecl tree) {
mcimadamore@1122
  2272
            List<JCTree> supertypes = List.nil();
mcimadamore@1122
  2273
            if (tree.getExtendsClause() != null) {
mcimadamore@1122
  2274
                supertypes = supertypes.prepend(tree.getExtendsClause());
mcimadamore@1122
  2275
            }
mcimadamore@1122
  2276
            if (tree.getImplementsClause() != null) {
mcimadamore@1122
  2277
                for (JCTree intf : tree.getImplementsClause()) {
mcimadamore@1122
  2278
                    supertypes = supertypes.prepend(intf);
mcimadamore@1122
  2279
                }
mcimadamore@1122
  2280
            }
mcimadamore@1122
  2281
            checkClass(tree.pos(), tree.sym, supertypes);
mcimadamore@1122
  2282
        }
mcimadamore@1122
  2283
mcimadamore@1122
  2284
        void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) {
dbalek@2716
  2285
            if (c == null || (c.flags_field & ACYCLIC) != 0)
mcimadamore@1122
  2286
                return;
mcimadamore@1122
  2287
            if (seenClasses.contains(c)) {
mcimadamore@1122
  2288
                errorFound = true;
mcimadamore@1122
  2289
                noteCyclic(pos, (ClassSymbol)c);
mcimadamore@1122
  2290
            } else if (!c.type.isErroneous()) {
mcimadamore@1122
  2291
                try {
mcimadamore@1122
  2292
                    seenClasses = seenClasses.prepend(c);
jjg@2213
  2293
                    if (c.type.hasTag(CLASS)) {
mcimadamore@1122
  2294
                        if (supertypes.nonEmpty()) {
mcimadamore@1122
  2295
                            scan(supertypes);
mcimadamore@1122
  2296
                        }
mcimadamore@1122
  2297
                        else {
mcimadamore@1122
  2298
                            ClassType ct = (ClassType)c.type;
mcimadamore@1122
  2299
                            if (ct.supertype_field == null ||
mcimadamore@1122
  2300
                                    ct.interfaces_field == null) {
mcimadamore@1122
  2301
                                //not completed yet
mcimadamore@1122
  2302
                                partialCheck = true;
mcimadamore@1122
  2303
                                return;
mcimadamore@1122
  2304
                            }
mcimadamore@1122
  2305
                            checkSymbol(pos, ct.supertype_field.tsym);
mcimadamore@1122
  2306
                            for (Type intf : ct.interfaces_field) {
mcimadamore@1122
  2307
                                checkSymbol(pos, intf.tsym);
mcimadamore@1122
  2308
                            }
mcimadamore@1122
  2309
                        }
mcimadamore@1122
  2310
                        if (c.owner.kind == TYP) {
mcimadamore@1122
  2311
                            checkSymbol(pos, c.owner);
mcimadamore@1122
  2312
                        }
mcimadamore@1122
  2313
                    }
mcimadamore@1122
  2314
                } finally {
mcimadamore@1122
  2315
                    seenClasses = seenClasses.tail;
mcimadamore@1122
  2316
                }
mcimadamore@1122
  2317
            }
mcimadamore@1122
  2318
        }
mcimadamore@1122
  2319
    }
mcimadamore@1122
  2320
duke@0
  2321
    /** Check for cyclic references. Issue an error if the
duke@0
  2322
     *  symbol of the type referred to has a LOCKED flag set.
duke@0
  2323
     *
duke@0
  2324
     *  @param pos      Position to be used for error reporting.
duke@0
  2325
     *  @param t        The type referred to.
duke@0
  2326
     */
duke@0
  2327
    void checkNonCyclic(DiagnosticPosition pos, Type t) {
duke@0
  2328
        checkNonCyclicInternal(pos, t);
duke@0
  2329
    }
duke@0
  2330
duke@0
  2331
duke@0
  2332
    void checkNonCyclic(DiagnosticPosition pos, TypeVar t) {
mcimadamore@5586
  2333
        checkNonCyclic1(pos, t, List.nil());
duke@0
  2334
    }
duke@0
  2335
mcimadamore@526
  2336
    private void checkNonCyclic1(DiagnosticPosition pos, Type t, List<TypeVar> seen) {
duke@0
  2337
        final TypeVar tv;
jjg@2213
  2338
        if  (t.hasTag(TYPEVAR) && (t.tsym.flags() & UNATTRIBUTED) != 0)
mcimadamore@222
  2339
            return;
duke@0
  2340
        if (seen.contains(t)) {
emc@3988
  2341
            tv = (TypeVar)t;
jjg@289
  2342
            tv.bound = types.createErrorType(t);
duke@0
  2343
            log.error(pos, "cyclic.inheritance", t);
jjg@2213
  2344
        } else if (t.hasTag(TYPEVAR)) {
emc@3988
  2345
            tv = (TypeVar)t;
mcimadamore@526
  2346
            seen = seen.prepend(tv);
duke@0
  2347
            for (Type b : types.getBounds(tv))
duke@0
  2348
                checkNonCyclic1(pos, b, seen);
duke@0
  2349
        }
duke@0
  2350
    }
duke@0
  2351
duke@0
  2352
    /** Check for cyclic references. Issue an error if the
duke@0
  2353
     *  symbol of the type referred to has a LOCKED flag set.
duke@0
  2354
     *
duke@0
  2355
     *  @param pos      Position to be used for error reporting.
duke@0
  2356
     *  @param t        The type referred to.
duke@0
  2357
     *  @returns        True if the check completed on all attributed classes
duke@0
  2358
     */
duke@0
  2359
    private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) {
duke@0
  2360
        boolean complete = true; // was the check complete?
duke@0
  2361
        //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG
duke@0
  2362
        Symbol c = t.tsym;
duke@0
  2363
        if ((c.flags_field & ACYCLIC) != 0) return true;
duke@0
  2364
duke@0
  2365
        if ((c.flags_field & LOCKED) != 0) {
duke@0
  2366
            noteCyclic(pos, (ClassSymbol)c);
duke@0
  2367
        } else if (!c.type.isErroneous()) {
duke@0
  2368
            try {
duke@0
  2369
                c.flags_field |= LOCKED;
jjg@2213
  2370
                if (c.type.hasTag(CLASS)) {
duke@0
  2371
                    ClassType clazz = (ClassType)c.type;
duke@0
  2372
                    if (clazz.interfaces_field != null)
duke@0
  2373
                        for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail)
duke@0
  2374
                            complete &= checkNonCyclicInternal(pos, l.head);
duke@0
  2375
                    if (clazz.supertype_field != null) {
duke@0
  2376
                        Type st = clazz.supertype_field;
jjg@2213
  2377
                        if (st != null && st.hasTag(CLASS))
duke@0
  2378
                            complete &= checkNonCyclicInternal(pos, st);
duke@0
  2379
                    }
duke@0
  2380
                    if (c.owner.kind == TYP)
duke@0
  2381
                        complete &= checkNonCyclicInternal(pos, c.owner.type);
duke@0
  2382
                }
duke@0
  2383
            } finally {
duke@0
  2384
                c.flags_field &= ~LOCKED;
duke@0
  2385
            }
duke@0
  2386
        }
duke@0
  2387
        if (complete)
alundblad@4474
  2388
            complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.isCompleted();
duke@0
  2389
        if (complete) c.flags_field |= ACYCLIC;
duke@0
  2390
        return complete;
duke@0
  2391
    }
duke@0
  2392
duke@0
  2393
    /** Note that we found an inheritance cycle. */
duke@0
  2394
    private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) {
duke@0
  2395
        log.error(pos, "cyclic.inheritance", c);
duke@0
  2396
        for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail)
jjg@289
  2397
            l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType);
duke@0
  2398
        Type st = types.supertype(c.type);
jjg@2213
  2399
        if (st.hasTag(CLASS))
jjg@289
  2400
            ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType);
jjg@289
  2401
        c.type = types.createErrorType(c, c.type);
duke@0
  2402
        c.flags_field |= ACYCLIC;
duke@0
  2403
    }
duke@0
  2404
duke@0
  2405
    /** Check that all methods which implement some
duke@0
  2406
     *  method conform to the method they implement.
duke@0
  2407
     *  @param tree         The class definition whose members are checked.
duke@0
  2408
     */
duke@0
  2409
    void checkImplementations(JCClassDecl tree) {
mcimadamore@2260
  2410
        checkImplementations(tree, tree.sym, tree.sym);
duke@0
  2411
    }
jjg@2372
  2412
    //where
duke@0
  2413
        /** Check that all methods which implement some
duke@0
  2414
         *  method in `ic' conform to the method they implement.
duke@0
  2415
         */
mcimadamore@2260
  2416
        void checkImplementations(JCTree tree, ClassSymbol origin, ClassSymbol ic) {
duke@0
  2417
            for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) {
jlahoda@33
  2418
                ElementKind kind = l.head.tsym.getKind();
jlahoda@33
  2419
jlahoda@33
  2420
                if (!kind.isClass() && !kind.isInterface()) {
jlahoda@33
  2421
                    //not a class: an error should have already been reported, ignore.
jlahoda@33
  2422
                    continue;
jlahoda@33
  2423
                }
jlahoda@33
  2424
duke@0
  2425
                ClassSymbol lc = (ClassSymbol)l.head.tsym;
ntoda@4105
  2426
                if ((lc.flags() & ABSTRACT) != 0) {
jlahoda@4103
  2427
                    for (Symbol sym : lc.members().getSymbols(NON_RECURSIVE)) {
jlahoda@4103
  2428
                        if (sym.kind == MTH &&
jlahoda@4103
  2429
                            (sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) {
jlahoda@4103
  2430
                            MethodSymbol absmeth = (MethodSymbol)sym;
duke@0
  2431
                            MethodSymbol implmeth = absmeth.implementation(origin, types, false);
duke@0
  2432
                            if (implmeth != null && implmeth != absmeth &&
duke@0
  2433
                                (implmeth.owner.flags() & INTERFACE) ==
duke@0
  2434
                                (origin.flags() & INTERFACE)) {
duke@0
  2435
                                // don't check if implmeth is in a class, yet
duke@0
  2436
                                // origin is an interface. This case arises only
duke@0
  2437
                                // if implmeth is declared in Object. The reason is
duke@0
  2438
                                // that interfaces really don't inherit from
duke@0
  2439
                                // Object it's just that the compiler represents
duke@0
  2440
                                // things that way.
duke@0
  2441
                                checkOverride(tree, implmeth, absmeth, origin);
duke@0
  2442
                            }
duke@0
  2443
                        }
duke@0
  2444
                    }
duke@0
  2445
                }
duke@0
  2446
            }
duke@0
  2447
        }
duke@0
  2448
duke@0
  2449
    /** Check that all abstract methods implemented by a class are
duke@0
  2450
     *  mutually compatible.
duke@0
  2451
     *  @param pos          Position to be used for error reporting.
duke@0
  2452
     *  @param c            The class whose interfaces are checked.
duke@0
  2453
     */
duke@0
  2454
    void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
duke@0
  2455
        List<Type> supertypes = types.interfaces(c);
duke@0
  2456
        Type supertype = types.supertype(c);
jjg@2213
  2457
        if (supertype.hasTag(CLASS) &&
duke@0
  2458
            (supertype.tsym.flags() & ABSTRACT) != 0)
duke@0
  2459
            supertypes = supertypes.prepend(supertype);
duke@0
  2460
        for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) {
ntoda@4105
  2461
            if (!l.head.getTypeArguments().isEmpty() &&
duke@0
  2462
                !checkCompatibleAbstracts(pos, l.head, l.head, c))
duke@0
  2463
                return;
duke@0
  2464
            for (List<Type> m = supertypes; m != l; m = m.tail)
duke@0
  2465
                if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
duke@0
  2466
                    return;
duke@0
  2467
        }
duke@0
  2468
        checkCompatibleConcretes(pos, c);
duke@0
  2469
    }
duke@0
  2470
mcimadamore@649
  2471
    void checkConflicts(DiagnosticPosition pos, Symbol sym, TypeSymbol c) {
jlahoda@730
  2472
        Type previous = null;
jlahoda@730
  2473
        for (Type ct = c.type; ct != Type.noType && ct != previous; previous = ct, ct = types.supertype(ct)) {
jlahoda@4103
  2474
            for (Symbol sym2 : ct.tsym.members().getSymbolsByName(sym.name, NON_RECURSIVE)) {
mcimadamore@649
  2475
                // VM allows methods and variables with differing types
jlahoda@4103
  2476
                if (sym.kind == sym2.kind &&
jlahoda@4103
  2477
                    types.isSameType(types.erasure(sym.type), types.erasure(sym2.type)) &&
jlahoda@4103
  2478
                    sym != sym2 &&
jlahoda@4103
  2479
                    (sym.flags() & Flags.SYNTHETIC) != (sym2.flags() & Flags.SYNTHETIC) &&
jlahoda@4103
  2480
                    (sym.flags() & BRIDGE) == 0 && (sym2.flags() & BRIDGE) == 0) {
jlahoda@4103
  2481
                    syntheticError(pos, (sym2.flags() & SYNTHETIC) == 0 ? sym2 : sym);
mcimadamore@649
  2482
                    return;
mcimadamore@649
  2483
                }
mcimadamore@649
  2484
            }
mcimadamore@649
  2485
        }
mcimadamore@649
  2486
    }
mcimadamore@649
  2487
mcimadamore@1227
  2488
    /** Check that all non-override equivalent methods accessible from 'site'
mcimadamore@1227
  2489
     *  are mutually compatible (JLS 8.4.8/9.4.1).
mcimadamore@1227
  2490
     *
mcimadamore@1227
  2491
     *  @param pos  Position to be used for error reporting.
mcimadamore@1227
  2492
     *  @param site The class whose methods are checked.
mcimadamore@1227
  2493
     *  @param sym  The method symbol to be checked.
mcimadamore@1227
  2494
     */
mcimadamore@1348
  2495
    void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
tzezula@3788
  2496
        if (site == null || site.isErroneous() || sym.type.isErroneous())
dbalek@1451
  2497
            return;
mcimadamore@1348
  2498
         ClashFilter cf = new ClashFilter(site);
mcimadamore@2043
  2499
        //for each method m1 that is overridden (directly or indirectly)
mcimadamore@2043
  2500
        //by method 'sym' in 'site'...
vromero@3142
  2501
vromero@3142
  2502
        List<MethodSymbol> potentiallyAmbiguousList = List.nil();
vromero@3142
  2503
        boolean overridesAny = false;
jlahoda@4103
  2504
        for (Symbol m1 : types.membersClosure(site, false).getSymbolsByName(sym.name, cf)) {
vromero@3142
  2505
            if (!sym.overrides(m1, site.tsym, types, false)) {
vromero@3142
  2506
                if (m1 == sym) {
vromero@3142
  2507
                    continue;
vromero@3142
  2508
                }
vromero@3142
  2509
vromero@3142
  2510
                if (!overridesAny) {
vromero@3142
  2511
                    potentiallyAmbiguousList = potentiallyAmbiguousList.prepend((MethodSymbol)m1);
vromero@3142
  2512
                }
vromero@3142
  2513
                continue;
vromero@3142
  2514
            }
vromero@3142
  2515
vromero@3142
  2516
            if (m1 != sym) {
vromero@3142
  2517
                overridesAny = true;
vromero@3142
  2518
                potentiallyAmbiguousList = List.nil();
vromero@3142
  2519
            }
vromero@3142
  2520
vromero@3142
  2521
            //...check each method m2 that is a member of 'site'
jlahoda@4103
  2522
            for (Symbol m2 : types.membersClosure(site, false).getSymbolsByName(sym.name, cf)) {
mcimadamore@2043
  2523
                if (m2 == m1) continue;
mcimadamore@1348
  2524
                //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
mcimadamore@1348
  2525
                //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
mcimadamore@2234
  2526
                if (!types.isSubSignature(sym.type, types.memberType(site, m2), allowStrictMethodClashCheck) &&
mcimadamore@2043
  2527
                        types.hasSameArgs(m2.erasure(types), m1.erasure(types))) {
mcimadamore@1348
  2528
                    sym.flags_field |= CLASH;
mcimadamore@2043
  2529
                    String key = m1 == sym ?
mcimadamore@1348
  2530
                            "name.clash.same.erasure.no.override" :
mcimadamore@1348
  2531
                            "name.clash.same.erasure.no.override.1";
mcimadamore@1348
  2532
                    log.error(pos,
mcimadamore@1348
  2533
                            key,
mcimadamore@1348
  2534
                            sym, sym.location(),
mcimadamore@2043
  2535
                            m2, m2.location(),
mcimadamore@2043
  2536
                            m1, m1.location());
mcimadamore@1348
  2537
                    return;
mcimadamore@1348
  2538
                }
mcimadamore@1227
  2539
            }
mcimadamore@1227
  2540
        }
vromero@3142
  2541
vromero@3142
  2542
        if (!overridesAny) {
vromero@3142
  2543
            for (MethodSymbol m: potentiallyAmbiguousList) {
vromero@3142
  2544
                checkPotentiallyAmbiguousOverloads(pos, site, sym, m);
vromero@3142
  2545
            }
vromero@3142
  2546
        }
mcimadamore@1227
  2547
    }
mcimadamore@1227
  2548
mcimadamore@1348
  2549
    /** Check that all static methods accessible from 'site' are
mcimadamore@1348
  2550
     *  mutually compatible (JLS 8.4.8).
mcimadamore@1348
  2551
     *
mcimadamore@1348
  2552
     *  @param pos  Position to be used for error reporting.
mcimadamore@1348
  2553
     *  @param site The class whose methods are checked.
mcimadamore@1348
  2554
     *  @param sym  The method symbol to be checked.
mcimadamore@1227
  2555
     */
mcimadamore@1348
  2556
    void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
dbalek@3782
  2557
        if (site == null || site.isErroneous())
dbalek@1451
  2558
            return;
mcimadamore@1227
  2559
        ClashFilter cf = new ClashFilter(site);
mcimadamore@1348
  2560
        //for each method m1 that is a member of 'site'...
jlahoda@4103
  2561
        for (Symbol s : types.membersClosure(site, true).getSymbolsByName(sym.name, cf)) {
mcimadamore@1348
  2562
            //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
mcimadamore@1348
  2563
            //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
vromero@3016
  2564
            if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) {
vromero@3016
  2565
                if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
vromero@3016
  2566
                    log.error(pos,
vromero@3016
  2567
                            "name.clash.same.erasure.no.hide",
vromero@3016
  2568
                            sym, sym.location(),
vromero@3016
  2569
                            s, s.location());
vromero@3016
  2570
                    return;
vromero@3016
  2571
                } else {
vromero@3016
  2572
                    checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)s);
vromero@3016
  2573
                }
vromero@3016
  2574
            }
mcimadamore@1348
  2575
         }
mcimadamore@1348
  2576
     }
mcimadamore@1227
  2577
mcimadamore@1348
  2578
     //where
mcimadamore@1348
  2579
     private class ClashFilter implements Filter<Symbol> {
mcimadamore@1227
  2580
mcimadamore@1348
  2581
         Type site;
mcimadamore@1227
  2582
mcimadamore@1348
  2583
         ClashFilter(Type site) {
mcimadamore@1348
  2584
             this.site = site;
mcimadamore@1348
  2585
         }
mcimadamore@1348
  2586
mcimadamore@1348
  2587
         boolean shouldSkip(Symbol s) {
mcimadamore@1348
  2588
             return (s.flags() & CLASH) != 0 &&
mcimadamore@1348
  2589
                s.owner == site.tsym;
mcimadamore@1348
  2590
         }
mcimadamore@1348
  2591
mcimadamore@1348
  2592
         public boolean accepts(Symbol s) {
mcimadamore@1348
  2593
             return s.kind == MTH &&
mcimadamore@1348
  2594
                     (s.flags() & SYNTHETIC) == 0 &&
mcimadamore@1348
  2595
                     !shouldSkip(s) &&
mcimadamore@1348
  2596
                     s.isInheritedIn(site.tsym, types) &&
mcimadamore@1348
  2597
                     !s.isConstructor();
mcimadamore@1348
  2598
         }
mcimadamore@1348
  2599
     }
mcimadamore@1227
  2600
mcimadamore@2234
  2601
    void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) {
dbalek@2332
  2602
        if (site == null || site.isErroneous()) {
dbalek@2332
  2603
            return;
dbalek@2332
  2604
        }
mcimadamore@2234
  2605
        DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site);
jlahoda@4103
  2606
        for (Symbol m : types.membersClosure(site, false).getSymbols(dcf)) {
mcimadamore@2234
  2607
            Assert.check(m.kind == MTH);
mcimadamore@2234
  2608
            List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m);
mcimadamore@2234
  2609
            if (prov.size() > 1) {
alundblad@3063
  2610
                ListBuffer<Symbol> abstracts = new ListBuffer<>();
alundblad@3063
  2611
                ListBuffer<Symbol> defaults = new ListBuffer<>();
mcimadamore@2234
  2612
                for (MethodSymbol provSym : prov) {
mcimadamore@2234
  2613
                    if ((provSym.flags() & DEFAULT) != 0) {
mcimadamore@2234
  2614
                        defaults = defaults.append(provSym);
mcimadamore@2234
  2615
                    } else if ((provSym.flags() & ABSTRACT) != 0) {
mcimadamore@2234
  2616
                        abstracts = abstracts.append(provSym);
mcimadamore@2234
  2617
                    }
mcimadamore@2234
  2618
                    if (defaults.nonEmpty() && defaults.size() + abstracts.size() >= 2) {
mcimadamore@2234
  2619
                        //strong semantics - issue an error if two sibling interfaces
mcimadamore@2234
  2620
                        //have two override-equivalent defaults - or if one is abstract
mcimadamore@2234
  2621
                        //and the other is default
mcimadamore@2234
  2622
                        String errKey;
mcimadamore@2234
  2623
                        Symbol s1 = defaults.first();
mcimadamore@2234
  2624
                        Symbol s2;
mcimadamore@2234
  2625
                        if (defaults.size() > 1) {
mcimadamore@2234
  2626
                            errKey = "types.incompatible.unrelated.defaults";
mcimadamore@2234
  2627
                            s2 = defaults.toList().tail.head;
mcimadamore@2234
  2628
                        } else {
mcimadamore@2234
  2629
                            errKey = "types.incompatible.abstract.default";
mcimadamore@2234
  2630
                            s2 = abstracts.first();
mcimadamore@2234
  2631
                        }
mcimadamore@2234
  2632
                        log.error(pos, errKey,
mcimadamore@2234
  2633
                                Kinds.kindName(site.tsym), site,
mcimadamore@2234
  2634
                                m.name, types.memberType(site, m).getParameterTypes(),
mcimadamore@2234
  2635
                                s1.location(), s2.location());
mcimadamore@2234
  2636
                        break;
mcimadamore@2234
  2637
                    }
mcimadamore@2234
  2638
                }
mcimadamore@2234
  2639
            }
mcimadamore@2234
  2640
        }
mcimadamore@2234
  2641
    }
mcimadamore@2234
  2642
mcimadamore@2234
  2643
    //where
mcimadamore@2234
  2644
     private class DefaultMethodClashFilter implements Filter<Symbol> {
mcimadamore@2234
  2645
mcimadamore@2234
  2646
         Type site;
mcimadamore@2234
  2647
mcimadamore@2234
  2648
         DefaultMethodClashFilter(Type site) {
mcimadamore@2234
  2649
             this.site = site;
mcimadamore@2234
  2650
         }
mcimadamore@2234
  2651
mcimadamore@2234
  2652
         public boolean accepts(Symbol s) {
mcimadamore@2234
  2653
             return s.kind == MTH &&
mcimadamore@2234
  2654
                     (s.flags() & DEFAULT) != 0 &&
mcimadamore@2234
  2655
                     s.isInheritedIn(site.tsym, types) &&
mcimadamore@2234
  2656
                     !s.isConstructor();
mcimadamore@2234
  2657
         }
mcimadamore@2234
  2658
     }
mcimadamore@2234
  2659
vromero@3016
  2660
    /**
vromero@3016
  2661
      * Report warnings for potentially ambiguous method declarations. Two declarations
vromero@3016
  2662
      * are potentially ambiguous if they feature two unrelated functional interface
vromero@3016
  2663
      * in same argument position (in which case, a call site passing an implicit
vromero@3016
  2664
      * lambda would be ambiguous).
vromero@3016
  2665
      */
vromero@3016
  2666
    void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site,
vromero@3016
  2667
            MethodSymbol msym1, MethodSymbol msym2) {
vromero@3016
  2668
        if (msym1 != msym2 &&
vromero@3016
  2669
                allowDefaultMethods &&
vromero@3016
  2670
                lint.isEnabled(LintCategory.OVERLOADS) &&
vromero@3016
  2671
                (msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 &&
vromero@3016
  2672
                (msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) {
vromero@3016
  2673
            Type mt1 = types.memberType(site, msym1);
vromero@3016
  2674
            Type mt2 = types.memberType(site, msym2);
vromero@3016
  2675
            //if both generic methods, adjust type variables
vromero@3016
  2676
            if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) &&
vromero@3016
  2677
                    types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) {
vromero@3016
  2678
                mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars);
vromero@3016
  2679
            }
vromero@3016
  2680
            //expand varargs methods if needed
vromero@3016
  2681
            int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length());
vromero@3016
  2682
            List<Type> args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true);
vromero@3016
  2683
            List<Type> args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true);
vromero@3016
  2684
            //if arities don't match, exit
vromero@3016
  2685
            if (args1.length() != args2.length()) return;
vromero@3016
  2686
            boolean potentiallyAmbiguous = false;
vromero@3016
  2687
            while (args1.nonEmpty() && args2.nonEmpty()) {
vromero@3016
  2688
                Type s = args1.head;
vromero@3016
  2689
                Type t = args2.head;
vromero@3016
  2690
                if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) {
vromero@3016
  2691
                    if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) &&
vromero@3016
  2692
                            types.findDescriptorType(s).getParameterTypes().length() > 0 &&
vromero@3016
  2693
                            types.findDescriptorType(s).getParameterTypes().length() ==
vromero@3016
  2694
                            types.findDescriptorType(t).getParameterTypes().length()) {
vromero@3016
  2695
                        potentiallyAmbiguous = true;
vromero@3016
  2696
                    } else {
vromero@3016
  2697
                        break;
vromero@3016
  2698
                    }
vromero@3016
  2699
                }
vromero@3016
  2700
                args1 = args1.tail;
vromero@3016
  2701
                args2 = args2.tail;
vromero@3016
  2702
            }
vromero@3016
  2703
            if (potentiallyAmbiguous) {
vromero@3016
  2704
                //we found two incompatible functional interfaces with same arity
vromero@3016
  2705
                //this means a call site passing an implicit lambda would be ambigiuous
vromero@3016
  2706
                msym1.flags_field |= POTENTIALLY_AMBIGUOUS;
vromero@3016
  2707
                msym2.flags_field |= POTENTIALLY_AMBIGUOUS;
vromero@3016
  2708
                log.warning(LintCategory.OVERLOADS, pos, "potentially.ambiguous.overload",
vromero@3016
  2709
                            msym1, msym1.location(),
vromero@3016
  2710
                            msym2, msym2.location());
vromero@3016
  2711
                return;
vromero@3016
  2712
            }
vromero@3016
  2713
        }
vromero@3016
  2714
    }
vromero@3016
  2715
vromero@5460
  2716
    void checkAccessFromSerializableElement(final JCTree tree, boolean isLambda) {
vromero@5460
  2717
        if (warnOnAnyAccessToMembers ||
vromero@5460
  2718
            (lint.isEnabled(LintCategory.SERIAL) &&
vromero@5460
  2719
            !lint.isSuppressed(LintCategory.SERIAL) &&
vromero@5460
  2720
            isLambda)) {
vromero@3964
  2721
            Symbol sym = TreeInfo.symbol(tree);
emc@4248
  2722
            if (!sym.kind.matches(KindSelector.VAL_MTH)) {
vromero@3964
  2723
                return;
vromero@3964
  2724
            }
vromero@3964
  2725
vromero@3964
  2726
            if (sym.kind == VAR) {
vromero@3964
  2727
                if ((sym.flags() & PARAMETER) != 0 ||
vromero@3964
  2728
                    sym.isLocal() ||
vromero@3964
  2729
                    sym.name == names._this ||
vromero@3964
  2730
                    sym.name == names._super) {
vromero@3964
  2731
                    return;
vromero@3964
  2732
                }
vromero@3964
  2733
            }
vromero@3964
  2734
vromero@3964
  2735
            if (!types.isSubtype(sym.owner.type, syms.serializableType) &&
vromero@5460
  2736
                isEffectivelyNonPublic(sym)) {
vromero@5460
  2737
                if (isLambda) {
vromero@5460
  2738
                    if (belongsToRestrictedPackage(sym)) {
vromero@5460
  2739
                        log.warning(LintCategory.SERIAL, tree.pos(),
vromero@5460
  2740
                            "access.to.member.from.serializable.lambda", sym);
vromero@5460
  2741
                    }
vromero@5460
  2742
                } else {
vromero@5460
  2743
                    log.warning(tree.pos(),
vromero@5460
  2744
                        "access.to.member.from.serializable.element", sym);
vromero@5460
  2745
                }
vromero@3964
  2746
            }
vromero@3964
  2747
        }
vromero@3964
  2748
    }
vromero@3964
  2749
vromero@3964
  2750
    private boolean isEffectivelyNonPublic(Symbol sym) {
vromero@3964
  2751
        if (sym.packge() == syms.rootPackage) {
vromero@3964
  2752
            return false;
vromero@3964
  2753
        }
vromero@3964
  2754
emc@4248
  2755
        while (sym.kind != PCK) {
vromero@3964
  2756
            if ((sym.flags() & PUBLIC) == 0) {
vromero@3964
  2757
                return true;
vromero@3964
  2758
            }
vromero@3964
  2759
            sym = sym.owner;
vromero@3964
  2760
        }
vromero@3964
  2761
        return false;
vromero@3964
  2762
    }
vromero@3964
  2763
vromero@5460
  2764
    private boolean belongsToRestrictedPackage(Symbol sym) {
vromero@5460
  2765
        String fullName = sym.packge().fullname.toString();
vromero@5460
  2766
        return fullName.startsWith("java.") ||
vromero@5460
  2767
                fullName.startsWith("javax.") ||
vromero@5460
  2768
                fullName.startsWith("sun.") ||
vromero@5460
  2769
                fullName.contains(".internal.");
vromero@5460
  2770
    }
vromero@5460
  2771
mcimadamore@649
  2772
    /** Report a conflict between a user symbol and a synthetic symbol.
mcimadamore@649
  2773
     */
mcimadamore@649
  2774
    private void syntheticError(DiagnosticPosition pos, Symbol sym) {
mcimadamore@649
  2775
        if (!sym.type.isErroneous()) {
vromero@4979
  2776
            log.error(pos, "synthetic.name.conflict", sym, sym.location());
mcimadamore@649
  2777
        }
mcimadamore@649
  2778
    }
mcimadamore@649
  2779
duke@0
  2780
    /** Check that class c does not implement directly or indirectly
duke@0
  2781
     *  the same parameterized interface with two different argument lists.
duke@0
  2782
     *  @param pos          Position to be used for error reporting.
duke@0
  2783
     *  @param type         The type whose interfaces are checked.
duke@0
  2784
     */
duke@0
  2785
    void checkClassBounds(DiagnosticPosition pos, Type type) {
vromero@3810
  2786
        checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type);
duke@0
  2787
    }
duke@0
  2788
//where
duke@0
  2789
        /** Enter all interfaces of type `type' into the hash table `seensofar'
duke@0
  2790
         *  with their class symbol as key and their type as value. Make
duke@0
  2791
         *  sure no class is entered with two different types.
duke@0
  2792
         */
duke@0
  2793
        void checkClassBounds(DiagnosticPosition pos,
duke@0
  2794
                              Map<TypeSymbol,Type> seensofar,
duke@0
  2795
                              Type type) {
duke@0
  2796
            if (type.isErroneous()) return;
duke@0
  2797
            for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) {
duke@0
  2798
                Type it = l.head;
duke@0
  2799
                Type oldit = seensofar.put(it.tsym, it);
duke@0
  2800
                if (oldit != null) {
duke@0
  2801
                    List<Type> oldparams = oldit.allparams();
duke@0
  2802
                    List<Type> newparams = it.allparams();
duke@0
  2803
                    if (!types.containsTypeEquivalent(oldparams, newparams))
duke@0
  2804
                        log.error(pos, "cant.inherit.diff.arg",
duke@0
  2805
                                  it.tsym, Type.toString(oldparams),
duke@0
  2806
                                  Type.toString(newparams));
duke@0
  2807
                }
duke@0
  2808
                checkClassBounds(pos, seensofar, it);
duke@0
  2809
            }
duke@0
  2810
            Type st = types.supertype(type);
dlsmith@4056
  2811
            if (st != Type.noType) checkClassBounds(pos, seensofar, st);
duke@0
  2812
        }
duke@0
  2813
duke@0
  2814
    /** Enter interface into into set.
duke@0
  2815
     *  If it existed already, issue a "repeated interface" error.
duke@0
  2816
     */
duke@0
  2817
    void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) {
duke@0
  2818
        if (its.contains(it))
duke@0
  2819
            log.error(pos, "repeated.interface");
duke@0
  2820
        else {
duke@0
  2821
            its.add(it);
duke@0
  2822
        }
duke@0
  2823
    }
duke@0
  2824
duke@0
  2825
/* *************************************************************************
duke@0
  2826
 * Check annotations
duke@0
  2827
 **************************************************************************/
duke@0
  2828
mcimadamore@1029
  2829
    /**
mcimadamore@1038
  2830
     * Recursively validate annotations values
mcimadamore@1029
  2831
     */
mcimadamore@1038
  2832
    void validateAnnotationTree(JCTree tree) {
mcimadamore@1038
  2833
        class AnnotationValidator extends TreeScanner {
mcimadamore@1029
  2834
            @Override
mcimadamore@1029
  2835
            public void visitAnnotation(JCAnnotation tree) {
jlahoda@1533
  2836
                if (tree.type != null && !tree.type.isErroneous()) {
jjg@1531
  2837
                    super.visitAnnotation(tree);
jjg@1531
  2838
                    validateAnnotation(tree);
jjg@1531
  2839
                }
mcimadamore@1029
  2840
            }
mcimadamore@1029
  2841
        }
mcimadamore@1038
  2842
        tree.accept(new AnnotationValidator());
mcimadamore@1029
  2843
    }
mcimadamore@1029
  2844
jjg@2167
  2845
    /**
jjg@2167
  2846
     *  {@literal
jjg@2167
  2847
     *  Annotation types are restricted to primitives, String, an
duke@0
  2848
     *  enum, an annotation, Class, Class<?>, Class<? extends
duke@0
  2849
     *  Anything>, arrays of the preceding.
jjg@2167
  2850
     *  }
duke@0
  2851
     */
duke@0
  2852
    void validateAnnotationType(JCTree restype) {
duke@0
  2853
        // restype may be null if an error occurred, so don't bother validating it
duke@0
  2854
        if (restype != null) {
duke@0
  2855
            validateAnnotationType(restype.pos(), restype.type);
duke@0
  2856
        }
duke@0
  2857
    }
duke@0
  2858
duke@0
  2859
    void validateAnnotationType(DiagnosticPosition pos, Type type) {
duke@0
  2860
        if (type.isPrimitive()) return;
duke@0
  2861
        if (types.isSameType(type, syms.stringType)) return;
duke@0
  2862
        if ((type.tsym.flags() & Flags.ENUM) != 0) return;
duke@0
  2863
        if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return;
dlsmith@3976
  2864
        if (types.cvarLowerBound(type).tsym == syms.classType.tsym) return;
duke@0
  2865
        if (types.isArray(type) && !types.isArray(types.elemtype(type))) {
duke@0
  2866
            validateAnnotationType(pos, types.elemtype(type));
duke@0
  2867
            return;
duke@0
  2868
        }
duke@0
  2869
        log.error(pos, "invalid.annotation.member.type");
duke@0
  2870
    }
duke@0
  2871
duke@0
  2872
    /**
duke@0
  2873
     * "It is also a compile-time error if any method declared in an
duke@0
  2874
     * annotation type has a signature that is override-equivalent to
duke@0
  2875
     * that of any public or protected method declared in class Object
duke@0
  2876
     * or in the interface annotation.Annotation."
duke@0
  2877
     *
jjh@1465
  2878
     * @jls 9.6 Annotation Types
duke@0
  2879
     */
duke@0
  2880
    void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) {
jjg@2213
  2881
        for (Type sup = syms.annotationType; sup.hasTag(CLASS); sup = types.supertype(sup)) {
duke@0
  2882
            Scope s = sup.tsym.members();
jlahoda@4103
  2883
            for (Symbol sym : s.getSymbolsByName(m.name)) {
jlahoda@4103
  2884
                if (sym.kind == MTH &&
jlahoda@4103
  2885
                    (sym.flags() & (PUBLIC | PROTECTED)) != 0 &&
jlahoda@4103
  2886
                    types.overrideEquivalent(m.type, sym.type))
jlahoda@4103
  2887
                    log.error(pos, "intf.annotation.member.clash", sym, sup);
duke@0
  2888
            }
duke@0
  2889
        }
duke@0
  2890
    }
duke@0
  2891
duke@0
  2892
    /** Check the annotations of a symbol.
duke@0
  2893
     */
duke@0
  2894
    public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) {
duke@0
  2895
        for (JCAnnotation a : annotations)
duke@0
  2896
            validateAnnotation(a, s);
duke@0
  2897
    }
duke@0
  2898
jjg@2372
  2899
    /** Check the type annotations.
jjg@2372
  2900
     */
jjg@2372
  2901
    public void validateTypeAnnotations(List<JCAnnotation> annotations, boolean isTypeParameter) {
jjg@2372
  2902
        for (JCAnnotation a : annotations)
jjg@2372
  2903
            validateTypeAnnotation(a, isTypeParameter);
jjg@2372
  2904
    }
jjg@2372
  2905
duke@0
  2906
    /** Check an annotation of a symbol.
duke@0
  2907
     */
jfranck@2156
  2908
    private void validateAnnotation(JCAnnotation a, Symbol s) {
mcimadamore@1038
  2909
        validateAnnotationTree(a);
duke@0
  2910
sadayapalam@5685
  2911
        if (a.type.tsym.isAnnotationType() && !annotationApplicable(a, s))
duke@0
  2912
            log.error(a.pos(), "annotation.type.not.applicable");
duke@0
  2913
mcimadamore@2344
  2914
        if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) {
mcimadamore@2344
  2915
            if (s.kind != TYP) {
mcimadamore@2344
  2916
                log.error(a.pos(), "bad.functional.intf.anno");
jlahoda@3135
  2917
            } else if (!s.isInterface() || (s.flags() & ANNOTATION) != 0) {
jlahoda@3135
  2918
                log.error(a.pos(), "bad.functional.intf.anno.1", diags.fragment("not.a.functional.intf", s));
mcimadamore@2344
  2919
            }
mcimadamore@2344
  2920
        }
duke@0
  2921
    }
duke@0
  2922
jjg@2372
  2923
    public void validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter) {
jlahoda@4143
  2924
        Assert.checkNonNull(a.type);
jjg@2372
  2925
        validateAnnotationTree(a);
jjg@2372
  2926
jjg@3158
  2927
        if (a.hasTag(TYPE_ANNOTATION) &&
jjg@3158
  2928
                !a.annotationType.type.isErroneous() &&
jjg@3158
  2929
                !isTypeAnnotation(a, isTypeParameter)) {
alundblad@4459
  2930
            log.error(a.pos(), Errors.AnnotationTypeNotApplicableToType(a.type));
jjg@3158
  2931
        }
jjg@2372
  2932
    }
jjg@2372
  2933
jfranck@2156
  2934
    /**
jjg@2339
  2935
     * Validate the proposed container 'repeatable' on the
jfranck@2156
  2936
     * annotation type symbol 's'. Report errors at position
jfranck@2156
  2937
     * 'pos'.
jfranck@2156
  2938
     *
jjg@2339
  2939
     * @param s The (annotation)type declaration annotated with a @Repeatable
jjg@2339
  2940
     * @param repeatable the @Repeatable on 's'
jfranck@2156
  2941
     * @param pos where to report errors
jfranck@2156
  2942
     */
jjg@2339
  2943
    public void validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos) {
jjg@2339
  2944
        Assert.check(types.isSameType(repeatable.type, syms.repeatableType));
jfranck@2156
  2945
jfranck@2156
  2946
        Type t = null;
jjg@2339
  2947
        List<Pair<MethodSymbol,Attribute>> l = repeatable.values;
jfranck@2156
  2948
        if (!l.isEmpty()) {
jfranck@2156
  2949
            Assert.check(l.head.fst.name == names.value);
jfranck@2156
  2950
            t = ((Attribute.Class)l.head.snd).getValue();
jfranck@2156
  2951
        }
jfranck@2156
  2952
jfranck@2156
  2953
        if (t == null) {
jjg@2339
  2954
            // errors should already have been reported during Annotate
jfranck@2156
  2955
            return;
jfranck@2156
  2956
        }
jfranck@2156
  2957
jjg@2339
  2958
        validateValue(t.tsym, s, pos);
jfranck@2156
  2959
        validateRetention(t.tsym, s, pos);
jfranck@2156
  2960
        validateDocumented(t.tsym, s, pos);
jfranck@2156
  2961
        validateInherited(t.tsym, s, pos);
jfranck@2156
  2962
        validateTarget(t.tsym, s, pos);
jfranck@3839
  2963
        validateDefault(t.tsym, pos);
jfranck@2156
  2964
    }
jfranck@2156
  2965
jjg@2339
  2966
    private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
jlahoda@4103
  2967
        Symbol sym = container.members().findFirst(names.value);
jlahoda@4103
  2968
        if (sym != null && sym.kind == MTH) {
jlahoda@4103
  2969
            MethodSymbol m = (MethodSymbol) sym;
jjg@2339
  2970
            Type ret = m.getReturnType();
jjg@2339
  2971
            if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) {
jjg@2339
  2972
                log.error(pos, "invalid.repeatable.annotation.value.return",
jjg@2339
  2973
                        container, ret, types.makeArrayType(contained.type));
jjg@2339
  2974
            }
jjg@2339
  2975
        } else {
jjg@2339
  2976
            log.error(pos, "invalid.repeatable.annotation.no.value", container);
jfranck@2156
  2977
        }
jfranck@2156
  2978
    }
jfranck@2156
  2979
jjg@4454
  2980
    private void validateRetention(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
jfranck@2156
  2981
        Attribute.RetentionPolicy containerRetention = types.getRetention(container);
jfranck@2156
  2982
        Attribute.RetentionPolicy containedRetention = types.getRetention(contained);
jfranck@2156
  2983
jfranck@2156
  2984
        boolean error = false;
jfranck@2156
  2985
        switch (containedRetention) {
jfranck@2156
  2986
        case RUNTIME:
jfranck@2156
  2987
            if (containerRetention != Attribute.RetentionPolicy.RUNTIME) {
jfranck@2156
  2988
                error = true;
jfranck@2156
  2989
            }
jfranck@2156
  2990
            break;
jfranck@2156
  2991
        case CLASS:
jfranck@2156
  2992
            if (containerRetention == Attribute.RetentionPolicy.SOURCE)  {
jfranck@2156
  2993
                error = true;
jfranck@2156
  2994
            }
jfranck@2156
  2995
        }
jfranck@2156
  2996
        if (error ) {
jjg@2339
  2997
            log.error(pos, "invalid.repeatable.annotation.retention",
jfranck@2156
  2998
                      container, containerRetention,
jfranck@2156
  2999
                      contained, containedRetention);
jfranck@2156
  3000
        }
jfranck@2156
  3001
    }
jfranck@2156
  3002
jfranck@2156
  3003
    private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) {
jfranck@2156
  3004
        if (contained.attribute(syms.documentedType.tsym) != null) {
jfranck@2156
  3005
            if (container.attribute(syms.documentedType.tsym) == null) {
jjg@2339
  3006
                log.error(pos, "invalid.repeatable.annotation.not.documented", container, contained);
jfranck@2156
  3007
            }
jfranck@2156
  3008
        }
jfranck@2156
  3009
    }
jfranck@2156
  3010
jfranck@2156
  3011
    private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) {
jfranck@2156
  3012
        if (contained.attribute(syms.inheritedType.tsym) != null) {
jfranck@2156
  3013
            if (container.attribute(syms.inheritedType.tsym) == null) {
jjg@2339
  3014
                log.error(pos, "invalid.repeatable.annotation.not.inherited", container, contained);
jfranck@2156
  3015
            }
jfranck@2156
  3016
        }
jfranck@2156
  3017
    }
jfranck@2156
  3018
jjg@4454
  3019
    private void validateTarget(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
jfranck@2563
  3020
        // The set of targets the container is applicable to must be a subset
jfranck@2563
  3021
        // (with respect to annotation target semantics) of the set of targets
jfranck@2563
  3022
        // the contained is applicable to. The target sets may be implicit or
jfranck@2563
  3023
        // explicit.
jfranck@2563
  3024
jfranck@2563
  3025
        Set<Name> containerTargets;
jfranck@2156
  3026
        Attribute.Array containerTarget = getAttributeTargetAttribute(container);
jfranck@2156
  3027
        if (containerTarget == null) {
jfranck@2563
  3028
            containerTargets = getDefaultTargetSet();
jfranck@2563
  3029
        } else {
briangoetz@3808
  3030
            containerTargets = new HashSet<>();
briangoetz@3808
  3031
            for (Attribute app : containerTarget.values) {
briangoetz@3808
  3032
                if (!(app instanceof Attribute.Enum)) {
briangoetz@3808
  3033
                    continue; // recovery
briangoetz@3808
  3034
                }
briangoetz@3808
  3035
                Attribute.Enum e = (Attribute.Enum)app;
briangoetz@3808
  3036
                containerTargets.add(e.value.name);
jfranck@2156
  3037
            }
jfranck@2563
  3038
        }
jfranck@2563
  3039
jfranck@2563
  3040
        Set<Name> containedTargets;
jfranck@2563
  3041
        Attribute.Array containedTarget = getAttributeTargetAttribute(contained);
jfranck@2563
  3042
        if (containedTarget == null) {
jfranck@2563
  3043
            containedTargets = getDefaultTargetSet();
jfranck@2563
  3044
        } else {
briangoetz@3808
  3045
            containedTargets = new HashSet<>();
briangoetz@3808
  3046
            for (Attribute app : containedTarget.values) {
briangoetz@3808
  3047
                if (!(app instanceof Attribute.Enum)) {
briangoetz@3808
  3048
                    continue; // recovery
briangoetz@3808
  3049
                }
briangoetz@3808
  3050
                Attribute.Enum e = (Attribute.Enum)app;
briangoetz@3808
  3051
                containedTargets.add(e.value.name);
jfranck@2156
  3052
            }
jfranck@2563
  3053
        }
jfranck@2563
  3054
jfranck@2563
  3055
        if (!isTargetSubsetOf(containerTargets, containedTargets)) {
jjg@2339
  3056
            log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained);
jfranck@2156
  3057
        }
jfranck@2156
  3058
    }
jfranck@2156
  3059
jfranck@2563
  3060
    /* get a set of names for the default target */
jfranck@2563
  3061
    private Set<Name> getDefaultTargetSet() {
jfranck@2563
  3062
        if (defaultTargets == null) {
briangoetz@3808
  3063
            Set<Name> targets = new HashSet<>();
jfranck@2563
  3064
            targets.add(names.ANNOTATION_TYPE);
jfranck@2563
  3065
            targets.add(names.CONSTRUCTOR);
jfranck@2563
  3066
            targets.add(names.FIELD);
jfranck@2563
  3067
            targets.add(names.LOCAL_VARIABLE);
jfranck@2563
  3068
            targets.add(names.METHOD);
jfranck@2563
  3069
            targets.add(names.PACKAGE);
jfranck@2563
  3070
            targets.add(names.PARAMETER);
jfranck@2563
  3071
            targets.add(names.TYPE);
jfranck@2563
  3072
jfranck@2563
  3073
            defaultTargets = java.util.Collections.unmodifiableSet(targets);
jfranck@2563
  3074
        }
jfranck@2563
  3075
jfranck@2563
  3076
        return defaultTargets;
jfranck@2563
  3077
    }
jfranck@2563
  3078
    private Set<Name> defaultTargets;
jfranck@2563
  3079
jfranck@2563
  3080
jfranck@2563
  3081
    /** Checks that s is a subset of t, with respect to ElementType
jfranck@3839
  3082
     * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE},
jfranck@3839
  3083
     * and {TYPE_USE} covers the set {ANNOTATION_TYPE, TYPE, TYPE_USE,
jfranck@3839
  3084
     * TYPE_PARAMETER}.
jfranck@2156
  3085
     */
jfranck@2563
  3086
    private boolean isTargetSubsetOf(Set<Name> s, Set<Name> t) {
jfranck@2563
  3087
        // Check that all elements in s are present in t
jfranck@2563
  3088
        for (Name n2 : s) {
jfranck@2156
  3089
            boolean currentElementOk = false;
jfranck@2563
  3090
            for (Name n1 : t) {
jfranck@2156
  3091
                if (n1 == n2) {
jfranck@2156
  3092
                    currentElementOk = true;
jfranck@2156
  3093
                    break;
jfranck@2156
  3094
                } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) {
jfranck@2156
  3095
                    currentElementOk = true;
jfranck@2156
  3096
                    break;
jfranck@3839
  3097
                } else if (n1 == names.TYPE_USE &&
jfranck@3839
  3098
                        (n2 == names.TYPE ||
jfranck@3839
  3099
                         n2 == names.ANNOTATION_TYPE ||
jfranck@3839
  3100
                         n2 == names.TYPE_PARAMETER)) {
jfranck@3839
  3101
                    currentElementOk = true;
jfranck@3839
  3102
                    break;
jfranck@2156
  3103
                }
jfranck@2156
  3104
            }
jfranck@2156
  3105
            if (!currentElementOk)
jfranck@2156
  3106
                return false;
jfranck@2156
  3107
        }
jfranck@2156
  3108
        return true;
jfranck@2156
  3109
    }
jfranck@2156
  3110
jfranck@3839
  3111
    private void validateDefault(Symbol container, DiagnosticPosition pos) {
jfranck@2183
  3112
        // validate that all other elements of containing type has defaults
jfranck@2183
  3113
        Scope scope = container.members();
jlahoda@4103
  3114
        for(Symbol elm : scope.getSymbols()) {
jfranck@2183
  3115
            if (elm.name != names.value &&
emc@4248
  3116
                elm.kind == MTH &&
jfranck@2183
  3117
                ((MethodSymbol)elm).defaultValue == null) {
jfranck@2183
  3118
                log.error(pos,
jjg@2339
  3119
                          "invalid.repeatable.annotation.elem.nondefault",
jfranck@2183
  3120
                          container,
jfranck@2183
  3121
                          elm);
jfranck@2183
  3122
            }
jfranck@2183
  3123
        }
jfranck@2183
  3124
    }
jfranck@2183
  3125
duke@0
  3126
    /** Is s a method symbol that overrides a method in a superclass? */
duke@0
  3127
    boolean isOverrider(Symbol s) {
duke@0
  3128
        if (s.kind != MTH || s.isStatic())
duke@0
  3129
            return false;
duke@0
  3130
        MethodSymbol m = (MethodSymbol)s;
duke@0
  3131
        TypeSymbol owner = (TypeSymbol)m.owner;
duke@0
  3132
        for (Type sup : types.closure(owner.type)) {
duke@0
  3133
            if (sup == owner.type)
duke@0
  3134
                continue; // skip "this"
duke@0
  3135
            Scope scope = sup.tsym.members();
jlahoda@4103
  3136
            for (Symbol sym : scope.getSymbolsByName(m.name)) {
jlahoda@4103
  3137
                if (!sym.isStatic() && m.overrides(sym, owner, types, true))
duke@0
  3138
                    return true;
duke@0
  3139
            }
duke@0
  3140
        }
duke@0
  3141
        return false;
duke@0
  3142
    }
duke@0
  3143
jlahoda@3135
  3144
    /** Is the annotation applicable to types? */
jjg@2372
  3145
    protected boolean isTypeAnnotation(JCAnnotation a, boolean isTypeParameter) {
alundblad@4477
  3146
        List<Attribute> targets = typeAnnotations.annotationTargets(a.annotationType.type.tsym);
jjg@4454
  3147
        return (targets == null) ?
jjg@4454
  3148
                false :
jjg@4454
  3149
                targets.stream()
jjg@4454
  3150
                        .anyMatch(attr -> isTypeAnnotation(attr, isTypeParameter));
jjg@4454
  3151
    }
jjg@4454
  3152
    //where
jjg@4454
  3153
        boolean isTypeAnnotation(Attribute a, boolean isTypeParameter) {
jjg@4454
  3154
            Attribute.Enum e = (Attribute.Enum)a;
jjg@4454
  3155
            return (e.value.name == names.TYPE_USE ||
jjg@4454
  3156
                    (isTypeParameter && e.value.name == names.TYPE_PARAMETER));
jjg@2372
  3157
        }
jjg@2372
  3158
duke@0
  3159
    /** Is the annotation applicable to the symbol? */
duke@0
  3160
    boolean annotationApplicable(JCAnnotation a, Symbol s) {
jfranck@2156
  3161
        Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym);
jjg@2372
  3162
        Name[] targets;
jlahoda@3239
  3163
jfranck@2156
  3164
        if (arr == null) {
jjg@2372
  3165
            targets = defaultTargetMetaInfo(a, s);
jjg@2372
  3166
        } else {
jjg@2372
  3167
            // TODO: can we optimize this?
jjg@2372
  3168
            targets = new Name[arr.values.length];
jjg@2372
  3169
            for (int i=0; i<arr.values.length; ++i) {
jjg@2372
  3170
                Attribute app = arr.values[i];
jjg@2372
  3171
                if (!(app instanceof Attribute.Enum)) {
jjg@2372
  3172
                    return true; // recovery
jjg@2372
  3173
                }
jjg@2372
  3174
                Attribute.Enum e = (Attribute.Enum) app;
jjg@2372
  3175
                targets[i] = e.value.name;
jjg@2372
  3176
            }
jfranck@2156
  3177
        }
jjg@2372
  3178
        for (Name target : targets) {
jjg@4454
  3179
            if (target == names.TYPE) {
jjg@4454
  3180
                if (s.kind == TYP)
jjg@4454
  3181
                    return true;
jjg@4454
  3182
            } else if (target == names.FIELD) {
jjg@4454
  3183
                if (s.kind == VAR && s.owner.kind != MTH)
jjg@4454
  3184
                    return true;
jjg@4454
  3185
            } else if (target == names.METHOD) {
jjg@4454
  3186
                if (s.kind == MTH && !s.isConstructor())
jjg@4454
  3187
                    return true;
jjg@4454
  3188
            } else if (target == names.PARAMETER) {
jjg@4454
  3189
                if (s.kind == VAR && s.owner.kind == MTH &&
jjg@4454
  3190
                      (s.flags() & PARAMETER) != 0) {
duke@0
  3191
                    return true;
duke@0
  3192
                }
jjg@4454
  3193
            } else if (target == names.CONSTRUCTOR) {
jjg@4454
  3194
                if (s.kind == MTH && s.isConstructor())
jjg@4454
  3195
                    return true;
jjg@4454
  3196
            } else if (target == names.LOCAL_VARIABLE) {
jjg@4454
  3197
                if (s.kind == VAR && s.owner.kind == MTH &&
jjg@4454
  3198
                      (s.flags() & PARAMETER) == 0) {
duke@0
  3199
                    return true;
duke@0
  3200
                }
jjg@4454
  3201
            } else if (target == names.ANNOTATION_TYPE) {
jjg@4454
  3202
                if (s.kind == TYP && (s.flags() & ANNOTATION) != 0) {
duke@0
  3203
                    return true;
duke@0
  3204
                }
jjg@4454
  3205
            } else if (target == names.PACKAGE) {
jjg@4454
  3206
                if (s.kind == PCK)
jjg@4454
  3207
                    return true;
jjg@4454
  3208
            } else if (target == names.TYPE_USE) {
jjg@4454
  3209
                if (s.kind == TYP || s.kind == VAR ||
jjg@4454
  3210
                        (s.kind == MTH && !s.isConstructor() &&
jjg@4454
  3211
                                !s.type.getReturnType().hasTag(VOID)) ||
jjg@4454
  3212
                        (s.kind == MTH && s.isConstructor())) {
jjg@2372
  3213
                    return true;
jjg@2372
  3214
                }
jjg@4454
  3215
            } else if (target == names.TYPE_PARAMETER) {
jjg@4454
  3216
                if (s.kind == TYP && s.type.hasTag(TYPEVAR))
jjg@598
  3217
                    return true;
jjg@4454
  3218
            } else
jjg@4454
  3219
                return true; // Unknown ElementType. This should be an error at declaration site,
jjg@4454
  3220
                             // assume applicable.
duke@0
  3221
        }
duke@0
  3222
        return false;
duke@0
  3223
    }
duke@0
  3224
jfranck@2156
  3225
jjg@4454
  3226
    Attribute.Array getAttributeTargetAttribute(TypeSymbol s) {
jjg@4454
  3227
        Attribute.Compound atTarget = s.getAnnotationTypeMetadata().getTarget();
jfranck@2156
  3228
        if (atTarget == null) return null; // ok, is applicable
jfranck@2156
  3229
        Attribute atValue = atTarget.member(names.value);
jfranck@2156
  3230
        if (!(atValue instanceof Attribute.Array)) return null; // error recovery
jfranck@2156
  3231
        return (Attribute.Array) atValue;
jfranck@2156
  3232
    }
jfranck@2156
  3233
jjg@2372
  3234
    private final Name[] dfltTargetMeta;
jjg@2372
  3235
    private Name[] defaultTargetMetaInfo(JCAnnotation a, Symbol s) {
jjg@2372
  3236
        return dfltTargetMeta;
jjg@2372
  3237
    }
jjg@2372
  3238
duke@0
  3239
    /** Check an annotation value.
jfranck@2288
  3240
     *
jfranck@2288
  3241
     * @param a The annotation tree to check
jfranck@2288
  3242
     * @return true if this annotation tree is valid, otherwise false
duke@0
  3243
     */
jfranck@2288
  3244
    public boolean validateAnnotationDeferErrors(JCAnnotation a) {
jfranck@2288
  3245
        boolean res = false;
jfranck@2288
  3246
        final Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
jfranck@2288
  3247
        try {
jfranck@2288
  3248
            res = validateAnnotation(a);
jfranck@2288
  3249
        } finally {
jfranck@2288
  3250
            log.popDiagnosticHandler(diagHandler);
jfranck@2288
  3251
        }
jfranck@2288
  3252
        return res;
jfranck@2288
  3253
    }
jfranck@2288
  3254
jfranck@2288
  3255
    private boolean validateAnnotation(JCAnnotation a) {
jfranck@2288
  3256
        boolean isValid = true;
jjg@4454
  3257
        AnnotationTypeMetadata metadata = a.annotationType.type.tsym.getAnnotationTypeMetadata();
jjg@4454
  3258
jfranck@2288
  3259
        // collect an inventory of the annotation elements
jjg@4454
  3260
        Set<MethodSymbol> elements = metadata.getAnnotationElements();
duke@0
  3261
jfranck@2288
  3262
        // remove the ones that are assigned values
duke@0
  3263
        for (JCTree arg : a.args) {
jjg@1972
  3264
            if (!arg.hasTag(ASSIGN)) continue; // recovery
jjg@4454
  3265
            JCAssign assign = (JCAssign)arg;
duke@0
  3266
            Symbol m = TreeInfo.symbol(assign.lhs);
duke@0
  3267
            if (m == null || m.type.isErroneous()) continue;
jjg@4454
  3268
            if (!elements.remove(m)) {
jfranck@2288
  3269
                isValid = false;
jjg@870
  3270
                log.error(assign.lhs.pos(), "duplicate.annotation.member.value",
jjg@4454
  3271
                        m.name, a.type);
jfranck@2288
  3272
            }
duke@0
  3273
        }
duke@0
  3274
duke@0
  3275
        // all the remaining ones better have default values
jfranck@2288
  3276
        List<Name> missingDefaults = List.nil();
jjg@4454
  3277
        Set<MethodSymbol> membersWithDefault = metadata.getAnnotationElementsWithDefault();
jjg@4454
  3278
        for (MethodSymbol m : elements) {
dbalek@4654
  3279
            if (m.type.isErroneous() || m.name == m.name.table.names.clinit)
jjg@4454
  3280
                continue;
jjg@4454
  3281
jjg@4454
  3282
            if (!membersWithDefault.contains(m))
jfranck@2288
  3283
                missingDefaults = missingDefaults.append(m.name);
mcimadamore@1032
  3284
        }
jfranck@2288
  3285
        missingDefaults = missingDefaults.reverse();
mcimadamore@1032
  3286
        if (missingDefaults.nonEmpty()) {
jfranck@2288
  3287
            isValid = false;
mcimadamore@1032
  3288
            String key = (missingDefaults.size() > 1)
mcimadamore@1032
  3289
                    ? "annotation.missing.default.value.1"
mcimadamore@1032
  3290
                    : "annotation.missing.default.value";
mcimadamore@1032
  3291
            log.error(a.pos(), key, a.type, missingDefaults);
mcimadamore@1032
  3292
        }
duke@0
  3293
jjg@4454
  3294
        return isValid && validateTargetAnnotationValue(a);
jjg@4454
  3295
    }
jjg@4454
  3296
jjg@4454
  3297
    /* Validate the special java.lang.annotation.Target annotation */
jjg@4454
  3298
    boolean validateTargetAnnotationValue(JCAnnotation a) {
duke@0
  3299
        // special case: java.lang.annotation.Target must not have
duke@0
  3300
        // repeated values in its value member
duke@0
  3301
        if (a.annotationType.type.tsym != syms.annotationTargetType.tsym ||
jjg@4454
  3302
                a.args.tail == null)
jjg@4454
  3303
            return true;
jjg@4454
  3304
jjg@4454
  3305
        boolean isValid = true;
jfranck@2288
  3306
        if (!a.args.head.hasTag(ASSIGN)) return false; // error recovery
duke@0
  3307
        JCAssign assign = (JCAssign) a.args.head;
duke@0
  3308
        Symbol m = TreeInfo.symbol(assign.lhs);
jfranck@2288
  3309
        if (m.name != names.value) return false;
duke@0
  3310
        JCTree rhs = assign.rhs;
jfranck@2288
  3311
        if (!rhs.hasTag(NEWARRAY)) return false;
duke@0
  3312
        JCNewArray na = (JCNewArray) rhs;
briangoetz@3808
  3313
        Set<Symbol> targets = new HashSet<>();
duke@0
  3314
        for (JCTree elem : na.elems) {
duke@0
  3315
            if (!targets.add(TreeInfo.symbol(elem))) {
jfranck@2288
  3316
                isValid = false;
duke@0
  3317
                log.error(elem.pos(), "repeated.annotation.target");
duke@0
  3318
            }
duke@0
  3319
        }
jfranck@2288
  3320
        return isValid;
duke@0
  3321
    }
duke@0
  3322
duke@0
  3323
    void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
sadayapalam@5383
  3324
        if (lint.isEnabled(LintCategory.DEP_ANN) && s.isDeprecatableViaAnnotation() &&
duke@0
  3325
            (s.flags() & DEPRECATED) != 0 &&
duke@0
  3326
            !syms.deprecatedType.isErroneous() &&
duke@0
  3327
            s.attribute(syms.deprecatedType.tsym) == null) {
mcimadamore@1244
  3328
            log.warning(LintCategory.DEP_ANN,
jjg@1008
  3329
                    pos, "missing.deprecated.annotation");
duke@0
  3330
        }
sadayapalam@5312
  3331
        // Note: @Deprecated has no effect on local variables, parameters and package decls.
sadayapalam@5383
  3332
        if (lint.isEnabled(LintCategory.DEPRECATION) && !s.isDeprecatableViaAnnotation()) {
sadayapalam@5312
  3333
            if (!syms.deprecatedType.isErroneous() && s.attribute(syms.deprecatedType.tsym) != null) {
sadayapalam@5383
  3334
                log.warning(LintCategory.DEPRECATION, pos,
sadayapalam@5383
  3335
                        "deprecated.annotation.has.no.effect", Kinds.kindName(s));
sadayapalam@5312
  3336
            }
sadayapalam@5312
  3337
        }
duke@0
  3338
    }
duke@0
  3339
mcimadamore@1317
  3340
    void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) {
jjg@5468
  3341
        if ( (s.isDeprecatedForRemoval()
jjg@5468
  3342
                || s.isDeprecated() && !other.isDeprecated())
alanb@5550
  3343
                && (s.outermostClass() != other.outermostClass() || s.outermostClass() == null)) {
mcimadamore@5585
  3344
            deferredLintHandler.report(() -> warnDeprecated(pos, s));
jjg@1996
  3345
        }
mcimadamore@1317
  3346
    }
mcimadamore@1317
  3347
mcimadamore@1317
  3348
    void checkSunAPI(final DiagnosticPosition pos, final Symbol s) {
mcimadamore@1317
  3349
        if ((s.flags() & PROPRIETARY) != 0) {
vromero@4965
  3350
            deferredLintHandler.report(() -> {
vromero@4965
  3351
                log.mandatoryWarning(pos, "sun.proprietary", s);
mcimadamore@1317
  3352
            });
mcimadamore@1317
  3353
        }
mcimadamore@1317
  3354
    }
mcimadamore@1317
  3355
jjg@2470
  3356
    void checkProfile(final DiagnosticPosition pos, final Symbol s) {
jjg@2470
  3357
        if (profile != Profile.DEFAULT && (s.flags() & NOT_IN_PROFILE) != 0) {
jjg@2470
  3358
            log.error(pos, "not.in.profile", s, profile);
jjg@2470
  3359
        }
jjg@2470
  3360
    }
jjg@2470
  3361
duke@0
  3362
/* *************************************************************************
duke@0
  3363
 * Check for recursive annotation elements.
duke@0
  3364
 **************************************************************************/
duke@0
  3365
duke@0
  3366
    /** Check for cycles in the graph of annotation elements.
duke@0
  3367
     */
duke@0
  3368
    void checkNonCyclicElements(JCClassDecl tree) {
duke@0
  3369
        if ((tree.sym.flags_field & ANNOTATION) == 0) return;
jjg@1281
  3370
        Assert.check((tree.sym.flags_field & LOCKED) == 0);
duke@0
  3371
        try {
duke@0
  3372
            tree.sym.flags_field |= LOCKED;
duke@0
  3373
            for (JCTree def : tree.defs) {
jjg@1972
  3374
                if (!def.hasTag(METHODDEF)) continue;
duke@0
  3375
                JCMethodDecl meth = (JCMethodDecl)def;
dbalek@4852
  3376
                if (meth.restype != null) {
dbalek@4852
  3377
                    checkAnnotationResType(meth.pos(), meth.restype.type);
dbalek@4852
  3378
                }
duke@0
  3379
            }
duke@0
  3380
        } finally {
duke@0
  3381
            tree.sym.flags_field &= ~LOCKED;
duke@0
  3382
            tree.sym.flags_field |= ACYCLIC_ANN;
duke@0
  3383
        }
duke@0
  3384
    }
duke@0
  3385
duke@0
  3386
    void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) {
duke@0
  3387
        if ((tsym.flags_field & ACYCLIC_ANN) != 0)
duke@0
  3388
            return;
duke@0
  3389
        if ((tsym.flags_field & LOCKED) != 0) {
duke@0
  3390
            log.error(pos, "cyclic.annotation.element");
duke@0
  3391
            return;
duke@0
  3392
        }
duke@0
  3393
        try {
duke@0
  3394
            tsym.flags_field |= LOCKED;
jlahoda@4103
  3395
            for (Symbol s : tsym.members().getSymbols(NON_RECURSIVE)) {
emc@4248
  3396
                if (s.kind != MTH)
duke@0
  3397
                    continue;
duke@0
  3398
                checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType());
duke@0
  3399
            }
duke@0
  3400
        } finally {
duke@0
  3401
            tsym.flags_field &= ~LOCKED;
duke@0
  3402
            tsym.flags_field |= ACYCLIC_ANN;
duke@0
  3403
        }
duke@0
  3404
    }
duke@0
  3405
duke@0
  3406
    void checkAnnotationResType(DiagnosticPosition pos, Type type) {
jjg@2213
  3407
        switch (type.getTag()) {
jjg@2213
  3408
        case CLASS:
duke@0
  3409
            if ((type.tsym.flags() & ANNOTATION) != 0)
duke@0
  3410
                checkNonCyclicElementsInternal(pos, type.tsym);
duke@0
  3411
            break;
jjg@2213
  3412
        case ARRAY:
duke@0
  3413
            checkAnnotationResType(pos, types.elemtype(type));
duke@0
  3414
            break;
duke@0
  3415
        default:
duke@0
  3416
            break; // int etc
duke@0
  3417
        }
duke@0
  3418
    }
duke@0
  3419
duke@0
  3420
/* *************************************************************************
duke@0
  3421
 * Check for cycles in the constructor call graph.
duke@0
  3422
 **************************************************************************/
duke@0
  3423
duke@0
  3424
    /** Check for cycles in the graph of constructors calling other
duke@0
  3425
     *  constructors.
duke@0
  3426
     */
duke@0
  3427
    void checkCyclicConstructors(JCClassDecl tree) {
briangoetz@3808
  3428
        Map<Symbol,Symbol> callMap = new HashMap<>();
duke@0
  3429
duke@0
  3430
        // enter each constructor this-call into the map
duke@0
  3431
        for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
duke@0
  3432
            JCMethodInvocation app = TreeInfo.firstConstructorCall(l.head);
duke@0
  3433
            if (app == null) continue;
duke@0
  3434
            JCMethodDecl meth = (JCMethodDecl) l.head;
duke@0
  3435
            if (TreeInfo.name(app.meth) == names._this) {
duke@0
  3436
                callMap.put(meth.sym, TreeInfo.symbol(app.meth));
dbalek@761
  3437
            } else if (meth.sym != null) {
duke@0
  3438
                meth.sym.flags_field |= ACYCLIC;
duke@0
  3439
            }
duke@0
  3440
        }
duke@0
  3441
duke@0
  3442
        // Check for cycles in the map
duke@0
  3443
        Symbol[] ctors = new Symbol[0];
duke@0
  3444
        ctors = callMap.keySet().toArray(ctors);
duke@0
  3445
        for (Symbol caller : ctors) {
duke@0
  3446
            checkCyclicConstructor(tree, caller, callMap);
duke@0
  3447
        }
duke@0
  3448
    }
duke@0
  3449
duke@0
  3450
    /** Look in the map to see if the given constructor is part of a
duke@0
  3451
     *  call cycle.
duke@0
  3452
     */
duke@0
  3453
    private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor,
duke@0
  3454
                                        Map<Symbol,Symbol> callMap) {
duke@0
  3455
        if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) {
duke@0
  3456
            if ((ctor.flags_field & LOCKED) != 0) {
duke@0
  3457
                log.error(TreeInfo.diagnosticPositionFor(ctor, tree),
duke@0
  3458
                          "recursive.ctor.invocation");
duke@0
  3459
            } else {
duke@0
  3460
                ctor.flags_field |= LOCKED;
duke@0
  3461
                checkCyclicConstructor(tree, callMap.remove(ctor), callMap);
duke@0
  3462
                ctor.flags_field &= ~LOCKED;
duke@0
  3463
            }
duke@0
  3464
            ctor.flags_field |= ACYCLIC;
duke@0
  3465
        }
duke@0
  3466
    }
duke@0
  3467
duke@0
  3468
/* *************************************************************************
duke@0
  3469
 * Miscellaneous
duke@0
  3470
 **************************************************************************/
duke@0
  3471
duke@0
  3472
    /**
duke@0
  3473
     *  Check for division by integer constant zero
duke@0
  3474
     *  @param pos           Position for error reporting.
duke@0
  3475
     *  @param operator      The operator for the expression
duke@0
  3476
     *  @param operand       The right hand operand for the expression
duke@0
  3477
     */
jlahoda@4081
  3478
    void checkDivZero(final DiagnosticPosition pos, Symbol operator, Type operand) {
duke@0
  3479
        if (operand.constValue() != null
vromero@2810
  3480
            && operand.getTag().isSubRangeOf(LONG)
duke@0
  3481
            && ((Number) (operand.constValue())).longValue() == 0) {
duke@0
  3482
            int opc = ((OperatorSymbol)operator).opcode;
duke@0
  3483
            if (opc == ByteCodes.idiv || opc == ByteCodes.imod
duke@0
  3484
                || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
mcimadamore@5585
  3485
                deferredLintHandler.report(() -> warnDivZero(pos));
duke@0
  3486
            }
duke@0
  3487
        }
duke@0
  3488
    }
duke@0
  3489
duke@0
  3490
    /**
duke@0
  3491
     * Check for empty statements after if
duke@0
  3492
     */
duke@0
  3493
    void checkEmptyIf(JCIf tree) {
jjg@1972
  3494
        if (tree.thenpart.hasTag(SKIP) && tree.elsepart == null &&
jjg@1972
  3495
                lint.isEnabled(LintCategory.EMPTY))
mcimadamore@1244
  3496
            log.warning(LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
duke@0
  3497
    }
duke@0
  3498
duke@0
  3499
    /** Check that symbol is unique in given scope.
duke@0
  3500
     *  @param pos           Position for error reporting.
duke@0
  3501
     *  @param sym           The symbol.
duke@0
  3502
     *  @param s             The scope.
duke@0
  3503
     */
duke@0
  3504
    boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) {
dbalek@3747
  3505
        if (sym.type != null && sym.type.isErroneous())
duke@0
  3506
            return true;
duke@0
  3507
        if (sym.owner.name == names.any) return false;
jlahoda@4103
  3508
        for (Symbol byName : s.getSymbolsByName(sym.name, NON_RECURSIVE)) {
jlahoda@4103
  3509
            if (sym != byName &&
jlahoda@4103
  3510
                    (byName.flags() & CLASH) == 0 &&
jlahoda@4103
  3511
                    sym.kind == byName.kind &&
mcimadamore@1348
  3512
                    sym.name != names.error &&
emc@3040
  3513
                    (sym.kind != MTH ||
jlahoda@4103
  3514
                     types.hasSameArgs(sym.type, byName.type) ||
jlahoda@4103
  3515
                     types.hasSameArgs(types.erasure(sym.type), types.erasure(byName.type)))) {
jlahoda@4103
  3516
                if ((sym.flags() & VARARGS) != (byName.flags() & VARARGS)) {
jlahoda@4103
  3517
                    varargsDuplicateError(pos, sym, byName);
mcimadamore@1309
  3518
                    return true;
jlahoda@4103
  3519
                } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, byName.type, false)) {
jlahoda@4103
  3520
                    duplicateErasureError(pos, sym, byName);
mcimadamore@1309
  3521
                    sym.flags_field |= CLASH;
mcimadamore@1309
  3522
                    return true;
mcimadamore@1309
  3523
                } else {
jlahoda@4103
  3524
                    duplicateError(pos, byName);
mcimadamore@1309
  3525
                    return false;
mcimadamore@1309
  3526
                }
duke@0
  3527
            }
duke@0
  3528
        }
duke@0
  3529
        return true;
duke@0
  3530
    }
mcimadamore@1309
  3531
mcimadamore@1348
  3532
    /** Report duplicate declaration error.
mcimadamore@1348
  3533
     */
mcimadamore@1348
  3534
    void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
mcimadamore@1348
  3535
        if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
mcimadamore@1348
  3536
            log.error(pos, "name.clash.same.erasure", sym1, sym2);
mcimadamore@1309
  3537
        }
mcimadamore@1348
  3538
    }
duke@0
  3539
jlahoda@4314
  3540
    /**Check that types imported through the ordinary imports don't clash with types imported
jlahoda@4314
  3541
     * by other (static or ordinary) imports. Note that two static imports may import two clashing
jlahoda@4314
  3542
     * types without an error on the imports.
jlahoda@4314
  3543
     * @param toplevel       The toplevel tree for which the test should be performed.
jlahoda@4314
  3544
     */
jlahoda@4314
  3545
    void checkImportsUnique(JCCompilationUnit toplevel) {
jlahoda@4314
  3546
        WriteableScope ordinallyImportedSoFar = WriteableScope.create(toplevel.packge);
jlahoda@4314
  3547
        WriteableScope staticallyImportedSoFar = WriteableScope.create(toplevel.packge);
jlahoda@4314
  3548
        WriteableScope topLevelScope = toplevel.toplevelScope;
jlahoda@4314
  3549
jlahoda@4314
  3550
        for (JCTree def : toplevel.defs) {
jlahoda@4314
  3551
            if (!def.hasTag(IMPORT))
jlahoda@4314
  3552
                continue;
jlahoda@4314
  3553
jlahoda@4314
  3554
            JCImport imp = (JCImport) def;
jlahoda@4314
  3555
jlahoda@4314
  3556
            if (imp.importScope == null)
jlahoda@4314
  3557
                continue;
jlahoda@4314
  3558
jlahoda@4314
  3559
            for (Symbol sym : imp.importScope.getSymbols(sym -> sym.kind == TYP)) {
jlahoda@4314
  3560
                if (imp.isStatic()) {
jlahoda@4314
  3561
                    checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, true);
jlahoda@4314
  3562
                    staticallyImportedSoFar.enter(sym);
jlahoda@4314
  3563
                } else {
jlahoda@4314
  3564
                    checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, false);
jlahoda@4314
  3565
                    ordinallyImportedSoFar.enter(sym);
jlahoda@4314
  3566
                }
jlahoda@4314
  3567
            }
jlahoda@4314
  3568
jlahoda@4314
  3569
            imp.importScope = null;
jlahoda@4314
  3570
        }
jlahoda@4314
  3571
    }
jlahoda@4314
  3572
duke@0
  3573
    /** Check that single-type import is not already imported or top-level defined,
duke@0
  3574
     *  but make an exception for two single-type imports which denote the same type.
jlahoda@4314
  3575
     *  @param pos                     Position for error reporting.
jlahoda@4314
  3576
     *  @param ordinallyImportedSoFar  A Scope containing types imported so far through
jlahoda@4314
  3577
     *                                 ordinary imports.
jlahoda@4314
  3578
     *  @param staticallyImportedSoFar A Scope containing types imported so far through
jlahoda@4314
  3579
     *                                 static imports.
jlahoda@4314
  3580
     *  @param topLevelScope           The current file's top-level Scope
jlahoda@4314
  3581
     *  @param sym                     The symbol.
jlahoda@4314
  3582
     *  @param staticImport            Whether or not this was a static import
duke@0
  3583
     */
jlahoda@4314
  3584
    private boolean checkUniqueImport(DiagnosticPosition pos, Scope ordinallyImportedSoFar,
jlahoda@4314
  3585
                                      Scope staticallyImportedSoFar, Scope topLevelScope,
jlahoda@4314
  3586
                                      Symbol sym, boolean staticImport) {
jlahoda@4314
  3587
        Filter<Symbol> duplicates = candidate -> candidate != sym && !candidate.type.isErroneous();
jlahoda@4314
  3588
        Symbol clashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates);
jlahoda@4314
  3589
        if (clashing == null && !staticImport) {
jlahoda@4314
  3590
            clashing = staticallyImportedSoFar.findFirst(sym.name, duplicates);
jlahoda@4314
  3591
        }
jlahoda@4314
  3592
        if (clashing != null) {
jlahoda@4314
  3593
            if (staticImport)
jlahoda@4314
  3594
                log.error(pos, "already.defined.static.single.import", clashing);
jlahoda@4314
  3595
            else
jlahoda@4314
  3596
                log.error(pos, "already.defined.single.import", clashing);
jlahoda@4314
  3597
            return false;
jlahoda@4314
  3598
        }
jlahoda@4314
  3599
        clashing = topLevelScope.findFirst(sym.name, duplicates);
jlahoda@4314
  3600
        if (clashing != null) {
jlahoda@4314
  3601
            log.error(pos, "already.defined.this.unit", clashing);
jlahoda@4314
  3602
            return false;
duke@0
  3603
        }
duke@0
  3604
        return true;
duke@0
  3605
    }
duke@0
  3606
duke@0
  3607
    /** Check that a qualified name is in canonical form (for import decls).
duke@0
  3608
     */
duke@0
  3609
    public void checkCanonical(JCTree tree) {
duke@0
  3610
        if (!isCanonical(tree))
duke@0
  3611
            log.error(tree.pos(), "import.requires.canonical",
duke@0
  3612
                      TreeInfo.symbol(tree));
duke@0
  3613
    }
duke@0
  3614
        // where
duke@0
  3615
        private boolean isCanonical(JCTree tree) {
jjg@1972
  3616
            while (tree.hasTag(SELECT)) {
duke@0
  3617
                JCFieldAccess s = (JCFieldAccess) tree;
alanb@5016
  3618
                if (s.sym.owner.name != TreeInfo.symbol(s.selected).name)
duke@0
  3619
                    return false;
duke@0
  3620
                tree = s.selected;
duke@0
  3621
            }
duke@0
  3622
            return true;
duke@0
  3623
        }
duke@0
  3624
ohrstrom@2227
  3625
    /** Check that an auxiliary class is not accessed from any other file than its own.
ohrstrom@2227
  3626
     */
ohrstrom@2227
  3627
    void checkForBadAuxiliaryClassAccess(DiagnosticPosition pos, Env<AttrContext> env, ClassSymbol c) {
ohrstrom@2227
  3628
        if (lint.isEnabled(Lint.LintCategory.AUXILIARYCLASS) &&
ohrstrom@2227
  3629
            (c.flags() & AUXILIARY) != 0 &&
ohrstrom@2227
  3630
            rs.isAccessible(env, c) &&
ohrstrom@2227
  3631
            !fileManager.isSameFile(c.sourcefile, env.toplevel.sourcefile))
ohrstrom@2227
  3632
        {
ohrstrom@2227
  3633
            log.warning(pos, "auxiliary.class.accessed.from.outside.of.its.source.file",
ohrstrom@2227
  3634
                        c, c.sourcefile);
ohrstrom@2227
  3635
        }
ohrstrom@2227
  3636
    }
ohrstrom@2227
  3637
duke@0
  3638
    private class ConversionWarner extends Warner {
mcimadamore@1244
  3639
        final String uncheckedKey;
duke@0
  3640
        final Type found;
duke@0
  3641
        final Type expected;
mcimadamore@1244
  3642
        public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) {
duke@0
  3643
            super(pos);
mcimadamore@1244
  3644
            this.uncheckedKey = uncheckedKey;
duke@0
  3645
            this.found = found;
duke@0
  3646
            this.expected = expected;
duke@0
  3647
        }
duke@0
  3648
jjg@688
  3649
        @Override
mcimadamore@1244
  3650
        public void warn(LintCategory lint) {
duke@0
  3651
            boolean warned = this.warned;
mcimadamore@1244
  3652
            super.warn(lint);
duke@0
  3653
            if (warned) return; // suppress redundant diagnostics
mcimadamore@1244
  3654
            switch (lint) {
mcimadamore@1244
  3655
                case UNCHECKED:
mcimadamore@1244
  3656
                    Check.this.warnUnchecked(pos(), "prob.found.req", diags.fragment(uncheckedKey), found, expected);
mcimadamore@1244
  3657
                    break;
mcimadamore@1244
  3658
                case VARARGS:
mcimadamore@1244
  3659
                    if (method != null &&
mcimadamore@1244
  3660
                            method.attribute(syms.trustMeType.tsym) != null &&
mcimadamore@1244
  3661
                            isTrustMeAllowedOnMethod(method) &&
mcimadamore@1244
  3662
                            !types.isReifiable(method.type.getParameterTypes().last())) {
mcimadamore@1244
  3663
                        Check.this.warnUnsafeVararg(pos(), "varargs.unsafe.use.varargs.param", method.params.last());
mcimadamore@1244
  3664
                    }
mcimadamore@1244
  3665
                    break;
mcimadamore@1244
  3666
                default:
mcimadamore@1244
  3667
                    throw new AssertionError("Unexpected lint: " + lint);
mcimadamore@1244
  3668
            }
duke@0
  3669
        }
duke@0
  3670
    }
duke@0
  3671
duke@0
  3672
    public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) {
duke@0
  3673
        return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected);
duke@0
  3674
    }
duke@0
  3675
duke@0
  3676
    public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) {
duke@0
  3677
        return new ConversionWarner(pos, "unchecked.assign", found, expected);
duke@0
  3678
    }
jlahoda@3135
  3679
jlahoda@3135
  3680
    public void checkFunctionalInterface(JCClassDecl tree, ClassSymbol cs) {
jlahoda@3135
  3681
        Compound functionalType = cs.attribute(syms.functionalInterfaceType.tsym);
jlahoda@3135
  3682
jlahoda@3135
  3683
        if (functionalType != null) {
jlahoda@3135
  3684
            try {
jlahoda@3135
  3685
                types.findDescriptorSymbol((TypeSymbol)cs);
jlahoda@3135
  3686
            } catch (Types.FunctionDescriptorLookupError ex) {
jlahoda@3135
  3687
                DiagnosticPosition pos = tree.pos();
jlahoda@3135
  3688
                for (JCAnnotation a : tree.getModifiers().annotations) {
jlahoda@3135
  3689
                    if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) {
jlahoda@3135
  3690
                        pos = a.pos();
jlahoda@3135
  3691
                        break;
jlahoda@3135
  3692
                    }
jlahoda@3135
  3693
                }
jlahoda@3135
  3694
                log.error(pos, "bad.functional.intf.anno.1", ex.getDiagnostic());
jlahoda@3135
  3695
            }
jlahoda@3135
  3696
        }
jlahoda@3135
  3697
    }
jlahoda@4103
  3698
jlahoda@4103
  3699
    public void checkImportsResolvable(final JCCompilationUnit toplevel) {
jlahoda@4103
  3700
        for (final JCImport imp : toplevel.getImports()) {
jlahoda@4103
  3701
            if (!imp.staticImport || !imp.qualid.hasTag(SELECT))
jlahoda@4103
  3702
                continue;
jlahoda@4103
  3703
            final JCFieldAccess select = (JCFieldAccess) imp.qualid;
jlahoda@4103
  3704
            final Symbol origin;
jlahoda@4103
  3705
            if (select.name == names.asterisk || (origin = TreeInfo.symbol(select.selected)) == null || origin.kind != TYP)
jlahoda@4103
  3706
                continue;
jlahoda@4103
  3707
jlahoda@4314
  3708
            TypeSymbol site = (TypeSymbol) TreeInfo.symbol(select.selected);
jlahoda@4314
  3709
            if (!checkTypeContainsImportableElement(site, site, toplevel.packge, select.name, new HashSet<Symbol>())) {
jlahoda@4314
  3710
                log.error(imp.pos(), "cant.resolve.location",
jlahoda@4314
  3711
                          KindName.STATIC,
jlahoda@4314
  3712
                          select.name, List.<Type>nil(), List.<Type>nil(),
jlahoda@4314
  3713
                          Kinds.typeKindName(TreeInfo.symbol(select.selected).type),
jlahoda@4314
  3714
                          TreeInfo.symbol(select.selected).type);
jlahoda@4103
  3715
            }
jlahoda@4103
  3716
        }
jlahoda@4103
  3717
    }
jlahoda@4103
  3718
sadayapalam@4546
  3719
    // Check that packages imported are in scope (JLS 7.4.3, 6.3, 6.5.3.1, 6.5.3.2)
sadayapalam@4546
  3720
    public void checkImportedPackagesObservable(final JCCompilationUnit toplevel) {
alanb@5016
  3721
        OUTER: for (JCImport imp : toplevel.getImports()) {
dbalek@5253
  3722
            if (!imp.staticImport && TreeInfo.name(imp.qualid) == names.asterisk
dbalek@5253
  3723
                    && ((JCFieldAccess)imp.qualid).selected.type != null) {
sadayapalam@4546
  3724
                TypeSymbol tsym = ((JCFieldAccess)imp.qualid).selected.type.tsym;
alanb@5016
  3725
                if (toplevel.modle.visiblePackages != null) {
alanb@5016
  3726
                    //TODO - unclear: selects like javax.* will get resolved from the current module
alanb@5016
  3727
                    //(as javax is not an exported package from any module). And as javax in the current
alanb@5016
  3728
                    //module typically does not contain any classes or subpackages, we need to go through
alanb@5016
  3729
                    //the visible packages to find a sub-package:
alanb@5016
  3730
                    for (PackageSymbol known : toplevel.modle.visiblePackages.values()) {
alanb@5016
  3731
                        if (Convert.packagePart(known.fullname) == tsym.flatName())
alanb@5016
  3732
                            continue OUTER;
alanb@5016
  3733
                    }
alanb@5016
  3734
                }
sadayapalam@4546
  3735
                if (tsym.kind == PCK && tsym.members().isEmpty() && !tsym.exists()) {
sadayapalam@4546
  3736
                    log.error(DiagnosticFlag.RESOLVE_ERROR, imp.pos, "doesnt.exist", tsym);
sadayapalam@4546
  3737
                }
sadayapalam@4546
  3738
            }
sadayapalam@4546
  3739
        }
sadayapalam@4546
  3740
    }
sadayapalam@4546
  3741
jlahoda@4103
  3742
    private boolean checkTypeContainsImportableElement(TypeSymbol tsym, TypeSymbol origin, PackageSymbol packge, Name name, Set<Symbol> processed) {
jlahoda@4103
  3743
        if (tsym == null || !processed.add(tsym))
jlahoda@4103
  3744
            return false;
jlahoda@4103
  3745
jlahoda@4103
  3746
            // also search through inherited names
jlahoda@4103
  3747
        if (checkTypeContainsImportableElement(types.supertype(tsym.type).tsym, origin, packge, name, processed))
jlahoda@4103
  3748
            return true;
jlahoda@4103
  3749
jlahoda@4103
  3750
        for (Type t : types.interfaces(tsym.type))
jlahoda@4103
  3751
            if (checkTypeContainsImportableElement(t.tsym, origin, packge, name, processed))
jlahoda@4103
  3752
                return true;
jlahoda@4103
  3753
jlahoda@4103
  3754
        for (Symbol sym : tsym.members().getSymbolsByName(name)) {
jlahoda@4103
  3755
            if (sym.isStatic() &&
jlahoda@4408
  3756
                importAccessible(sym, packge) &&
jlahoda@4103
  3757
                sym.isMemberOf(origin, types)) {
jlahoda@4103
  3758
                return true;
jlahoda@4103
  3759
            }
jlahoda@4103
  3760
        }
jlahoda@4103
  3761
jlahoda@4103
  3762
        return false;
jlahoda@4103
  3763
    }
jlahoda@4103
  3764
jlahoda@4103
  3765
    // is the sym accessible everywhere in packge?
jlahoda@4408
  3766
    public boolean importAccessible(Symbol sym, PackageSymbol packge) {
jlahoda@4408
  3767
        try {
jlahoda@4408
  3768
            int flags = (int)(sym.flags() & AccessFlags);
jlahoda@4408
  3769
            switch (flags) {
jlahoda@4408
  3770
            default:
jlahoda@4408
  3771
            case PUBLIC:
jlahoda@4408
  3772
                return true;
jlahoda@4408
  3773
            case PRIVATE:
jlahoda@4408
  3774
                return false;
jlahoda@4408
  3775
            case 0:
jlahoda@4408
  3776
            case PROTECTED:
jlahoda@4408
  3777
                return sym.packge() == packge;
jlahoda@4408
  3778
            }
jlahoda@4408
  3779
        } catch (ClassFinder.BadClassFile err) {
jlahoda@4408
  3780
            throw err;
jlahoda@4408
  3781
        } catch (CompletionFailure ex) {
jlahoda@4103
  3782
            return false;
jlahoda@4103
  3783
        }
jlahoda@4103
  3784
    }
jlahoda@4103
  3785
jlahoda@5433
  3786
    public void checkLeaksNotAccessible(Env<AttrContext> env, JCClassDecl check) {
jlahoda@5433
  3787
        JCCompilationUnit toplevel = env.toplevel;
jlahoda@5433
  3788
jlahoda@5433
  3789
        if (   toplevel.modle == syms.unnamedModule
jlahoda@5433
  3790
            || toplevel.modle == syms.noModule
jlahoda@5433
  3791
            || (check.sym.flags() & COMPOUND) != 0) {
jlahoda@5433
  3792
            return ;
jlahoda@5433
  3793
        }
jlahoda@5433
  3794
jlahoda@5433
  3795
        ExportsDirective currentExport = findExport(toplevel.packge);
jlahoda@5433
  3796
jlahoda@5433
  3797
        if (   currentExport == null //not exported
jlahoda@5433
  3798
            || currentExport.modules != null) //don't check classes in qualified export
jlahoda@5433
  3799
            return ;
jlahoda@5433
  3800
jlahoda@5433
  3801
        new TreeScanner() {
jlahoda@5433
  3802
            Lint lint = env.info.lint;
jlahoda@5433
  3803
            boolean inSuperType;
jlahoda@5433
  3804
jlahoda@5433
  3805
            @Override
jlahoda@5433
  3806
            public void visitBlock(JCBlock tree) {
jlahoda@5433
  3807
            }
jlahoda@5433
  3808
            @Override
jlahoda@5433
  3809
            public void visitMethodDef(JCMethodDecl tree) {
jlahoda@5433
  3810
                if (!isAPISymbol(tree.sym))
jlahoda@5433
  3811
                    return;
jlahoda@5433
  3812
                Lint prevLint = lint;
jlahoda@5433
  3813
                try {
jlahoda@5433
  3814
                    lint = lint.augment(tree.sym);
jlahoda@5433
  3815
                    if (lint.isEnabled(LintCategory.EXPORTS)) {
jlahoda@5433
  3816
                        super.visitMethodDef(tree);
jlahoda@5433
  3817
                    }
jlahoda@5433
  3818
                } finally {
jlahoda@5433
  3819
                    lint = prevLint;
jlahoda@5433
  3820
                }
jlahoda@5433
  3821
            }
jlahoda@5433
  3822
            @Override
jlahoda@5433
  3823
            public void visitVarDef(JCVariableDecl tree) {
jlahoda@5433
  3824
                if (!isAPISymbol(tree.sym) && tree.sym.owner.kind != MTH)
jlahoda@5433
  3825
                    return;
jlahoda@5433
  3826
                Lint prevLint = lint;
jlahoda@5433
  3827
                try {
jlahoda@5433
  3828
                    lint = lint.augment(tree.sym);
jlahoda@5433
  3829
                    if (lint.isEnabled(LintCategory.EXPORTS)) {
jlahoda@5433
  3830
                        scan(tree.mods);
jlahoda@5433
  3831
                        scan(tree.vartype);
jlahoda@5433
  3832
                    }
jlahoda@5433
  3833
                } finally {
jlahoda@5433
  3834
                    lint = prevLint;
jlahoda@5433
  3835
                }
jlahoda@5433
  3836
            }
jlahoda@5433
  3837
            @Override
jlahoda@5433
  3838
            public void visitClassDef(JCClassDecl tree) {
jlahoda@5433
  3839
                if (tree != check)
jlahoda@5433
  3840
                    return ;
jlahoda@5433
  3841
jlahoda@5433
  3842
                if (!isAPISymbol(tree.sym))
jlahoda@5433
  3843
                    return ;
jlahoda@5433
  3844
jlahoda@5433
  3845
                Lint prevLint = lint;
jlahoda@5433
  3846
                try {
jlahoda@5433
  3847
                    lint = lint.augment(tree.sym);
jlahoda@5433
  3848
                    if (lint.isEnabled(LintCategory.EXPORTS)) {
jlahoda@5433
  3849
                        scan(tree.mods);
jlahoda@5433
  3850
                        scan(tree.typarams);
jlahoda@5433
  3851
                        try {
jlahoda@5433
  3852
                            inSuperType = true;
jlahoda@5433
  3853
                            scan(tree.extending);
jlahoda@5433
  3854
                            scan(tree.implementing);
jlahoda@5433
  3855
                        } finally {
jlahoda@5433
  3856
                            inSuperType = false;
jlahoda@5433
  3857
                        }
jlahoda@5433
  3858
                        scan(tree.defs);
jlahoda@5433
  3859
                    }
jlahoda@5433
  3860
                } finally {
jlahoda@5433
  3861
                    lint = prevLint;
jlahoda@5433
  3862
                }
jlahoda@5433
  3863
            }
jlahoda@5433
  3864
            @Override
jlahoda@5433
  3865
            public void visitTypeApply(JCTypeApply tree) {
jlahoda@5433
  3866
                scan(tree.clazz);
jlahoda@5433
  3867
                boolean oldInSuperType = inSuperType;
jlahoda@5433
  3868
                try {
jlahoda@5433
  3869
                    inSuperType = false;
jlahoda@5433
  3870
                    scan(tree.arguments);
jlahoda@5433
  3871
                } finally {
jlahoda@5433
  3872
                    inSuperType = oldInSuperType;
jlahoda@5433
  3873
                }
jlahoda@5433
  3874
            }
jlahoda@5433
  3875
            @Override
jlahoda@5433
  3876
            public void visitIdent(JCIdent tree) {
jlahoda@5433
  3877
                Symbol sym = TreeInfo.symbol(tree);
jlahoda@5433
  3878
                if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR)) {
jlahoda@5433
  3879
                    checkVisible(tree.pos(), sym, toplevel.packge, inSuperType);
jlahoda@5433
  3880
                }
jlahoda@5433
  3881
            }
jlahoda@5433
  3882
jlahoda@5433
  3883
            @Override
jlahoda@5433
  3884
            public void visitSelect(JCFieldAccess tree) {
jlahoda@5433
  3885
                Symbol sym = TreeInfo.symbol(tree);
jlahoda@5433
  3886
                Symbol sitesym = TreeInfo.symbol(tree.selected);
jlahoda@5433
  3887
                if (sym.kind == TYP && sitesym.kind == PCK) {
jlahoda@5433
  3888
                    checkVisible(tree.pos(), sym, toplevel.packge, inSuperType);
jlahoda@5433
  3889
                } else {
jlahoda@5433
  3890
                    super.visitSelect(tree);
jlahoda@5433
  3891
                }
jlahoda@5433
  3892
            }
jlahoda@5433
  3893
jlahoda@5433
  3894
            @Override
jlahoda@5433
  3895
            public void visitAnnotation(JCAnnotation tree) {
jlahoda@5433
  3896
                if (tree.attribute.type.tsym.getAnnotation(java.lang.annotation.Documented.class) != null)
jlahoda@5433
  3897
                    super.visitAnnotation(tree);
jlahoda@5433
  3898
            }
jlahoda@5433
  3899
jlahoda@5433
  3900
        }.scan(check);
jlahoda@5433
  3901
    }
jlahoda@5433
  3902
        //where:
jlahoda@5433
  3903
        private ExportsDirective findExport(PackageSymbol pack) {
jlahoda@5433
  3904
            for (ExportsDirective d : pack.modle.exports) {
jlahoda@5433
  3905
                if (d.packge == pack)
jlahoda@5433
  3906
                    return d;
jlahoda@5433
  3907
            }
jlahoda@5433
  3908
jlahoda@5433
  3909
            return null;
jlahoda@5433
  3910
        }
jlahoda@5433
  3911
        private boolean isAPISymbol(Symbol sym) {
jlahoda@5433
  3912
            while (sym.kind != PCK) {
jlahoda@5433
  3913
                if ((sym.flags() & Flags.PUBLIC) == 0 && (sym.flags() & Flags.PROTECTED) == 0) {
jlahoda@5433
  3914
                    return false;
jlahoda@5433
  3915
                }
jlahoda@5433
  3916
                sym = sym.owner;
jlahoda@5433
  3917
            }
jlahoda@5433
  3918
            return true;
jlahoda@5433
  3919
        }
jlahoda@5433
  3920
        private void checkVisible(DiagnosticPosition pos, Symbol what, PackageSymbol inPackage, boolean inSuperType) {
jlahoda@5433
  3921
            if (!isAPISymbol(what) && !inSuperType) { //package private/private element
jlahoda@5433
  3922
                log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessible(kindName(what), what, what.packge().modle));
jlahoda@5433
  3923
                return ;
jlahoda@5433
  3924
            }
jlahoda@5433
  3925
jlahoda@5433
  3926
            PackageSymbol whatPackage = what.packge();
jlahoda@5433
  3927
            ExportsDirective whatExport = findExport(whatPackage);
jlahoda@5433
  3928
            ExportsDirective inExport = findExport(inPackage);
jlahoda@5433
  3929
jlahoda@5433
  3930
            if (whatExport == null) { //package not exported:
jlahoda@5433
  3931
                log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleUnexported(kindName(what), what, what.packge().modle));
jlahoda@5433
  3932
                return ;
jlahoda@5433
  3933
            }
jlahoda@5433
  3934
jlahoda@5433
  3935
            if (whatExport.modules != null) {
jlahoda@5433
  3936
                if (inExport.modules == null || !whatExport.modules.containsAll(inExport.modules)) {
jlahoda@5433
  3937
                    log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleUnexportedQualified(kindName(what), what, what.packge().modle));
jlahoda@5433
  3938
                }
jlahoda@5433
  3939
            }
jlahoda@5433
  3940
jlahoda@5433
  3941
            if (whatPackage.modle != inPackage.modle && whatPackage.modle != syms.java_base) {
alanb@5550
  3942
                //check that relativeTo.modle requires transitive what.modle, somehow:
jlahoda@5433
  3943
                List<ModuleSymbol> todo = List.of(inPackage.modle);
jlahoda@5433
  3944
jlahoda@5433
  3945
                while (todo.nonEmpty()) {
jlahoda@5433
  3946
                    ModuleSymbol current = todo.head;
jlahoda@5433
  3947
                    todo = todo.tail;
jlahoda@5433
  3948
                    if (current == whatPackage.modle)
jlahoda@5433
  3949
                        return ; //OK
jlahoda@5433
  3950
                    for (RequiresDirective req : current.requires) {
alanb@5550
  3951
                        if (req.isTransitive()) {
jlahoda@5433
  3952
                            todo = todo.prepend(req.module);
jlahoda@5433
  3953
                        }
jlahoda@5433
  3954
                    }
jlahoda@5433
  3955
                }
jlahoda@5433
  3956
alanb@5550
  3957
                log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleNotRequiredTransitive(kindName(what), what, what.packge().modle));
jlahoda@5433
  3958
            }
jlahoda@5433
  3959
        }
alanb@5580
  3960
alanb@5580
  3961
    void checkModuleExists(final DiagnosticPosition pos, ModuleSymbol msym) {
alanb@5580
  3962
        if (msym.kind != MDL) {
mcimadamore@5585
  3963
            deferredLintHandler.report(() -> {
mcimadamore@5585
  3964
                if (lint.isEnabled(LintCategory.MODULE))
mcimadamore@5585
  3965
                    log.warning(LintCategory.MODULE, pos, Warnings.ModuleNotFound(msym));
alanb@5580
  3966
            });
alanb@5580
  3967
        }
alanb@5580
  3968
    }
alanb@5580
  3969
jjg@5728
  3970
    void checkPackageExistsForOpens(final DiagnosticPosition pos, PackageSymbol packge) {
jjg@5728
  3971
        if (packge.members().isEmpty() &&
jjg@5728
  3972
            ((packge.flags() & Flags.HAS_RESOURCE) == 0)) {
jjg@5728
  3973
            deferredLintHandler.report(() -> {
jjg@5728
  3974
                if (lint.isEnabled(LintCategory.OPENS))
jjg@5728
  3975
                    log.warning(pos, Warnings.PackageEmptyOrNotFound(packge));
jjg@5728
  3976
            });
jjg@5728
  3977
        }
jjg@5728
  3978
    }
jjg@5728
  3979
jlahoda@5902
  3980
    void checkModuleRequires(final DiagnosticPosition pos, final RequiresDirective rd) {
jlahoda@5902
  3981
        if ((rd.module.flags() & Flags.AUTOMATIC_MODULE) != 0) {
jlahoda@5902
  3982
            deferredLintHandler.report(() -> {
jlahoda@5902
  3983
                if (rd.isTransitive() && lint.isEnabled(LintCategory.REQUIRES_TRANSITIVE_AUTOMATIC)) {
jlahoda@5902
  3984
                    log.warning(pos, Warnings.RequiresTransitiveAutomatic);
jlahoda@5902
  3985
                } else if (lint.isEnabled(LintCategory.REQUIRES_AUTOMATIC)) {
jlahoda@5902
  3986
                    log.warning(pos, Warnings.RequiresAutomatic);
jlahoda@5902
  3987
                }
jlahoda@5902
  3988
            });
jlahoda@5902
  3989
        }
jlahoda@5902
  3990
    }
jlahoda@5902
  3991
duke@0
  3992
}