/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/** This is the main context-dependent analysis phase in GJC. It
* encompasses name resolution, type checking and constant folding as
* subtasks. Some subtasks involve auxiliary classes.
* @see Check
* @see Resolve
* @see ConstFold
* @see Infer
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
return instance;
}
}
/** Switch: relax some constraints for retrofit mode.
*/
boolean relax;
/** Switch: support generics?
*/
boolean allowGenerics;
/** Switch: allow variable-arity methods.
*/
boolean allowVarargs;
/** Switch: support enums?
*/
boolean allowEnums;
/** Switch: support boxing and unboxing?
*/
boolean allowBoxing;
/** Switch: support covariant result types?
*/
boolean allowCovariantReturns;
/** Switch: allow references to surrounding object from anonymous
* objects during constructor call?
*/
boolean allowAnonOuterThis;
/** Switch: generates a warning if diamond can be safely applied
* to a given new expression
*/
boolean findDiamonds;
/**
*/
static final boolean allowDiamondFinder = true;
/**
* Switch: warn about use of variable before declaration?
* RFE: 6425594
*/
boolean useBeforeDeclarationWarning;
/**
* Switch: allow strings in switch?
*/
boolean allowStringsInSwitch;
/**
* Switch: name of source level; used for error reporting.
*/
/** Check kind and type of given tree against protokind and prototype.
* If check succeeds, store type in tree and return it.
* If check fails, store errType in tree and return it.
* No checks are performed if the prototype is a method type.
* It is not necessary in this case since we know that kind and type
* are correct.
*
* @param tree The tree whose kind and type is checked
* @param owntype The computed type of the tree
* @param ownkind The computed kind of the tree
* @param pkind The expected kind (or: protokind) of the tree
* @param pt The expected type (or: prototype) of the tree
*/
} else {
}
}
return owntype;
}
/** Is given blank final variable assignable, i.e. in a scope where it
* may be assigned to even though it is final?
* @param v The blank final variable.
* @param env The current environment.
*/
// owner refers to the innermost variable, method or
// initializer block declaration at this point.
return
||
&&
&&
}
/** Check that variable can be assigned to.
* @param pos The current source code position.
* @param v The assigned varaible
* @param base If the variable is referred to in a Select, the part
* to the left of the `.', null otherwise.
* @param env The current environment.
*/
||
isAssignableAsBlankFinal(v, env)))) {
if (v.isResourceVariable()) { //TWR resource
} else {
}
v.flags_field &= ~EFFECTIVELY_FINAL;
}
}
/** Does tree represent a static reference to an identifier?
* It is assumed that tree is either a SELECT or an IDENT.
* We have to weed out selects from non-type names here.
* @param tree The candidate tree.
*/
return false;
}
}
return true;
}
/** Is this symbol a type?
*/
}
/** The current `this' symbol.
* @param env The current environment.
*/
}
/** Attribute a parsed identifier.
* @param tree Parsed identifier name
* @param topLevel The toplevel to use
*/
}
// where
return site;
} else {
}
}
}
}
}
}
try {
} catch (BreakAttr b) {
return b.env;
} catch (AssertionError ae) {
} else {
throw ae;
}
} finally {
}
return env;
}
try {
} catch (BreakAttr b) {
return b.env;
} catch (AssertionError ae) {
} else {
throw ae;
}
} finally {
}
return env;
}
}
}
/* ************************************************************************
* Visitor methods
*************************************************************************/
/** Visitor argument: the current environment.
*/
/** Visitor argument: the currently expected proto-kind.
*/
int pkind;
/** Visitor argument: the currently expected proto-type.
*/
/** Visitor argument: the error key to be generated when a type error occurs
*/
/** Visitor result: the computed type.
*/
/** Visitor method: attribute a tree, catching any completion failure
* exceptions. Return the tree's type.
*
* @param tree The tree to be visited.
* @param env The environment visitor argument.
* @param pkind The protokind visitor argument.
* @param pt The prototype visitor argument.
*/
}
try {
return result;
} catch (CompletionFailure ex) {
} finally {
this.errKey = prevErrKey;
}
}
/** Derived visitor method: attribute an expression tree.
*/
}
}
/** Derived visitor method: attribute an expression tree with
* no constraints on the computed type.
*/
}
/** Derived visitor method: attribute a type tree.
*/
return result;
}
/** Derived visitor method: attribute a type tree.
*/
return result;
}
/** Derived visitor method: attribute a statement or definition tree.
*/
}
/** Attribute a list of expressions, returning a list of types.
*/
}
/** Attribute a list of statements, returning nothing.
*/
}
/** Attribute the arguments in a method call, returning a list of types.
*/
}
/** Attribute a type argument list, returning a list of types.
* Caller is responsible for calling checkRefTypes.
*/
}
/** Attribute a type argument list, returning a list of types.
* Check that all the types are references.
*/
}
/**
* Attribute type variables (of generic classes or methods).
* Compound types are attributed later in attribBounds.
* @param typarams the type variables to enter
* @param env the current environment
*/
} else {
// if no bounds are given, assume a single bound of
// java.lang.Object.
}
}
}
}
}
}
}
/**
* Attribute the type references in a list of annotations.
*/
}
}
/**
* Attribute a "lazy constant value".
* @param env The env for the const value
* @param initializer The initializer for the const value
* @param type The expected type, or null
* @see VarSymbol#setlazyConstValue
*/
// in case no lint value has been set up for this env, scan up
// env stack looking for smallest enclosing env for which it is set.
// Having found the enclosing lint value, we can initialize the lint value for this class
// ... but ...
// There's a problem with evaluating annotations in the right order, such that
// env.info.enclVar.attributes_field might not yet have been evaluated, and so might be
// null. In that case, calling augment will throw an NPE. To avoid this, for now we
// revert to the jdk 6 behavior and ignore the (unevaluated) attributes.
else
env.info.lint = lintEnv.info.lint.augment(env.info.enclVar.attributes_field, env.info.enclVar.flags());
try {
else
return null;
} finally {
}
}
/** Attribute type reference in an `extends' or `implements' clause.
* Supertypes of anonymous inner classes are usually already attributed.
*
* @param tree The tree making up the type reference.
* @param env The environment current at the reference.
* @param classExpected true if only a class is expected here.
* @param interfaceExpected true if only an interface is expected here.
*/
boolean classExpected,
boolean interfaceExpected,
boolean checkExtensible) {
}
boolean classExpected,
boolean interfaceExpected,
boolean checkExtensible) {
if (t.isErroneous())
return t;
// check that type variable is already visible
if (t.getUpperBound() == null) {
return types.createErrorType(t);
}
} else {
}
// return errType is necessary since otherwise there might
// be undetected cycles which cause attribution to loop
return types.createErrorType(t);
} else if (checkExtensible &&
return types.createErrorType(t);
}
if (checkExtensible &&
"cant.inherit.from.final", t.tsym);
}
return t;
}
}
// Local classes have not been entered yet, so we need to do it now:
if (c == null) {
// exit in case something drastic went wrong during enter.
} else {
// make sure class has been completed:
c.complete();
// If this class appears as an anonymous class
// in a superclass constructor call where
// no explicit outer instance is given,
// disable implicit outer instance from being passed.
// (This would be an illegal access to "this before super").
{
c.flags_field |= NOOUTERTHIS;
}
}
}
try {
// If we override any other methods, check that we do so properly.
// JLS ???
if (m.isStatic()) {
} else {
}
// Create a new environment with local scope
// for attributing the method.
// Enter all type parameters into the local method scope.
"intf.annotation.members.cant.have.params");
// Attribute all value parameters.
}
// Check that type parameters are well-formed.
// Check that result type is well-formed.
// annotation method checks
// annotation method cannot have throws clause
"throws.not.allowed.in.intf.annotation");
}
// annotation method cannot declare type-parameters
"intf.annotation.members.cant.have.type.params");
}
// validate annotation method's return type (could be an annotation type)
// ensure that annotation method does not clash with members of Object/Annotation
// if default value is an annotation, check it is a well-formed
// annotation value (e.g. no duplicate values, no missing values, etc.)
}
}
// Empty bodies are only allowed for
// abstract, native, or interface methods, or for methods
// in a retrofit signature class.
!relax)
"default.allowed.in.intf.annotation.member");
}
} else {
// Add an implicit super() call unless an explicit call to
// super(...) or this(...) is given
// or we are compiling class java.lang.Object.
false));
// enum constructors are not allowed to call super
// directly, so make sure there aren't any super calls
// in enum constructors, except in the compiler
// generated one.
"call.to.super.not.allowed.in.enum.ctor",
}
}
// Attribute method body.
}
}
finally {
}
}
// Local variables have not been entered yet, so we need to do it now:
// parameters have already been entered
} else {
}
}
// Check that the variable's declared type is well-formed.
try {
// In this case, `v' is final. Ensure that it's initializer is
// evaluated.
v.getConstValue(); // ensure initializer is evaluated
} else {
// Attribute initializer in a new environment
// with the declared variable as owner.
// Check that initializer conforms to variable's declared type.
// In order to catch self-references, we set the variable's
// declaration position to maximal possible value, effectively
// marking the variable as undefined.
}
}
}
finally {
}
}
}
// Block is a static or instance initializer;
// let the owner of the environment be a freshly
// created BLOCK-method.
} else {
// Create a new local environment with a local scope.
}
}
}
}
}
// or perhaps expr implements Iterable<T>?
"foreach.not.applicable.to.type",
} else {
}
}
}
// Check that label is not used in an enclosing statement
break;
}
}
}
boolean enumSwitch =
allowEnums &&
boolean stringSwitch = false;
if (allowStringsInSwitch) {
stringSwitch = true;
} else {
}
}
if (!enumSwitch && !stringSwitch)
// Attribute all cases and
// check that there are no duplicate case labels or default clauses.
boolean hasDefault = false; // Is there a default label?
if (enumSwitch) {
}
} else {
} else {
}
}
}
} else if (hasDefault) {
} else {
hasDefault = true;
}
}
}
// where
/** Add any variables defined in stats to the switch scope. */
}
}
// where
/** Return the selected enumeration constant symbol, or null. */
}
? null : s;
}
}
return null;
}
}
// Create a new local environment with a local
// Create a nested environment for attributing the try block if needed
// Attribute resource declarations
//check that resource type cannot throw InterruptedException
} else {
}
}
// Attribute body
if (isTryWithResource)
// Attribute catch clauses
if (TreeInfo.isMultiCatch(c)) {
//multi-catch parameter is implicitly marked as final
}
}
}
// Attribute finalizer
}
if (!resource.isErroneous() &&
try {
log.deferDiagnostics = true;
env,
}
finally {
}
}
}
}
}
//where
/** Compute the type of a conditional expression, after
* checking that it exists. See Spec 15.25.
*
* @param pos The source position to be used for
* error diagnostics.
* @param condtype The type of the expression's condition.
* @param thentype The type of the expression's then-part.
* @param elsetype The type of the expression's else-part.
*/
// If condition and both arms are numeric constants,
// evaluate at compile-time.
: ctype;
}
/** Compute the type of a conditional expression, after
* checking that it exists. Does not take into
* account the special case where condition and both arms
* are constants.
*
* @param pos The source position to be used for error
* diagnostics.
* @param condtype The type of the expression's condition.
* @param thentype The type of the expression's then-part.
* @param elsetype The type of the expression's else-part.
*/
// If same type, that is the result
// Otherwise, if both arms can be converted to a numeric
// type, return the least numeric type that fits both arms
// (i.e. return larger of the two, or return int if one
// arm is short, the other is char).
// If one arm has an integer subrange type (i.e., byte,
// short, or char), and the other is an integer constant
// that fits into the subrange, return the subrange type.
return thenUnboxed.baseType();
return elseUnboxed.baseType();
return candidate;
}
}
// Those were all the cases that could result in a primitive
if (allowBoxing) {
if (thentype.isPrimitive())
if (elsetype.isPrimitive())
}
}
// both are known to be reference types. The result is
// lub(thentype,elsetype). This cannot fail, as it will
// always be possible to infer "Object" if nothing better.
}
}
//a fresh environment is required for 292 inference to work properly ---
//see Infer.instantiatePolymorphicSignatureInstance()
}
}
}
//where
/** Return the target of a break or continue statement, if it exists,
* report an error if not.
* Note: The target of a labelled break or continue is the
* (non-labelled) statement tree referred to by the label,
* not the tree representing the labelled statement itself.
*
* @param pos The position to be used for error diagnostics
* @param tag The tag of the jump statement. This is either
* Tree.BREAK or Tree.CONTINUE.
* @param label The label of the jump statement, or null if no
* label is given.
* @param env The environment current at the jump statement.
*/
int tag,
// Search environments outwards from the point of jump.
LOOP:
// If jump is a continue, check that target is a loop.
// Found labelled statement target, now go inwards
// to next non-labelled tree.
} else {
return labelled;
}
}
break;
case JCTree.FOREACHLOOP:
break;
break;
break LOOP;
default:
}
}
else
return null;
}
// Check that there is an enclosing method which is
// nested within than the enclosing class.
} else {
// Attribute return expression, if it exists, and check that
// it conforms to result type of enclosing method.
"cant.ret.val.from.meth.decl.void");
} else {
}
}
}
}
}
}
/** Visitor method for method invocations.
* NOTE: The method part of an application will have in its type field
* the return type of the method, not the method's type itself!
*/
// The local environment of a method application is
// a new environment nested in the current one.
// The types of the actual method arguments.
// The types of the actual method type arguments.
boolean isConstructorCall =
if (isConstructorCall) {
// We are seeing a ...this(...) or ...super(...) call.
// Check that this is the first statement in a constructor.
// Record the fact
// that this is a constructor call (using isSelfCall).
// Attribute arguments, yielding list of argument types.
// Variable `site' points to the class in which the called
// constructor is defined.
} else {
}
}
// we are calling a nested class
// We are seeing a prefixed call, of the form
// <expr>.super(...).
// Check that the prefix expression conforms
// to the outer instance type of the class.
encl));
// qualifier omitted; check for existence
// of an appropriate implicit qualifier.
}
}
// if we're calling a java.lang.Enum constructor,
// prefix the implicit String and int parameters
// Resolve the called constructor under the assumption
// that we are referring to a superclass instance of the
// current instance (JLS ???).
// Set method symbol to resolved constructor...
// ...and check that it is legal in the current context.
// (this will also set the tree's type)
}
// Otherwise, `site' is an error type and we do nothing
}
} else {
// Otherwise, we are seeing a regular method call.
// Attribute the arguments, yielding list of argument types, ...
// ... and attribute the method using as a prototype a methodtype
// whose formal argument types is exactly the list of actual
// arguments (this will also set the method symbol).
// Compute the result type.
throw new AssertionError(mtype);
// as a special case, array.clone() has a result that is
// the same as static type of the array being cloned
// as a special case, x.getClass() has type Class<? extends |X|>
if (allowGenerics &&
restype = new
syms.boundClass)),
}
// Check that value of resulting type is admissible in the
// current context. Also, capture the return type
}
}
//where
/** Check that given application node appears as first statement
* in a constructor call.
* @param tree The application node
* @param env The environment current at the application.
*/
return true;
}
return false;
}
/** Obtain a method type with given argument types.
*/
}
// The local environment of a class creation is
// a new environment nested in the current one.
// The anonymous inner class definition of the new expression,
// if one is defined by it.
// If enclosing class is given, attribute it, and
// complete class name to be fully qualified
: clazz;
// We are seeing a qualified new, of the form
// <expr>.new C <...> (...) ...
// In this case, we let clazz stand for the name of the
// allocated class C prefixed with the type of the qualifier
// expression, so that we can
// resolve it with standard techniques later. I.e., if
// <expr> has type T, then <expr>.new C <...> (...)
// yields a clazz T.C.
else
}
// Attribute clazz expression and store
// symbol + type back into the attributed tree.
// We have to work in this case to store
// symbol + type back into the attributed tree.
if (!clazztype.isErroneous()) {
}
}
// Check for the existence of an apropos outer instance
}
// Attribute constructor arguments.
} else if (allowDiamondFinder &&
!clazztype.isErroneous() &&
findDiamonds) {
try {
//disable diamond-related diagnostics
log.deferDiagnostics = true;
tree,
}
finally {
}
!inferred.isErroneous() &&
"diamond.redundant.args" :
"diamond.redundant.args.1";
}
}
// If we have made no mistakes in the class type...
// Enums may not be instantiated except implicitly
if (allowEnums &&
// Check that class is not abstract
// Check that no constructor arguments are given to
// anonymous classes implementing an interface
if (!typeargtypes.isEmpty())
// Error recovery: pretend no arguments were supplied.
}
// Resolve the called constructor under the assumption
// that we are referring to a superclass instance of the
// current instance (JLS ???).
else {
//the following code alters some of the fields in the current
//AttrContext - hence, the current context must be dup'ed in
//order to avoid downstream failures
}
// We are seeing an anonymous class instance creation.
// In this case, the class instance creation
// expression
//
// E.new <typeargs1>C<typargs2>(args) { ... }
//
// is represented internally as
//
// E . new <typeargs1>C<typargs2>(args) ( class <empty-name> { ... } ) .
//
// This expression is then *transformed* as follows:
//
// (1) add a STATIC flag to the class definition
// if the current environment is static
// (2) add an extends or implements clause
// (3) add a constructor.
//
// For instance, if C is a class, and ET is the type of E,
// the expression
//
// E.new <typeargs1>C<typargs2>(args) { ... }
//
// is translated to (where X is a fresh name and typarams is the
// parameter list of the super constructor):
//
// new <typeargs1>X(<*nullchk*>E, args) where
// X extends C<typargs2> {
// <typarams> X(ET e, args) {
// e.<typeargs1>super(args)
// }
// ...
// }
} else {
}
// If an outer instance is given,
// prefix it to the constructor arguments
// and delete it from the new expression
}
// Reassign clazztype and recompute constructor.
typeargtypes, true, useVarargs);
}
else {
}
}
}
}
if (clazztype.isErroneous() ||
clazztype.isInterface() ||
mapping == erroneousMapping) {
//if the type of the instance creation expression is erroneous,
//or if it's an interface, or if something prevented us to form a valid
//mapping, return the (possibly erroneous) type unchanged
return clazztype;
}
//dup attribution environment and augment the set of inference variables
//if the type of the instance creation expression is a class type
//apply method resolution inference (JLS 15.12.2.7). The return type
//of the resolved constructor will be a partially instantiated type
try {
} finally {
}
} else {
}
//if the resolved constructor's return type has some uninferred
//type-variables, infer them using the expected type and declared
//bounds (JLS 15.12.2.8).
try {
//an error occurred while inferring uninstantiated type-variables
"cant.apply.diamond.1",
ex.diagnostic);
}
}
true);
}
/** Creates a synthetic scope containing fake generic constructors.
* Assuming that the original scope contains a constructor of the kind:
* Foo(X x, Y y), where X,Y are class type-variables declared in Foo,
* the synthetic scope is added a generic constructor of the kind:
* <X,Y>Foo<X,Y>(X x, Y y). This is crucial in order to enable diamond
* inference. The inferred return type of the synthetic constructor IS
* the inferred type for the diamond operator.
*/
return erroneousMapping;
}
//for each constructor in the original scope, create a synthetic constructor
//whose return type is the type of the class in which the constructor is
//declared, and insert it into the new scope.
e = e.next()) {
}
return mapping;
}
/** Make an attributed null check tree.
*/
// optimization: X.this is never null; skip null check
return tree;
}
}
} else {
// we are seeing an untyped aggregate { ... }
// this is allowed only if the prototype is an array
} else {
pt);
}
}
}
}
}
}
}
// Attribute arguments.
// Find operator.
!owntype.isErroneous() &&
!operand.isErroneous()) {
operand);
owntype);
}
}
// Attribute arguments.
// Find operator.
!argtype.isErroneous()) {
// If the argument is constant, fold it.
// Remove constant types from arguments to
// conserve space. The parser will fold concatenations
// of string literals; the code here also
// gets rid of intermediate results when some of the
// operands are constant identifiers.
}
}
}
}
}
// Attribute arguments.
// Find operator.
!left.isErroneous() &&
!right.isErroneous()) {
left,
right);
// If both arguments are constants, fold them.
// Remove constant types from arguments to
// conserve space. The parser will fold concatenations
// of string literals; the code here also
// gets rid of intermediate results when some of the
// operands are constant identifiers.
}
}
}
}
// Check that argument types of a reference ==, != are
// castable to each other, (JLS???).
}
}
}
}
//a fresh environment is required for 292 inference to work properly ---
//see Infer.instantiatePolymorphicSignatureInstance()
}
}
}
boolean varArgs = false;
// Find symbol
// If we are looking for a method, the prototype `pt' will be a
// method type with the type of the call's arguments as parameters.
} else {
}
// (1) Also find the environment current for the class where
// sym is defined (`symEnv').
// Only for pre-tiger versions (1.4 and earlier):
// (2) Also determine whether we access symbol out of an anonymous
// class in a this or super call. This is illegal for instance
// members since such classes don't carry a this$n link.
// (`noOuterThisPath').
boolean noOuterThisPath = false;
// Find environment in which identifier is defined.
}
}
// If symbol is a variable, ...
// ..., evaluate its initializer, if it has one, and check for
// illegal forward reference.
// If symbol is a local variable accessed from an embedded
// inner class check that it is final.
"local.var.accessed.from.icls.needs.final",
v);
}
// If we are expecting a variable (as opposed to a value), check
// that the variable is assignable in the current environment.
}
// In a constructor body,
// if symbol is a field or instance method, check that it is
// not accessed before the supertype constructor is called.
}
// If the found symbol is inaccessible, then it is
// accessed through an enclosing instance. Locate this
// enclosing instance:
}
}
// Determine the expected kind of the qualifier expression.
int skind = 0;
{
} else {
}
// Attribute the qualifier expression, and determine its symbol (if any).
// don't allow T.class T[].class, etc
return;
}
}
// If qualifier symbol is a type or `super', assert `selectSuper'
// for the selection. This is relevant for determining whether
// protected symbols are accessible.
// If selected expression is polymorphic, strip
// type parameters and remember in env.info.tvars, so that
// they can be added later (in Attr.checkId and Infer.instantiateMethod).
}
// Determine the symbol represented by the selection.
}
}
// If that symbol is a variable, ...
// ..., evaluate its initializer, if it has one, and check for
// illegal forward reference.
// If we are expecting a variable (as opposed to a value), check
// that the variable is assignable in the current environment.
}
}
// Disallow selecting a type from an expression
}
// If `C' is the currently compiled class, check that
// C.this' does not appear in a call to a super(...)
}
} else {
// Check if type-qualified fields or methods are static (JLS)
}
}
// If the qualified item is not a type and the selected item is static, report
// a warning. Make allowance for the class of an array type e.g. Object[].class)
}
// If we are selecting an instance member via a `super', ...
// Check that super-qualified symbols are not abstract (JLS)
// Determine argument types for site.
}
}
}
//where
/** Determine symbol referenced by a Select expression,
*
* @param tree The select tree.
* @param site The type of the selected expression,
* @param env The current environment.
* @param pt The current prototype.
* @param pkind The expected kind(s) of the Select expression.
*/
int pkind) {
}
int pkind) {
case PACKAGE:
case ARRAY:
case CLASS:
return rs.resolveQualifiedMethod(
// In this case, we have already made sure in
// visitSelect that qualifier expression is a type.
return new VarSymbol(
} else {
// We are seeing a plain identifier as selector.
return sym;
}
case WILDCARD:
throw new AssertionError(tree);
case TYPEVAR:
// Normally, site.getUpperBound() shouldn't be null.
// It should only happen during memberEnter/attribBase
// when determining the super type which *must* beac
// done before attributing the type variables. In
// other words, we are seeing this illegal program:
// class B<T> extends A<T.foo> {}
: null;
} else {
sym;
return sym;
}
case ERROR:
// preserve identifier names through errors
default:
// The qualifier expression is of a primitive type -- only
// .class is allowed for these.
// In this case, we have already made sure in Select that
// qualifier expression is a type.
return new VarSymbol(
} else {
}
}
}
/** Determine type of identifier or select expression and check that
* (1) the referenced symbol is not deprecated
* (2) the symbol's type is safe (@see checkSafe)
* (3) if symbol is a variable, check that its type and kind are
* compatible with the prototype and protokind.
* (4) if symbol is an instance field of a raw type,
* which is being assigned to, issue an unchecked warning if its
* type changes under erasure.
* (5) if symbol is an instance method of a raw type, issue an
* unchecked warning if its argument types change under erasure.
* If checks succeed:
* If symbol is a constant, return its constant type
* else if symbol is a method, return its result type
* otherwise return its type.
* Otherwise return errType.
*
* @param tree The syntax tree representing the identifier
* @param site If this is a select, the type of the selected
* expression, otherwise the type of the current class.
* @param sym The symbol representing the identifier.
* @param env The current environment.
* @param pkind The set of expected kinds.
* @param pt The expected type.
*/
int pkind,
boolean useVarargs) {
case TYP:
// For types, the computed type equals the symbol's type,
// except for two situations:
// (a) If the symbol's type is parameterized, erase it
// because no type parameters were given.
// We recover generic outer type later in visitTypeApply.
}
// (b) If the symbol's type is an inner class, then
// we have to interpret its outer type as a superclass
// of the site type. Example:
//
// class Tree<A> { class Visitor { ... } }
// class PointTree extends Tree<Point> { ... }
// ...PointTree.Visitor...
//
// Then the type of the last expression above is
// Tree<Point>.Visitor.
}
}
break;
case VAR:
// Test (4): if symbol is an instance field of a raw type,
// which is being assigned to, issue an unchecked warning if
// its type changes under erasure.
if (allowGenerics &&
if (s != null &&
s.isRaw() &&
"unchecked.assign.to.var",
v, s);
}
}
// The computed type of a variable is the type of the
// variable symbol, taken as a member of the site type.
}
}
// If the variable is a constant, record constant value in
// computed type.
}
break;
case MTH: {
break;
}
break;
default:
" in tree " + tree);
}
// Test (1): emit a `deprecation' warning if symbol is deprecated.
// (for constructors, the error was given when the constructor was
// resolved)
}
// Test (3): if symbol is a variable, check that its type and
// kind are compatible with the prototype and protokind.
}
/** Check that variable is initialized and evaluate the variable's
* initializer, if not yet done. Also check that variable is not
* referenced before it is defined.
* @param tree The tree making up the variable reference.
* @param env The current environment.
* @param v The variable's symbol.
*/
VarSymbol v,
boolean onlyWarning) {
// System.err.println(v + " " + ((v.flags() & STATIC) != 0) + " " +
// tree.pos + " " + v.pos + " " +
// Resolve.isStatic(env));//DEBUG
// A forward reference is diagnosed if the declaration position
// of the variable is greater than the current tree position
// and the tree and variable definition occur in the same class
// definition. Note that writes don't count as references.
// This check applies only to class and instance
// variables. Local variables follow different scope rules,
// and are subject to definite assignment checking.
"self.ref" : "forward.ref";
if (!onlyWarning || isStaticEnumField(v)) {
} else if (useBeforeDeclarationWarning) {
}
}
v.getConstValue(); // ensure initializer is evaluated
}
/**
* Check for illegal references to static members of enum. In
* an enum type, constructors and initializers may not
* reference its static members unless they are constant.
*
* @param tree The tree making up the variable reference.
* @param env The current environment.
* @param v The variable's symbol.
* @jls section 8.9 Enums
*/
// JLS:
//
// "It is a compile-time error to reference a static field
// of an enum type that is not a compile-time constant
// (15.28) from constructors, instance initializer blocks,
// or instance variable initializer expressions of that
// type. It is a compile-time error for the constructors,
// instance initializer blocks, or instance variable
// initializer expressions of an enum constant e to refer
// to itself or to an enum constant of the same type that
// is declared to the right of e."
if (isStaticEnumField(v)) {
return;
// See if the enclosing class is the enum (or a
// subclass thereof) declaring v. If not, this
// reference is OK.
return;
// If the reference isn't from an initializer, then
// the reference is OK.
return;
}
}
/** Is the given symbol a static, non-constant field of an Enum?
* Note: enum literals should not be regarded as such
*/
!Flags.isConstant(v) &&
}
/** Can the given symbol be the owner of code which forms part
* if class initialization? This is the case if the symbol is
* a type or field, or if the symbol is the synthetic method.
* owning a block.
*/
return
}
/**
* Check that method arguments conform to its instantation.
**/
boolean useVarargs) {
// Test (5): if symbol is an instance method of a raw type, issue
// an unchecked warning if its argument types change under erasure.
if (allowGenerics &&
"unchecked.call.mbr.of.raw.type",
sym, s);
}
}
// Compute the identifier's instantiated type.
// For methods, we need to compute the instance type by
// Resolve.instantiate from the symbol's type as well as
// any type arguments and value arguments.
noteWarner.clear();
site,
sym,
true,
// If this fails, something went wrong; we should not have
// found the identifier in the first place.
if (!pt.isErroneous())
"internal.error.cant.instantiate",
} else {
// System.out.println("call : " + env.tree);
// System.out.println("method : " + owntype);
// System.out.println("actuals: " + argtypes);
}
if (useVarargs) {
}
// non-varargs call to varargs method
varParam);
}
"unchecked.meth.invocation.applied",
}
if (useVarargs) {
}
break;
break;
default:
}
}
}
return owntype;
}
return;
if (formal.isCompound()
return;
if (false) {
// TODO: make assertConvertible work
+ " actual:" + actual
+ " formal: " + formal);
}
}
}
//where
/** Return the type of a literal with given type tag.
*/
}
}
}
/** Visitor method for parameterized types.
* Bound checking is left until later, since types are attributed
* before supertype structure is completely known
*/
// Attribute functor part of application and make sure it's a class.
// Attribute type parameters
while (a.nonEmpty()) {
a = a.tail;
f = f.tail;
}
// Compute the proper generic outer
clazzOuter = site;
}
}
} else {
} else {
}
}
}
}
if (!ctype.isErroneous()) {
//check that alternatives of a union type are pairwise
//unrelated w.r.t. subtyping
for (Type t : multicatchTypes) {
//assume 'a' <: 'b'
}
}
}
if (all_multicatchTypes != null)
} else {
if (all_multicatchTypes == null) {
}
}
}
}
}
if (a.bound.isErroneous())
return;
// accept class or interface or typevar as first bound.
if (b.isErroneous()) {
a.bound = b;
}
// if first bound was a typevar, do not accept further bounds.
"type.var.may.not.be.followed.by.other.bounds");
}
} else {
// if first bound was a class or interface, accept only interfaces
// as further bounds.
if (i.isErroneous())
a.bound = i;
}
}
}
// in case of multiple bounds ...
// ... the variable's bound is a class type flagged COMPOUND
// (see comment for TypeVar.bound).
// In this case, generate a class tree that represents the
// bound class, ...
} else {
}
// ... and attribute the bound class
c.flags_field |= UNATTRIBUTED;
}
}
//- System.err.println("visitWildcard("+tree+");");//DEBUG
}
}
}
/** Default visitor method for all other trees.
*/
throw new AssertionError();
}
/**
* Attribute an env for either a top level tree or class declaration.
*/
else
}
/**
* Attribute a top level tree. These trees are encountered when the
* package declaration has annotations.
*/
try {
} catch (CompletionFailure ex) {
}
}
/** Main method: attribute class definition associated with given class symbol.
* reporting completion failures at the given position.
* @param pos The source position at which completion errors are to be
* reported.
* @param c The class symbol whose definition will be attributed.
*/
try {
attribClass(c);
} catch (CompletionFailure ex) {
}
}
/** Attribute class definition associated with given class symbol.
* @param c The class symbol whose definition will be attributed.
*/
// Check for cycles in the inheritance graph, which can arise from
// ill-formed class files.
// First, attribute superclass.
// Next attribute owner, if it is a class.
}
// The previous operations might have attributed the current class
// if there was a cycle. So we test first whether the class is still
// UNATTRIBUTED.
c.flags_field &= ~UNATTRIBUTED;
// Get environment current at the point of class definition.
// The info.lint field in the envs stored in enter.typeEnvs is deliberately uninitialized,
// because the annotations were not available at the time the env was created. Therefore,
// we look up the environment chain for the first enclosing environment for which the
// lint value is set. Typically, this is the parent env, but might be further if there
// are any envs created as a result of TypeParameter nodes.
// Having found the enclosing lint value, we can initialize the lint value for this class
try {
// java.lang.Enum may not be subclassed by a non-enum
// Enums may not be extended by source-level classes
!target.compilerBootstrap(c)) {
}
attribClassBody(env, c);
} finally {
}
}
}
// nothing to do
}
/** Finish the attribution of a class. */
// Validate annotations
// Validate type parameters, supertype and interfaces.
if (!c.isAnonymous()) {
//already checked if anonymous
}
// If this is a non-abstract class, check that it has no abstract
// methods or unimplemented methods of an implemented interface.
if (!relax)
}
"cant.extend.intf.annotation");
"intf.annotation.cant.have.type.params");
} else {
// Check that all extended classes and interfaces
// are compatible (i.e. no two define methods with same arguments
// yet different return types). (JLS 8.4.6.3)
}
// Check that class does not import the same parameterized interface
// with two different argument lists.
}
// Check that a generic class doesn't extend Throwable
// Check that all methods which implement some
// method conform to the method they implement.
//check that a resource implementing AutoCloseable cannot throw InterruptedException
// Attribute declaration
// Check that declarations in inner classes are not static (JLS 8.1.2)
// Make an exception for static constants.
}
}
// Check for cycles among non-initial constructors.
// Check for cycles among annotation elements.
// Check for proper use of serialVersionUID
isSerializable(c) &&
}
}
// where
/** check if a class is a subtype of Serializable, if that is available. */
try {
}
catch (CompletionFailure e) {
return false;
}
}
/** Check that an appropriate serialVersionUID member is defined. */
// check for presence of serialVersionUID
return;
}
// check that it is static final
// check that it is long
// check constant
}
}
// <editor-fold desc="post-attribution visitor">
/**
* the compiler has encountered some errors (which might have ended up
* terminating attribution abruptly); if the compiler is used in fail-over
* mode (e.g. by an IDE) and the AST contains semantic errors, this routine
* prevents NPE to be progagated during subsequent compilation steps.
*/
}
}
}
if (tree instanceof JCExpression) {
}
}
}
}
}
super.visitSelect(that);
}
}
super.visitClassDef(that);
}
}
super.visitMethodDef(that);
}
}
super.visitVarDef(that);
}
}
}
super.visitNewClass(that);
}
super.visitAssignop(that);
}
super.visitBinary(that);
}
super.visitUnary(that);
}
}
// </editor-fold>
}