001 /* Copyright (c) 2014, Erik Hogeman <Erik.Hogemn@gmail.com> 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 * * Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * * Redistributions in binary form must reproduce the above copyright 010 * notice, this list of conditions and the following disclaimer in the 011 * documentation and/or other materials provided with the distribution. 012 * * Neither the name of the Lund University nor the names of its 013 * contributors may be used to endorse or promote products derived from 014 * this software without specific prior written permission. 015 * 016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 017 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 020 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 021 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 022 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 023 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 024 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 025 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 026 * POSSIBILITY OF SUCH DAMAGE. 027 */ 028 029 aspect PreciseRethrow { 030 inh boolean InferredParameterDeclaration.inhModifiedInScope(Variable var); 031 inh boolean LambdaParameters.inhModifiedInScope(Variable var); 032 inh boolean VariableDeclaration.inhModifiedInScope(Variable var); 033 034 eq LambdaExpr.getLambdaParameters().inhModifiedInScope(Variable var) = modifiedInScope(var); 035 eq DeclaredLambdaParameters.getParameter().inhModifiedInScope(Variable var) = 036 inhModifiedInScope(var); 037 eq InferredLambdaParameters.getParameter().inhModifiedInScope(Variable var) = 038 inhModifiedInScope(var); 039 040 syn boolean BodyDecl.modifiedInScope(Variable var); 041 syn boolean TypeDecl.modifiedInScope(Variable var); 042 043 syn boolean LambdaBody.modifiedInScope(Variable var); 044 eq LambdaExpr.modifiedInScope(Variable var) = getLambdaBody().modifiedInScope(var); 045 eq BlockLambdaBody.modifiedInScope(Variable var) = getBlock().modifiedInScope(var); 046 eq ExprLambdaBody.modifiedInScope(Variable var) = getExpr().modifiedInScope(var); 047 048 eq EnhancedForStmt.getVariableDeclaration().inhModifiedInScope(Variable var) = 049 modifiedInScope(var); 050 eq EnhancedForStmt.getStmt().inhModifiedInScope(Variable var) = false; 051 eq Block.getStmt().inhModifiedInScope(Variable var) = modifiedInScope(var); 052 eq IfStmt.getThen().inhModifiedInScope(Variable var) = false; 053 eq IfStmt.getElse().inhModifiedInScope(Variable var) = false; 054 eq WhileStmt.getStmt().inhModifiedInScope(Variable var) = false; 055 eq DoStmt.getStmt().inhModifiedInScope(Variable var) = false; 056 eq ForStmt.getInitStmt().inhModifiedInScope(Variable var) = modifiedInScope(var); 057 eq ForStmt.getUpdateStmt().inhModifiedInScope(Variable var) = modifiedInScope(var); 058 eq ForStmt.getStmt().inhModifiedInScope(Variable var) = false; 059 060 eq ConstructorDecl.getParsedConstructorInvocation().inhModifiedInScope(Variable var) = false; 061 eq ConstructorDecl.getImplicitConstructorInvocation().inhModifiedInScope(Variable var) = false; 062 063 eq BodyDecl.modifiedInScope(Variable var) = false; 064 eq ConstructorDecl.modifiedInScope(Variable var) = getBlock().modifiedInScope(var); 065 eq InstanceInitializer.modifiedInScope(Variable var) = getBlock().modifiedInScope(var); 066 eq StaticInitializer.modifiedInScope(Variable var) = getBlock().modifiedInScope(var); 067 068 refine PreciseRethrow 069 eq LocalClassDeclStmt.modifiedInScope(Variable var) = getClassDecl().modifiedInScope(var); 070 eq MemberClassDecl.modifiedInScope(Variable var) = getClassDecl().modifiedInScope(var); 071 eq MemberInterfaceDecl.modifiedInScope(Variable var) = getInterfaceDecl().modifiedInScope(var); 072 eq MethodDecl.modifiedInScope(Variable var) = hasBlock() && getBlock().modifiedInScope(var); 073 074 eq TypeDecl.modifiedInScope(Variable var) { 075 for (int i = 0; i < getNumBodyDecl(); i++) { 076 BodyDecl body = getBodyDecl(i); 077 if (body.modifiedInScope(var)) { 078 return true; 079 } 080 } 081 return false; 082 } 083 084 eq ArrayAccess.modifiedInScope(Variable var) = getExpr().modifiedInScope(var); 085 086 refine PreciseRethrow 087 eq AbstractDot.modifiedInScope(Variable var) = 088 getLeft().modifiedInScope(var) || getRight().modifiedInScope(var); 089 090 eq PostIncExpr.modifiedInScope(Variable var) = getOperand().isVariable(var); 091 eq PostDecExpr.modifiedInScope(Variable var) = getOperand().isVariable(var); 092 eq PreIncExpr.modifiedInScope(Variable var) = getOperand().isVariable(var); 093 eq PreDecExpr.modifiedInScope(Variable var) = getOperand().isVariable(var); 094 095 refine PreciseRethrow 096 eq ClassInstanceExpr.modifiedInScope(Variable var) { 097 for (int i = 0; i < getNumArg(); ++i) { 098 if (getArg(i).modifiedInScope(var)) { 099 return true; 100 } 101 } 102 if (hasTypeDecl()) { 103 return getTypeDecl().modifiedInScope(var); 104 } else { 105 return false; 106 } 107 } 108 109 refine PreciseRethrow 110 eq ConstructorDecl.getParameter().inhModifiedInScope(Variable var) { 111 return getBlock().modifiedInScope(var) || getConstructorInvocation().modifiedInScope(var); 112 } 113 114 refine PreciseRethrow 115 eq AssignExpr.modifiedInScope(Variable var) { 116 boolean isLeft = getDest().isVariable(var); 117 if (isLeft && var instanceof VariableDeclaration) { 118 VariableDeclaration decl = (VariableDeclaration) var; 119 if (!decl.hasInit()) { 120 // Variable is being written to in an inner class. 121 if (decl.hostType() != hostType()) { 122 return true; 123 } 124 // 4.12.4; 125 return !getSource().isDUafter(var); 126 } 127 return true; 128 } else { 129 return isLeft || getSource().modifiedInScope(var); 130 } 131 } 132 } 133 134 aspect EffectivelyFinal { 135 //4.12.4 136 syn lazy boolean InferredParameterDeclaration.isEffectivelyFinal() = 137 isFinal() || !inhModifiedInScope(this); 138 syn lazy boolean FieldDeclaration.isEffectivelyFinal() = isFinal(); 139 140 //14.20 141 // CatchParameterDeclaration is only used in a multi-catch, and multi-catch parameters are 142 // always implicitly final. 143 syn lazy boolean CatchParameterDeclaration.isEffectivelyFinal() = true; 144 145 /** 146 * Note: this attribute deviates from what the JLS says about effectively finalness, 147 * simply because the attribute name would be confusing if it did not return true 148 * when the variable was explicitly declared final. The JLS considers declared final 149 * and effectively final to be mutually exclusive, we don't. 150 */ 151 syn lazy boolean VariableDeclaration.isEffectivelyFinal() = 152 isFinal() || !inhModifiedInScope(this); 153 }