src/share/classes/com/sun/tools/javac/comp/Flow.java

changeset 935
5b29f2a85085
parent 906
c15d788cb381
child 969
8cc5b440fdde
equal deleted inserted replaced
934:480de7832e2f 935:5b29f2a85085
188 private final Check chk; 188 private final Check chk;
189 private TreeMaker make; 189 private TreeMaker make;
190 private final Resolve rs; 190 private final Resolve rs;
191 private Env<AttrContext> attrEnv; 191 private Env<AttrContext> attrEnv;
192 private Lint lint; 192 private Lint lint;
193 private final boolean allowRethrowAnalysis; 193 private final boolean allowImprovedRethrowAnalysis;
194 private final boolean allowImprovedCatchAnalysis;
194 195
195 public static Flow instance(Context context) { 196 public static Flow instance(Context context) {
196 Flow instance = context.get(flowKey); 197 Flow instance = context.get(flowKey);
197 if (instance == null) 198 if (instance == null)
198 instance = new Flow(context); 199 instance = new Flow(context);
207 types = Types.instance(context); 208 types = Types.instance(context);
208 chk = Check.instance(context); 209 chk = Check.instance(context);
209 lint = Lint.instance(context); 210 lint = Lint.instance(context);
210 rs = Resolve.instance(context); 211 rs = Resolve.instance(context);
211 Source source = Source.instance(context); 212 Source source = Source.instance(context);
212 allowRethrowAnalysis = source.allowMulticatch(); 213 allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
214 allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
213 } 215 }
214 216
215 /** A flag that indicates whether the last statement could 217 /** A flag that indicates whether the last statement could
216 * complete normally. 218 * complete normally.
217 */ 219 */
1044 } 1046 }
1045 } 1047 }
1046 } 1048 }
1047 } 1049 }
1048 scanStat(tree.body); 1050 scanStat(tree.body);
1049 List<Type> thrownInTry = thrown; 1051 List<Type> thrownInTry = allowImprovedCatchAnalysis ?
1052 chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) :
1053 thrown;
1050 thrown = thrownPrev; 1054 thrown = thrownPrev;
1051 caught = caughtPrev; 1055 caught = caughtPrev;
1052 boolean aliveEnd = alive; 1056 boolean aliveEnd = alive;
1053 uninitsTry.andSet(uninits); 1057 uninitsTry.andSet(uninits);
1054 Bits initsEnd = inits; 1058 Bits initsEnd = inits;
1079 Type exc = ct.type; 1083 Type exc = ct.type;
1080 if (exc != syms.unknownType) { 1084 if (exc != syms.unknownType) {
1081 ctypes = ctypes.append(exc); 1085 ctypes = ctypes.append(exc);
1082 if (types.isSameType(exc, syms.objectType)) 1086 if (types.isSameType(exc, syms.objectType))
1083 continue; 1087 continue;
1084 if (chk.subset(exc, caughtInTry)) { 1088 checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
1085 log.error(l.head.pos(),
1086 "except.already.caught", exc);
1087 } else if (!chk.isUnchecked(l.head.pos(), exc) &&
1088 exc.tsym != syms.throwableType.tsym &&
1089 exc.tsym != syms.exceptionType.tsym &&
1090 !chk.intersects(exc, thrownInTry)) {
1091 log.error(l.head.pos(),
1092 "except.never.thrown.in.try", exc);
1093 }
1094 caughtInTry = chk.incl(exc, caughtInTry); 1089 caughtInTry = chk.incl(exc, caughtInTry);
1095 } 1090 }
1096 } 1091 }
1097 inits = initsTry.dup(); 1092 inits = initsTry.dup();
1098 uninits = uninitsTry.dup(); 1093 uninits = uninitsTry.dup();
1150 ListBuffer<PendingExit> exits = pendingExits; 1145 ListBuffer<PendingExit> exits = pendingExits;
1151 pendingExits = prevPendingExits; 1146 pendingExits = prevPendingExits;
1152 while (exits.nonEmpty()) pendingExits.append(exits.next()); 1147 while (exits.nonEmpty()) pendingExits.append(exits.next());
1153 } 1148 }
1154 uninitsTry.andSet(uninitsTryPrev).andSet(uninits); 1149 uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
1150 }
1151
1152 void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
1153 if (chk.subset(exc, caughtInTry)) {
1154 log.error(pos, "except.already.caught", exc);
1155 } else if (!chk.isUnchecked(pos, exc) &&
1156 exc.tsym != syms.throwableType.tsym &&
1157 exc.tsym != syms.exceptionType.tsym &&
1158 !chk.intersects(exc, thrownInTry)) {
1159 log.error(pos, "except.never.thrown.in.try", exc);
1160 } else if (allowImprovedCatchAnalysis) {
1161 List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
1162 // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
1163 // unchecked exception, the result list would not be empty, as the augmented
1164 // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
1165 // exception, that would have been covered in the branch above
1166 if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty()) {
1167 String key = catchableThrownTypes.length() == 1 ?
1168 "unreachable.catch" :
1169 "unreachable.catch.1";
1170 log.warning(pos, key, catchableThrownTypes);
1171 }
1172 }
1155 } 1173 }
1156 1174
1157 public void visitConditional(JCConditional tree) { 1175 public void visitConditional(JCConditional tree) {
1158 scanCond(tree.cond); 1176 scanCond(tree.cond);
1159 Bits initsBeforeElse = initsWhenFalse; 1177 Bits initsBeforeElse = initsWhenFalse;
1236 Symbol sym = TreeInfo.symbol(tree.expr); 1254 Symbol sym = TreeInfo.symbol(tree.expr);
1237 if (sym != null && 1255 if (sym != null &&
1238 sym.kind == VAR && 1256 sym.kind == VAR &&
1239 (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 && 1257 (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
1240 preciseRethrowTypes.get(sym) != null && 1258 preciseRethrowTypes.get(sym) != null &&
1241 allowRethrowAnalysis) { 1259 allowImprovedRethrowAnalysis) {
1242 for (Type t : preciseRethrowTypes.get(sym)) { 1260 for (Type t : preciseRethrowTypes.get(sym)) {
1243 markThrown(tree, t); 1261 markThrown(tree, t);
1244 } 1262 }
1245 } 1263 }
1246 else { 1264 else {

mercurial