001    /* Copyright (c) 2005-2008, Torbjorn Ekman
002     * All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions are met:
006     *
007     * 1. Redistributions of source code must retain the above copyright notice,
008     * this list of conditions and the following disclaimer.
009     *
010     * 2. Redistributions in binary form must reproduce the above copyright notice,
011     * this list of conditions and the following disclaimer in the documentation
012     * and/or other materials provided with the distribution.
013     *
014     * 3. Neither the name of the copyright holder nor the names of its
015     * contributors may be used to endorse or promote products derived from this
016     * software without specific prior written permission.
017     *
018     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
022     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028     * POSSIBILITY OF SUCH DAMAGE.
029     */
030    
031    
032    aspect TypeCheck {
033      public void ASTNode.typeCheck() {
034      }
035    
036      syn boolean Expr.isVariable() = false;
037      eq AbstractDot.isVariable() = lastAccess().isVariable();
038      eq VarAccess.isVariable() = true;
039      eq ArrayAccess.isVariable() = true;
040      eq ParExpr.isVariable() = getExpr().isVariable();
041    
042      // 5.2
043      public void VariableDeclaration.typeCheck() {
044        if (hasInit()) {
045          TypeDecl source = getInit().type();
046          TypeDecl dest = type();
047          if (!source.assignConversionTo(dest, getInit())) {
048            errorf("can not assign variable %s of type %s a value of type %s",
049                name(), dest.typeName(), source.typeName());
050          }
051        }
052      }
053    
054      // 5.2
055      public void FieldDeclaration.typeCheck() {
056        if (hasInit()) {
057          TypeDecl source = getInit().type();
058          TypeDecl dest = type();
059          if (!source.assignConversionTo(dest, getInit())) {
060            errorf("can not assign field %s of type %s a value of type %s",
061                name(), dest.typeName(), source.typeName());
062          }
063        }
064      }
065    
066      // 5.2 Assignment Conversion
067      public void AssignSimpleExpr.typeCheck() {
068        if (!getDest().isVariable()) {
069          error("left hand side is not a variable");
070        } else if (!getSource().type().assignConversionTo(getDest().type(), getSource())
071            && !getSource().type().isUnknown()) {
072          errorf("can not assign %s of type %s a value of type %s",
073              getDest().prettyPrint(), getDest().type().typeName(), getSource().type().typeName());
074        }
075      }
076    
077      public void AssignExpr.typeCheck() {
078        if (!getDest().isVariable()) {
079          error("left hand side is not a variable");
080        } else {
081          TypeDecl source = getSource().type();
082          TypeDecl dest = getDest().type();
083          if (getSource().type().isPrimitive() && getDest().type().isPrimitive()) {
084            return;
085          }
086          errorf("can not assign %s of type %s a value of type %s",
087              getDest().prettyPrint(), getDest().type().typeName(), getSource().type().typeName());
088        }
089      }
090    
091      public void AssignMultiplicativeExpr.typeCheck() {
092        if (getSource().type().isBoolean() || getDest().type().isBoolean()) {
093          error("Multiplicative operators do not operate on boolean types");
094        }
095        super.typeCheck();
096      }
097    
098      public void AssignPlusExpr.typeCheck() {
099        if (!getDest().isVariable()) {
100          error("left hand side is not a variable");
101        } else if (getSource().type().isUnknown() || getDest().type().isUnknown()) {
102          return;
103        } else if (getDest().type().isString() && !(getSource().type().isVoid())) {
104          return;
105        } else if (getSource().type().isBoolean() || getDest().type().isBoolean()) {
106          error("Operator + does not operate on boolean types");
107        } else if (getSource().type().isPrimitive() && getDest().type().isPrimitive()) {
108          return;
109        } else
110          errorf("can not assign %s of type %s a value of type %s",
111              getDest().prettyPrint(), getDest().type().typeName(), getSource().type().typeName());
112      }
113      public void AssignMinusExpr.typeCheck() {
114        if (getSource().type().isBoolean() || getDest().type().isBoolean()) {
115          error("Operator - does not operate on boolean types");
116        }
117        super.typeCheck();
118      }
119    
120      public void AssignShiftExpr.typeCheck() {
121        if (!getSource().type().isIntegralType() || !getDest().type().isIntegralType()) {
122          error("Shift operators only operate on integral types");
123        }
124        super.typeCheck();
125      }
126    
127      public void AssignBitwiseExpr.typeCheck() {
128        TypeDecl source = getSource().type();
129        TypeDecl dest = getDest().type();
130        if (source.isIntegralType() && dest.isIntegralType()) {
131          super.typeCheck();
132        } else if (source.isBoolean() && dest.isBoolean()) {
133          super.typeCheck();
134        } else {
135          error("Operator only operates on integral and boolean types");
136        }
137      }
138    
139      // 5.3 Method Invocation Conversion
140      public void MethodAccess.typeCheck() {
141        for (int i = 0; i < getNumArg(); ++i) {
142          if (getArg(i).type().isVoid()) {
143            errorf("expression '%s' has type void and is not a valid method argument",
144                getArg(i).prettyPrint());
145          }
146        }
147        for (int i = 0; i < decl().getNumParameter(); i++) {
148          TypeDecl exprType = getArg(i).type();
149          TypeDecl parmType = decl().getParameter(i).type();
150          if (!exprType.methodInvocationConversionTo(parmType)
151              && !exprType.isUnknown() && !parmType.isUnknown()) {
152            errorf("argument '%s' of type %s is not compatible with the method parameter type %s",
153                getArg(i).prettyPrint(), exprType.typeName(), parmType.typeName());
154          }
155        }
156      }
157    
158      // 15.13
159      public void ArrayAccess.typeCheck() {
160        if (isQualified() && !qualifier().type().isArrayDecl() && !qualifier().type().isUnknown()) {
161          errorf("the type %s of the indexed element is not an array", qualifier().type().name());
162        }
163        if (!getExpr().type().unaryNumericPromotion().isInt() || !getExpr().type().isIntegralType()) {
164          errorf("array index must be int after unary numeric promotion which %s is not",
165              getExpr().type().typeName());
166        }
167      }
168    
169      public void ArrayInit.typeCheck() {
170        TypeDecl initializerType = declType().componentType();
171        if (initializerType.isUnknown()) {
172          error("the dimension of the initializer is larger than the expected dimension");
173        }
174        for (int i = 0; i < getNumInit(); i++) {
175          Expr e = getInit(i);
176          if (!e.type().assignConversionTo(initializerType, e)) {
177            errorf("the type %s of the initializer is not compatible with %s",
178                e.type().name(), initializerType.name());
179          }
180        }
181      }
182    
183      // 15.17
184      public void MultiplicativeExpr.typeCheck() {
185        if (!getLeftOperand().type().isNumericType()) {
186          errorf("%s is not numeric", getLeftOperand().type().typeName());
187        }
188        if (!getRightOperand().type().isNumericType()) {
189          errorf("%s is not numeric", getRightOperand().type().typeName());
190        }
191      }
192    
193      // 15.18
194      public void AdditiveExpr.typeCheck() {
195        if (!getLeftOperand().type().isNumericType()) {
196          errorf("%s is not numeric", getLeftOperand().type().typeName());
197        }
198        if (!getRightOperand().type().isNumericType()) {
199          errorf("%s is not numeric", getRightOperand().type().typeName());
200        }
201      }
202    
203      // 15.18
204      public void AddExpr.typeCheck() {
205        TypeDecl left = getLeftOperand().type();
206        TypeDecl right = getRightOperand().type();
207        if (!left.isString() && !right.isString()) {
208          super.typeCheck();
209        } else if (left.isVoid()) {
210          error("The type void of the left hand side is not numeric");
211        } else if (right.isVoid()) {
212          error("The type void of the right hand side is not numeric");
213        }
214      }
215    
216      // 15.19
217      public void ShiftExpr.typeCheck() {
218        if (!getLeftOperand().type().isIntegralType()) {
219          errorf("%s is not integral", getLeftOperand().type().typeName());
220        }
221        if (!getRightOperand().type().isIntegralType()) {
222          errorf("%s is not integral", getRightOperand().type().typeName());
223        }
224      }
225    
226      // 15.22
227      public void BitwiseExpr.typeCheck() {
228        TypeDecl left = getLeftOperand().type();
229        TypeDecl right = getRightOperand().type();
230        if (left.isIntegralType() && right.isIntegralType()) {
231          return;
232        } else if (left.isBoolean() && right.isBoolean()) {
233          return;
234        } else {
235          errorf("%s is not compatible with %s", left.typeName(), right.typeName());
236        }
237      }
238    
239      // 15.20
240      public void RelationalExpr.typeCheck() {
241        if (!getLeftOperand().type().isNumericType()) {
242          errorf("%s is not numeric", getLeftOperand().type().typeName());
243        }
244        if (!getRightOperand().type().isNumericType()) {
245          errorf("%s is not numeric", getRightOperand().type().typeName());
246        }
247      }
248    
249      // 15.23, 15.24
250      public void LogicalExpr.typeCheck() {
251        if (!getLeftOperand().type().isBoolean()) {
252          errorf("%s is not boolean", getLeftOperand().type().typeName());
253        }
254        if (!getRightOperand().type().isBoolean()) {
255          errorf("%s is not boolean", getRightOperand().type().typeName());
256        }
257      }
258    
259      // 15.21
260      public void EqualityExpr.typeCheck() {
261        TypeDecl left = getLeftOperand().type();
262        TypeDecl right = getRightOperand().type();
263        if (left.isNumericType() && right.isNumericType()) {
264          return;
265        } else if (left.isBoolean() && right.isBoolean()) {
266          return;
267        } else if ((left.isReferenceType() || left.isNull()) && (right.isReferenceType() || right.isNull())) {
268          if (left.castingConversionTo(right) || right.castingConversionTo(left)) {
269            return;
270          }
271        }
272        errorf("%s can not be compared to %s", left.typeName(), right.typeName());
273      }
274    
275      // 15.20.2
276      public void InstanceOfExpr.typeCheck() {
277        TypeDecl relationalExpr = getExpr().type();
278        TypeDecl referenceType = getTypeAccess().type();
279        if (!relationalExpr.isUnknown()) {
280          if (!relationalExpr.isReferenceType() && !relationalExpr.isNull()) {
281            error("The relational expression in instance of must be reference or null type");
282          }
283          if (!referenceType.isReferenceType()) {
284            error("The reference expression in instance of must be reference type");
285          }
286          if (!relationalExpr.castingConversionTo(referenceType)) {
287            errorf("The type %s of the relational expression %s can not be cast into the type %s",
288                relationalExpr.typeName(), getExpr().prettyPrint(), referenceType.typeName());
289          }
290          if (getExpr().isTypeAccess()) {
291            errorf("The relational expression %s must not be a type name", getExpr().prettyPrint());
292          }
293        }
294      }
295    
296      // 15.16
297      public void CastExpr.typeCheck() {
298        TypeDecl expr = getExpr().type();
299        TypeDecl type = getTypeAccess().type();
300        if (!expr.isUnknown()) {
301          if (!expr.castingConversionTo(type)) {
302            errorf("%s can not be cast into %s", expr.typeName(), type.typeName());
303          }
304          if (!getTypeAccess().isTypeAccess()) {
305            errorf("%s is not a type access in cast expression", getTypeAccess().prettyPrint());
306          }
307        }
308      }
309    
310      public void ParExpr.typeCheck() {
311        if (getExpr().isTypeAccess()) {
312          errorf("%s is a type and may not be used in parenthesized expression", getExpr().prettyPrint());
313        }
314      }
315    
316      // 15.15.3
317      public void PlusExpr.typeCheck() {
318        if (!getOperand().type().isNumericType()) {
319          error("unary plus only operates on numeric types");
320        }
321      }
322    
323      // 15.15.4
324      public void MinusExpr.typeCheck() {
325        if (!getOperand().type().isNumericType()) {
326          error("unary minus only operates on numeric types");
327        }
328      }
329    
330      // 15.15.5
331      public void BitNotExpr.typeCheck() {
332        if (!getOperand().type().isIntegralType()) {
333          error("unary ~ only operates on integral types");
334        }
335      }
336    
337      // 15.15.6
338      public void LogNotExpr.typeCheck() {
339        if (!getOperand().type().isBoolean()) {
340          error("unary ! only operates on boolean types");
341        }
342      }
343    
344      // 15.14
345      public void PostfixExpr.typeCheck() {
346        if (!getOperand().isVariable()) {
347          error("postfix expressions only work on variables");
348        } else if (!getOperand().type().isNumericType()) {
349          error("postfix expressions only operates on numeric types");
350        }
351      }
352    
353      // 15.15.1
354      public void PreIncExpr.typeCheck() {
355        if (!getOperand().isVariable()) {
356          error("prefix increment expression only work on variables");
357        } else if (!getOperand().type().isNumericType()) {
358          error("unary increment only operates on numeric types");
359        }
360      }
361    
362      // 15.15.2
363      public void PreDecExpr.typeCheck() {
364        if (!getOperand().isVariable()) {
365          error("prefix decrement expression only work on variables");
366        } else if (!getOperand().type().isNumericType()) {
367          error("unary decrement only operates on numeric types");
368        }
369      }
370    
371      public void IfStmt.typeCheck() {
372        TypeDecl cond = getCondition().type();
373        if (!cond.isBoolean()) {
374          errorf("the type of \"%s\" is %s which is not boolean",
375              getCondition().prettyPrint(), cond.name());
376        }
377      }
378      public void WhileStmt.typeCheck() {
379        TypeDecl cond = getCondition().type();
380        if (!cond.isBoolean()) {
381          errorf("the type of \"%s\" is %s which is not boolean",
382              getCondition().prettyPrint(), cond.name());
383        }
384      }
385      public void DoStmt.typeCheck() {
386        TypeDecl cond = getCondition().type();
387        if (!cond.isBoolean()) {
388          errorf("the type of \"%s\" is %s which is not boolean",
389              getCondition().prettyPrint(), cond.name());
390        }
391      }
392      public void ForStmt.typeCheck() {
393        if (hasCondition()) {
394          TypeDecl cond = getCondition().type();
395          if (!cond.isBoolean()) {
396            errorf("the type of \"%s\" is %s which is not boolean",
397                getCondition().prettyPrint(), cond.name());
398          }
399        }
400      }
401    
402      public void SwitchStmt.typeCheck() {
403        TypeDecl type = getExpr().type();
404        if (!type.isIntegralType() || type.isLong()) {
405          error("Switch expression must be of char, byte, short, or int");
406        }
407      }
408    
409      public void ConstCase.typeCheck() {
410        TypeDecl switchType = switchType();
411        TypeDecl type = getValue().type();
412        if (!type.assignConversionTo(switchType, getValue())) {
413          error("Constant expression must be assignable to Expression");
414        }
415        if (!getValue().isConstant() && !getValue().type().isUnknown()) {
416          error("Switch expression must be constant");
417        }
418      }
419    
420      inh TypeDecl Case.switchType();
421      eq SwitchStmt.getBlock().switchType() = getExpr().type();
422      eq Program.getChild().switchType() = unknownType();
423    
424      public void SynchronizedStmt.typeCheck() {
425        TypeDecl type = getExpr().type();
426        if (!type.isReferenceType() || type.isNull()) {
427          error("*** The type of the expression must be a reference");
428        }
429      }
430    
431      public void BasicCatch.typeCheck() {
432        if (!getParameter().type().instanceOf(typeThrowable())) {
433          error("*** The catch variable must extend Throwable");
434        }
435      }
436    
437      public void ThrowStmt.typeCheck() {
438        if (!getExpr().type().instanceOf(typeThrowable())) {
439          error("*** The thrown expression must extend Throwable");
440        }
441      }
442    
443      public void AssertStmt.typeCheck() {
444        // 14.10
445        if (!getCondition().type().isBoolean()) {
446          error("Assert requires boolean condition");
447        }
448        if (hasMessage() && getMessage().type().isVoid()) {
449          error("The detail message of an assert statement may not be void");
450        }
451      }
452    
453      public void MethodDecl.typeCheck() {
454        // Thrown vs super class method see MethodDecl.nameCheck
455        // 8.4.4
456        TypeDecl exceptionType = typeThrowable();
457        for (int i = 0; i < getNumException(); i++) {
458          TypeDecl typeDecl = getException(i).type();
459          if (!typeDecl.instanceOf(exceptionType)) {
460            errorf("%s throws non throwable type %s", signature(), typeDecl.fullName());
461          }
462        }
463    
464        // check returns
465        if (!isVoid() && hasBlock() && getBlock().canCompleteNormally()) {
466          error("the body of a non void method may not complete normally");
467        }
468    
469      }
470      // 14.16
471      inh TypeDecl TypeDecl.typeVoid();
472      inh TypeDecl ReturnStmt.returnType();
473      eq TypeDecl.getBodyDecl().returnType() = typeVoid();
474      eq MethodDecl.getBlock().returnType() = type();
475      eq Program.getChild().returnType() = typeVoid();
476    
477      public void ReturnStmt.typeCheck() {
478        if (hasResult() && !returnType().isVoid()) {
479          if (!getResult().type().assignConversionTo(returnType(), getResult())) {
480            errorf("return value must be an instance of %s which %s is not",
481                returnType().typeName(), getResult().type().typeName());
482          }
483        }
484        // 8.4.5 8.8.5
485        if (returnType().isVoid() && hasResult()) {
486          error("return stmt may not have an expression in void methods");
487        }
488        // 8.4.5
489        if (!returnType().isVoid() && !hasResult()) {
490          error("return stmt must have an expression in non void methods");
491        }
492        if (enclosingBodyDecl() instanceof InstanceInitializer || enclosingBodyDecl() instanceof StaticInitializer) {
493          error("Initializers may not return");
494        }
495    
496      }
497    
498      public void ConstructorDecl.typeCheck() {
499        // 8.8.4 (8.4.4)
500        TypeDecl exceptionType = typeThrowable();
501        for (int i = 0; i < getNumException(); i++) {
502          TypeDecl typeDecl = getException(i).type();
503          if (!typeDecl.instanceOf(exceptionType)) {
504            errorf("%s throws non throwable type %s", signature(), typeDecl.fullName());
505          }
506        }
507      }
508    
509      public void ClassInstanceExpr.typeCheck() {
510        if (isQualified() && qualifier().isTypeAccess() && !qualifier().type().isUnknown()) {
511          error("*** The expression in a qualified class instance expr must not be a type name");
512        }
513        // 15.9
514        if (isQualified() && !type().isInnerClass() && !((ClassDecl) type()).superclass().isInnerClass() && !type().isUnknown()) {
515          error("*** Qualified class instance creation can only instantiate inner classes and their anonymous subclasses");
516        }
517        if (!type().isClassDecl()) {
518          errorf("*** Can only instantiate classes, which %s is not", type().typeName());
519        }
520        typeCheckEnclosingInstance();
521        typeCheckAnonymousSuperclassEnclosingInstance();
522      }
523    
524      public void ClassInstanceExpr.typeCheckEnclosingInstance() {
525        TypeDecl C = type();
526        if (!C.isInnerClass()) {
527          return;
528        }
529    
530        TypeDecl enclosing = null;
531        if (C.isAnonymous()) {
532          if (noEnclosingInstance()) {
533            enclosing = null;
534          } else {
535            enclosing = hostType();
536          }
537        } else if (C.isLocalClass()) {
538          if (C.inStaticContext()) {
539            enclosing = null;
540          } else if (noEnclosingInstance()) {
541            enclosing = unknownType();
542          } else {
543            TypeDecl nest = hostType();
544            while (nest != null && !nest.instanceOf(C.enclosingType())) {
545              nest = nest.enclosingType();
546            }
547            enclosing = nest;
548          }
549        } else if (C.isMemberType()) {
550          if (!isQualified()) {
551            if (noEnclosingInstance()) {
552              errorf("No enclosing instance to initialize %s with", C.typeName());
553              //System.err.println("ClassInstanceExpr: Non qualified MemberType " + C.typeName() + " is in a static context when instantiated in " + this);
554              enclosing = unknownType();
555            } else {
556              TypeDecl nest = hostType();
557              while (nest != null && !nest.instanceOf(C.enclosingType())) {
558                if (nest.isStatic()) {
559                  errorf("No enclosing instance to initialize %s with", C.typeName());
560                  nest = unknownType();
561                  break;
562                }
563                nest = nest.enclosingType();
564              }
565              enclosing = nest == null ? unknownType() : nest;
566            }
567          } else {
568            enclosing = enclosingInstance();
569          }
570        }
571        if (enclosing != null) {
572          if (enclosing.isUnknown()) {
573            errorf("No enclosing instance to initialize %s with", C.typeName());
574          } else if (!enclosing.instanceOf(C.enclosingType())) {
575            errorf("*** Can not instantiate %s with the enclosing instance %s due to incorrect enclosing instance",
576                C.typeName(), enclosing.typeName());
577          } else if (!isQualified() && C.isMemberType() && inExplicitConstructorInvocation() && enclosing == hostType()) {
578            errorf("*** The innermost enclosing instance of type %s is this which is not yet initialized here.",
579                enclosing.typeName());
580          }
581        }
582      }
583    
584      inh TypeDecl SuperConstructorAccess.enclosingInstance();
585      inh TypeDecl ClassInstanceExpr.enclosingInstance();
586      inh TypeDecl TypeDecl.enclosingInstance();
587      eq Program.getChild().enclosingInstance() = null;
588      eq StaticInitializer.getBlock().enclosingInstance() = null;
589      //eq InstanceInitializer.getBlock().enclosingInstance() = null;
590      eq TypeDecl.getBodyDecl(int index).enclosingInstance() {
591        if (getBodyDecl(index) instanceof MemberTypeDecl && !((MemberTypeDecl) getBodyDecl(index)).typeDecl().isInnerType()) {
592          return null;
593        }
594        if (getBodyDecl(index) instanceof ConstructorDecl) {
595          return enclosingInstance();
596        }
597        return this;
598      }
599      eq AbstractDot.getRight().enclosingInstance() = getLeft().type();
600      eq ConstructorDecl.getParsedConstructorInvocation().enclosingInstance() = unknownType();
601      eq ConstructorDecl.getImplicitConstructorInvocation().enclosingInstance() = unknownType();
602    
603      syn boolean ClassInstanceExpr.noEnclosingInstance() =
604          isQualified() ? qualifier().staticContextQualifier() : inStaticContext();
605    
606      public void ClassInstanceExpr.typeCheckAnonymousSuperclassEnclosingInstance() {
607        if (type().isAnonymous() && ((ClassDecl) type()).superclass().isInnerType()) {
608          TypeDecl S = ((ClassDecl) type()).superclass();
609          if (S.isLocalClass()) {
610            if (S.inStaticContext()) {
611            } else if (noEnclosingInstance()) {
612              errorf("*** No enclosing instance to class %s due to static context", type().typeName());
613            } else if (inExplicitConstructorInvocation()) {
614              errorf("*** No enclosing instance to superclass %s of %s since this is not initialized yet",
615                  S.typeName(), type().typeName());
616            }
617          } else if (S.isMemberType()) {
618            if (!isQualified()) {
619              // 15.9.2 2nd paragraph
620              if (noEnclosingInstance()) {
621                errorf("*** No enclosing instance to class %s due to static context", type().typeName());
622              } else {
623                TypeDecl nest = hostType();
624                while (nest != null && !nest.instanceOf(S.enclosingType())) {
625                  nest = nest.enclosingType();
626                }
627                if (nest == null) {
628                  errorf("*** No enclosing instance to superclass %s of %s",
629                      S.typeName(), type().typeName());
630                } else if (inExplicitConstructorInvocation()) {
631                  errorf("*** No enclosing instance to superclass %s of %s since this is not initialized yet",
632                      S.typeName(), type().typeName());
633                }
634              }
635            }
636          }
637        }
638      }
639    
640      public void ArrayTypeWithSizeAccess.typeCheck() {
641        super.typeCheck();
642        if (!getExpr().type().unaryNumericPromotion().isInt()) {
643          errorf("%s is not int after unary numeric promotion", getExpr().type().typeName());
644        }
645      }
646    
647      // 15.25
648      public void ConditionalExpr.typeCheck() {
649        if (!getCondition().type().isBoolean()) {
650          error("The first operand of a conditional expression must be a boolean");
651        }
652        if (type().isUnknown() && !getTrueExpr().type().isUnknown() && !getFalseExpr().type().isUnknown()) {
653          error("The types of the second and third operand in this conditional expression do not match");
654        }
655      }
656    
657      public void IntegerLiteral.typeCheck() {
658        if (constant().error) {
659          error("The value of an int literal must be a decimal value in the range -2147483648..2147483647 or a hexadecimal or octal literal that fits in 32 bits.");
660        }
661      }
662    
663      public void LongLiteral.typeCheck() {
664        if (constant().error) {
665          errorf("The value of the long literal %s is not legal", getLITERAL());
666        }
667      }
668    
669      public void FloatingPointLiteral.typeCheck() {
670        if (!isZero() && constant().floatValue() == 0.0f) {
671          errorf("It is an error for nonzero floating-point %s to round to zero", getLITERAL());
672        }
673        if (constant().floatValue() == Float.NEGATIVE_INFINITY || constant().floatValue() == Float.POSITIVE_INFINITY) {
674          errorf("the floating-point literal \"%s\" is too large", getLITERAL());
675        }
676      }
677    
678      public void DoubleLiteral.typeCheck() {
679        if (!isZero() && constant().doubleValue() == 0.0f) {
680          errorf("It is an error for nonzero floating-point %s to round to zero", getLITERAL());
681        }
682        if (constant().doubleValue() == Double.NEGATIVE_INFINITY || constant().doubleValue() == Double.POSITIVE_INFINITY) {
683          errorf("the floating-point literal \"%s\" is too large", getLITERAL());
684        }
685      }
686    }