001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 011 aspect TypeCheck { 012 public void ASTNode.typeCheck() { 013 } 014 015 syn boolean Expr.isVariable() = false; 016 eq AbstractDot.isVariable() = lastAccess().isVariable(); 017 eq VarAccess.isVariable() = true; 018 eq ArrayAccess.isVariable() = true; 019 eq ParExpr.isVariable() = getExpr().isVariable(); 020 021 // 5.2 022 public void VariableDeclaration.typeCheck() { 023 if(hasInit()) { 024 TypeDecl source = getInit().type(); 025 TypeDecl dest = type(); 026 if(!source.assignConversionTo(dest, getInit())) 027 error("can not assign variable " + name() + " of type " + dest.typeName() + 028 " a value of type " + source.typeName()); 029 } 030 } 031 032 // 5.2 033 public void FieldDeclaration.typeCheck() { 034 if(hasInit()) { 035 TypeDecl source = getInit().type(); 036 TypeDecl dest = type(); 037 if(!source.assignConversionTo(dest, getInit())) 038 error("can not assign field " + name() + " of type " + dest.typeName() + 039 " a value of type " + source.typeName()); 040 } 041 } 042 043 // 5.2 Assignment Conversion 044 public void AssignSimpleExpr.typeCheck() { 045 if(!getDest().isVariable()) 046 error("left hand side is not a variable"); 047 else if(!sourceType().assignConversionTo(getDest().type(), getSource()) && !sourceType().isUnknown()) 048 error("can not assign " + getDest() + " of type " + getDest().type().typeName() + 049 " a value of type " + sourceType().typeName()); 050 } 051 052 public void AssignExpr.typeCheck() { 053 if(!getDest().isVariable()) 054 error("left hand side is not a variable"); 055 else { 056 TypeDecl source = sourceType(); 057 TypeDecl dest = getDest().type(); 058 if(getSource().type().isPrimitive() && getDest().type().isPrimitive()) 059 return; 060 error("can not assign " + getDest() + " of type " + getDest().type().typeName() + 061 " a value of type " + sourceType().typeName()); 062 } 063 } 064 065 public void AssignMultiplicativeExpr.typeCheck() { 066 if(sourceType().isBoolean() || getDest().type().isBoolean()) 067 error("Multiplicative operators do not operate on boolean types"); 068 super.typeCheck(); 069 } 070 071 public void AssignPlusExpr.typeCheck() { 072 if(!getDest().isVariable()) 073 error("left hand side is not a variable"); 074 else if(getSource().type().isUnknown() || getDest().type().isUnknown()) 075 return; 076 else if(getDest().type().isString() && !(getSource().type().isVoid())) 077 return; 078 else if(getSource().type().isBoolean() || getDest().type().isBoolean()) 079 error("Operator + does not operate on boolean types"); 080 else if(getSource().type().isPrimitive() && getDest().type().isPrimitive()) 081 return; 082 else 083 error("can not assign " + getDest() + " of type " + getDest().type().typeName() + 084 " a value of type " + sourceType().typeName()); 085 } 086 public void AssignMinusExpr.typeCheck() { 087 if(sourceType().isBoolean() || getDest().type().isBoolean()) 088 error("Operator - does not operate on boolean types"); 089 super.typeCheck(); 090 } 091 092 public void AssignShiftExpr.typeCheck() { 093 if(!sourceType().isIntegralType() || !getDest().type().isIntegralType()) 094 error("Shift operators only operate on integral types"); 095 super.typeCheck(); 096 } 097 098 public void AssignBitwiseExpr.typeCheck() { 099 TypeDecl source = sourceType(); 100 TypeDecl dest = getDest().type(); 101 if(source.isIntegralType() && dest.isIntegralType()) 102 super.typeCheck(); 103 else if(source.isBoolean() && dest.isBoolean()) 104 super.typeCheck(); 105 else 106 error("Operator only operates on integral and boolean types"); 107 } 108 109 syn TypeDecl AssignExpr.sourceType() = getSource().type().isPrimitive() ? getSource().type() : unknownType(); 110 111 eq AssignPlusExpr.sourceType() { 112 TypeDecl left = getDest().type(); 113 TypeDecl right = getSource().type(); 114 if(!left.isString() && !right.isString()) 115 return super.sourceType(); 116 if(left.isVoid() || right.isVoid()) 117 return unknownType(); 118 return left.isString() ? left : right; 119 } 120 121 syn TypeDecl AssignSimpleExpr.sourceType() = getSource().type(); 122 123 // 5.3 Method Invocation Conversion 124 public void MethodAccess.typeCheck() { 125 for(int i = 0; i < decl().getNumParameter(); i++) { 126 TypeDecl exprType = getArg(i).type(); 127 TypeDecl parmType = decl().getParameter(i).type(); 128 if(!exprType.methodInvocationConversionTo(parmType) && !exprType.isUnknown() && !parmType.isUnknown()) { 129 error("The type " + exprType.typeName() + " of expr " + 130 getArg(i) + " is not compatible with the method parameter " + 131 decl().getParameter(i)); 132 } 133 } 134 } 135 136 // 15.13 137 public void ArrayAccess.typeCheck() { 138 if(isQualified() && !qualifier().type().isArrayDecl() && !qualifier().type().isUnknown()) 139 error("the type " + qualifier().type().name() + " of the indexed element is not an array"); 140 if(!getExpr().type().unaryNumericPromotion().isInt() || !getExpr().type().isIntegralType()) 141 error("array index must be int after unary numeric promotion which " + getExpr().type().typeName() + " is not"); 142 } 143 144 public void ArrayInit.typeCheck() { 145 TypeDecl initializerType = declType().componentType(); 146 if(initializerType.isUnknown()) 147 error("the dimension of the initializer is larger than the expected dimension"); 148 for(int i = 0; i < getNumInit(); i++) { 149 Expr e = getInit(i); 150 if(!e.type().assignConversionTo(initializerType, e)) 151 error("the type " + e.type().name() + " of the initializer is not compatible with " + initializerType.name()); 152 } 153 } 154 155 // 15.17 156 public void MultiplicativeExpr.typeCheck() { 157 if(!getLeftOperand().type().isNumericType()) 158 error(getLeftOperand().type().typeName() + " is not numeric"); 159 if(!getRightOperand().type().isNumericType()) 160 error(getRightOperand().type().typeName() + " is not numeric"); 161 } 162 163 // 15.18 164 public void AdditiveExpr.typeCheck() { 165 if(!getLeftOperand().type().isNumericType()) 166 error(getLeftOperand().type().typeName() + " is not numeric"); 167 if(!getRightOperand().type().isNumericType()) 168 error(getRightOperand().type().typeName() + " is not numeric"); 169 } 170 171 // 15.18 172 public void AddExpr.typeCheck() { 173 TypeDecl left = getLeftOperand().type(); 174 TypeDecl right = getRightOperand().type(); 175 if(!left.isString() && !right.isString()) 176 super.typeCheck(); 177 else if(left.isVoid()) 178 error("The type void of the left hand side is not numeric"); 179 else if(right.isVoid()) 180 error("The type void of the right hand side is not numeric"); 181 } 182 183 // 15.19 184 public void ShiftExpr.typeCheck() { 185 if(!getLeftOperand().type().isIntegralType()) 186 error(getLeftOperand().type().typeName() + " is not integral"); 187 if(!getRightOperand().type().isIntegralType()) 188 error(getRightOperand().type().typeName() + " is not integral"); 189 } 190 191 // 15.22 192 public void BitwiseExpr.typeCheck() { 193 TypeDecl left = getLeftOperand().type(); 194 TypeDecl right = getRightOperand().type(); 195 if(left.isIntegralType() && right.isIntegralType()) 196 return; 197 else if(left.isBoolean() && right.isBoolean()) 198 return; 199 else 200 error(left.typeName() + " is not compatible with " + right.typeName()); 201 } 202 203 // 15.20 204 public void RelationalExpr.typeCheck() { 205 if(!getLeftOperand().type().isNumericType()) 206 error(getLeftOperand().type().typeName() + " is not numeric"); 207 if(!getRightOperand().type().isNumericType()) 208 error(getRightOperand().type().typeName() + " is not numeric"); 209 } 210 211 // 15.23, 15.24 212 public void LogicalExpr.typeCheck() { 213 if(!getLeftOperand().type().isBoolean()) 214 error(getLeftOperand().type().typeName() + " is not boolean"); 215 if(!getRightOperand().type().isBoolean()) 216 error(getRightOperand().type().typeName() + " is not boolean"); 217 } 218 219 // 15.21 220 public void EqualityExpr.typeCheck() { 221 TypeDecl left = getLeftOperand().type(); 222 TypeDecl right = getRightOperand().type(); 223 if(left.isNumericType() && right.isNumericType()) 224 return; 225 else if(left.isBoolean() && right.isBoolean()) 226 return; 227 else if((left.isReferenceType() || left.isNull()) && (right.isReferenceType() || right.isNull())) { 228 if(left.castingConversionTo(right) || right.castingConversionTo(left)) 229 return; 230 } 231 error(left.typeName() + " can not be compared to " + right.typeName()); 232 } 233 234 // 15.20.2 235 public void InstanceOfExpr.typeCheck() { 236 TypeDecl relationalExpr = getExpr().type(); 237 TypeDecl referenceType = getTypeAccess().type(); 238 if(!relationalExpr.isUnknown()) { 239 if(!relationalExpr.isReferenceType() && !relationalExpr.isNull()) 240 error("The relational expression in instance of must be reference or null type"); 241 if(!referenceType.isReferenceType()) 242 error("The reference expression in instance of must be reference type"); 243 if(!relationalExpr.castingConversionTo(referenceType)) 244 error("The type " + relationalExpr.typeName() + " of the relational expression " + 245 getExpr() + " can not be cast into the type " + referenceType.typeName()); 246 if(getExpr().isTypeAccess()) 247 error("The relational expression " + getExpr() + " must not be a type name"); 248 } 249 } 250 251 // 15.16 252 public void CastExpr.typeCheck() { 253 TypeDecl expr = getExpr().type(); 254 TypeDecl type = getTypeAccess().type(); 255 if(!expr.isUnknown()) { 256 if(!expr.castingConversionTo(type)) 257 error(expr.typeName() + " can not be cast into " + type.typeName()); 258 if(!getTypeAccess().isTypeAccess()) 259 error("" + getTypeAccess() + " is not a type access in cast expression"); 260 } 261 } 262 263 public void ParExpr.typeCheck() { 264 if(getExpr().isTypeAccess()) 265 error("" + getExpr() + " is a type and may not be used in parenthesized expression"); 266 } 267 268 // 15.15.3 269 public void PlusExpr.typeCheck() { 270 if(!getOperand().type().isNumericType()) 271 error("unary plus only operates on numeric types"); 272 } 273 274 // 15.15.4 275 public void MinusExpr.typeCheck() { 276 if(!getOperand().type().isNumericType()) 277 error("unary minus only operates on numeric types"); 278 } 279 280 // 15.15.5 281 public void BitNotExpr.typeCheck() { 282 if(!getOperand().type().isIntegralType()) 283 error("unary ~ only operates on integral types"); 284 } 285 286 // 15.15.6 287 public void LogNotExpr.typeCheck() { 288 if(!getOperand().type().isBoolean()) 289 error("unary ! only operates on boolean types"); 290 } 291 292 // 15.14 293 public void PostfixExpr.typeCheck() { 294 if(!getOperand().isVariable()) 295 error("postfix expressions only work on variables"); 296 else if(!getOperand().type().isNumericType()) 297 error("postfix expressions only operates on numeric types"); 298 } 299 300 // 15.15.1 301 public void PreIncExpr.typeCheck() { 302 if(!getOperand().isVariable()) 303 error("prefix increment expression only work on variables"); 304 else if(!getOperand().type().isNumericType()) 305 error("unary increment only operates on numeric types"); 306 } 307 308 // 15.15.2 309 public void PreDecExpr.typeCheck() { 310 if(!getOperand().isVariable()) 311 error("prefix decrement expression only work on variables"); 312 else if(!getOperand().type().isNumericType()) 313 error("unary decrement only operates on numeric types"); 314 } 315 316 public void IfStmt.typeCheck() { 317 TypeDecl cond = getCondition().type(); 318 if(!cond.isBoolean()) { 319 error("the type of \"" + getCondition() + "\" is " + cond.name() + " which is not boolean"); 320 } 321 } 322 public void WhileStmt.typeCheck() { 323 TypeDecl cond = getCondition().type(); 324 if(!cond.isBoolean()) { 325 error("the type of \"" + getCondition() + "\" is " + cond.name() + " which is not boolean"); 326 } 327 } 328 public void DoStmt.typeCheck() { 329 TypeDecl cond = getCondition().type(); 330 if(!cond.isBoolean()) { 331 error("the type of \"" + getCondition() + "\" is " + cond.name() + " which is not boolean"); 332 } 333 } 334 public void ForStmt.typeCheck() { 335 if(hasCondition()) { 336 TypeDecl cond = getCondition().type(); 337 if(!cond.isBoolean()) { 338 error("the type of \"" + getCondition() + "\" is " + cond.name() + " which is not boolean"); 339 } 340 } 341 } 342 343 public void SwitchStmt.typeCheck() { 344 TypeDecl type = getExpr().type(); 345 if(!type.isIntegralType() || type.isLong()) 346 error("Switch expression must be of char, byte, short, or int"); 347 } 348 349 public void ConstCase.typeCheck() { 350 TypeDecl switchType = switchType(); 351 TypeDecl type = getValue().type(); 352 if(!type.assignConversionTo(switchType, getValue())) 353 error("Constant expression must be assignable to Expression"); 354 if(!getValue().isConstant() && !getValue().type().isUnknown()) 355 error("Switch expression must be constant"); 356 } 357 358 inh TypeDecl Case.switchType(); 359 eq SwitchStmt.getBlock().switchType() = getExpr().type(); 360 eq Program.getChild().switchType() = unknownType(); 361 362 public void SynchronizedStmt.typeCheck() { 363 TypeDecl type = getExpr().type(); 364 if(!type.isReferenceType() || type.isNull()) 365 error("*** The type of the expression must be a reference"); 366 } 367 368 public void BasicCatch.typeCheck() { 369 if(!getParameter().type().instanceOf(typeThrowable())) 370 error("*** The catch variable must extend Throwable"); 371 } 372 373 public void ThrowStmt.typeCheck() { 374 if(!getExpr().type().instanceOf(typeThrowable())) 375 error("*** The thrown expression must extend Throwable"); 376 } 377 378 public void AssertStmt.typeCheck() { 379 // 14.10 380 if(!getfirst().type().isBoolean()) 381 error("Assert requires boolean condition"); 382 if(hasExpr() && getExpr().type().isVoid()) 383 error("The second part of an assert statement may not be void"); 384 } 385 386 public void MethodDecl.typeCheck() { 387 // Thrown vs super class method see MethodDecl.nameCheck 388 // 8.4.4 389 TypeDecl exceptionType = typeThrowable(); 390 for(int i = 0; i < getNumException(); i++) { 391 TypeDecl typeDecl = getException(i).type(); 392 if(!typeDecl.instanceOf(exceptionType)) 393 error(signature() + " throws non throwable type " + typeDecl.fullName()); 394 } 395 396 // check returns 397 if(!isVoid() && hasBlock() && getBlock().canCompleteNormally()) 398 error("the body of a non void method may not complete normally"); 399 400 } 401 // 14.16 402 inh TypeDecl TypeDecl.typeVoid(); 403 inh TypeDecl ReturnStmt.returnType(); 404 eq TypeDecl.getBodyDecl().returnType() = typeVoid(); 405 eq MethodDecl.getBlock().returnType() = type(); 406 eq Program.getChild().returnType() = typeVoid(); 407 408 public void ReturnStmt.typeCheck() { 409 if(hasResult() && !returnType().isVoid()) { 410 if(!getResult().type().assignConversionTo(returnType(), getResult())) 411 error("return value must be an instance of " + returnType().typeName() + " which " + getResult().type().typeName() + " is not"); 412 } 413 // 8.4.5 8.8.5 414 if(returnType().isVoid() && hasResult()) 415 error("return stmt may not have an expression in void methods"); 416 // 8.4.5 417 if(!returnType().isVoid() && !hasResult()) 418 error("return stmt must have an expression in non void methods"); 419 if(enclosingBodyDecl() instanceof InstanceInitializer || enclosingBodyDecl() instanceof StaticInitializer) 420 error("Initializers may not return"); 421 422 } 423 424 public void ConstructorDecl.typeCheck() { 425 // 8.8.4 (8.4.4) 426 TypeDecl exceptionType = typeThrowable(); 427 for(int i = 0; i < getNumException(); i++) { 428 TypeDecl typeDecl = getException(i).type(); 429 if(!typeDecl.instanceOf(exceptionType)) 430 error(signature() + " throws non throwable type " + typeDecl.fullName()); 431 } 432 } 433 434 public void ClassInstanceExpr.typeCheck() { 435 if(isQualified() && qualifier().isTypeAccess() && !qualifier().type().isUnknown()) 436 error("*** The expression in a qualified class instance expr must not be a type name"); 437 // 15.9 438 if(isQualified() && !type().isInnerClass() && !((ClassDecl)type()).superclass().isInnerClass() && !type().isUnknown()) { 439 error("*** Qualified class instance creation can only instantiate inner classes and their anonymous subclasses"); 440 } 441 if(!type().isClassDecl()) { 442 error("*** Can only instantiate classes, which " + type().typeName() + " is not"); 443 } 444 typeCheckEnclosingInstance(); 445 typeCheckAnonymousSuperclassEnclosingInstance(); 446 } 447 448 public void ClassInstanceExpr.typeCheckEnclosingInstance() { 449 TypeDecl C = type(); 450 if(!C.isInnerClass()) 451 return; 452 453 TypeDecl enclosing = null; 454 if(C.isAnonymous()) { 455 if(noEnclosingInstance()) { 456 enclosing = null; 457 } 458 else { 459 enclosing = hostType(); 460 } 461 } 462 else if(C.isLocalClass()) { 463 if(C.inStaticContext()) { 464 enclosing = null; 465 } 466 else if(noEnclosingInstance()) { 467 enclosing = unknownType(); 468 } 469 else { 470 TypeDecl nest = hostType(); 471 while(nest != null && !nest.instanceOf(C.enclosingType())) 472 nest = nest.enclosingType(); 473 enclosing = nest; 474 } 475 } 476 else if(C.isMemberType()) { 477 if(!isQualified()) { 478 if(noEnclosingInstance()) { 479 error("No enclosing instance to initialize " + C.typeName() + " with"); 480 //System.err.println("ClassInstanceExpr: Non qualified MemberType " + C.typeName() + " is in a static context when instantiated in " + this); 481 enclosing = unknownType(); 482 } 483 else { 484 TypeDecl nest = hostType(); 485 while(nest != null && !nest.instanceOf(C.enclosingType())) 486 nest = nest.enclosingType(); 487 enclosing = nest == null ? unknownType() : nest; 488 } 489 } 490 else { 491 enclosing = enclosingInstance(); 492 } 493 } 494 if(enclosing != null && !enclosing.instanceOf(type().enclosingType())) { 495 String msg = enclosing == null ? "None" : enclosing.typeName(); 496 error("*** Can not instantiate " + type().typeName() + " with the enclosing instance " + msg + " due to incorrect enclosing instance"); 497 } 498 else if(!isQualified() && C.isMemberType() && inExplicitConstructorInvocation() && enclosing == hostType()) { 499 error("*** The innermost enclosing instance of type " + enclosing.typeName() + " is this which is not yet initialized here."); 500 } 501 } 502 503 inh TypeDecl SuperConstructorAccess.enclosingInstance(); 504 inh TypeDecl ClassInstanceExpr.enclosingInstance(); 505 inh TypeDecl TypeDecl.enclosingInstance(); 506 eq Program.getChild().enclosingInstance() = null; 507 eq StaticInitializer.getBlock().enclosingInstance() = null; 508 //eq InstanceInitializer.getBlock().enclosingInstance() = null; 509 eq TypeDecl.getBodyDecl().enclosingInstance() { 510 if(getBodyDecl(childIndex) instanceof MemberTypeDecl && !((MemberTypeDecl)getBodyDecl(childIndex)).typeDecl().isInnerType()) 511 return null; 512 if(getBodyDecl(childIndex) instanceof ConstructorDecl) 513 return enclosingInstance(); 514 return this; 515 } 516 eq AbstractDot.getRight().enclosingInstance() = getLeft().type(); 517 eq ConstructorDecl.getConstructorInvocation().enclosingInstance() = unknownType(); 518 519 syn boolean ClassInstanceExpr.noEnclosingInstance() = isQualified() ? qualifier().staticContextQualifier() : inStaticContext(); 520 521 public void ClassInstanceExpr.typeCheckAnonymousSuperclassEnclosingInstance() { 522 if(type().isAnonymous() && ((ClassDecl)type()).superclass().isInnerType()) { 523 TypeDecl S = ((ClassDecl)type()).superclass(); 524 if(S.isLocalClass()) { 525 if(S.inStaticContext()) { 526 } 527 else if(noEnclosingInstance()) { 528 error("*** No enclosing instance to class " + type().typeName() + " due to static context"); 529 } 530 else if(inExplicitConstructorInvocation()) 531 error("*** No enclosing instance to superclass " + S.typeName() + " of " + type().typeName() + " since this is not initialized yet"); 532 } 533 else if(S.isMemberType()) { 534 if(!isQualified()) { 535 // 15.9.2 2nd paragraph 536 if(noEnclosingInstance()) { 537 error("*** No enclosing instance to class " + type().typeName() + " due to static context"); 538 } 539 else { 540 TypeDecl nest = hostType(); 541 while(nest != null && !nest.instanceOf(S.enclosingType())) 542 nest = nest.enclosingType(); 543 if(nest == null) { 544 error("*** No enclosing instance to superclass " + S.typeName() + " of " + type().typeName()); 545 } 546 else if(inExplicitConstructorInvocation()) { 547 error("*** No enclosing instance to superclass " + S.typeName() + " of " + type().typeName() + " since this is not initialized yet"); 548 } 549 } 550 } 551 } 552 } 553 } 554 555 public void ArrayTypeWithSizeAccess.typeCheck() { 556 super.typeCheck(); 557 if(!getExpr().type().unaryNumericPromotion().isInt()) 558 error(getExpr().type().typeName() + " is not int after unary numeric promotion"); 559 } 560 561 // 15.25 562 public void ConditionalExpr.typeCheck() { 563 if(!getCondition().type().isBoolean()) 564 error("The first operand of a conditional expression must be a boolean"); 565 if(type().isUnknown() && !getTrueExpr().type().isUnknown() && !getFalseExpr().type().isUnknown()) { 566 error("The types of the second and third operand in this conditional expression do not match"); 567 } 568 } 569 570 public void IntegerLiteral.typeCheck() { 571 if(constant().error) 572 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."); 573 574 } 575 public void LongLiteral.typeCheck() { 576 if(constant().error) 577 error("The value of the long literal " + getLITERAL() + " is not legal"); 578 579 } 580 581 public void FloatingPointLiteral.typeCheck() { 582 if(!isZero() && constant().floatValue() == 0.0f) 583 error("It is an error for nonzero floating-point " + getLITERAL() + " to round to zero"); 584 if(constant().floatValue() == Float.NEGATIVE_INFINITY || constant().floatValue() == Float.POSITIVE_INFINITY) 585 error("It is an error for floating-point " + getLITERAL() + " to round to an infinity"); 586 587 } 588 public void DoubleLiteral.typeCheck() { 589 if(!isZero() && constant().doubleValue() == 0.0f) 590 error("It is an error for nonzero floating-point " + getLITERAL() + " to round to zero"); 591 if(constant().doubleValue() == Double.NEGATIVE_INFINITY || constant().doubleValue() == Double.POSITIVE_INFINITY) 592 error("It is an error for floating-point " + getLITERAL() + " to round to an infinity"); 593 } 594 }