Skip to content

Commit d6238d2

Browse files
committed
Warn on casts to same type + Error on impossible casts
1 parent 40256c9 commit d6238d2

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

src/main/java/com/laytonsmith/core/functions/Compiler.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import com.laytonsmith.core.Optimizable;
1313
import com.laytonsmith.core.ParseTree;
1414
import com.laytonsmith.core.Script;
15+
import com.laytonsmith.core.compiler.CompilerEnvironment;
16+
import com.laytonsmith.core.compiler.CompilerWarning;
1517
import com.laytonsmith.core.compiler.FileOptions;
1618
import com.laytonsmith.core.compiler.analysis.StaticAnalysis;
1719
import com.laytonsmith.core.compiler.signature.FunctionSignatures;
@@ -1246,22 +1248,49 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
12461248
throw new CRECastException(
12471249
"Cannot cast from " + value.typeof().getSimpleName() + " to " + type.getSimpleName() + ".", t);
12481250
}
1249-
// TODO - Perform runtime conversion to 'type' when necessary (cross-cast handling).
12501251
return value;
12511252
}
12521253

12531254
@Override
12541255
public CClassType typecheck(StaticAnalysis analysis,
12551256
ParseTree ast, Environment env, Set<ConfigCompileException> exceptions) {
12561257

1257-
// Typecheck children and validate function signature through super call.
1258-
super.typecheck(analysis, ast, env, exceptions);
1258+
// Fall back to default behavior for invalid usage.
1259+
if(ast.numberOfChildren() != 2) {
1260+
return super.typecheck(analysis, ast, env, exceptions);
1261+
}
12591262

1260-
// Return type that is being cast to.
1261-
if(ast.numberOfChildren() != 2 || !(ast.getChildAt(1).getData() instanceof CClassType)) {
1263+
// Typecheck value and type nodes.
1264+
ParseTree valNode = ast.getChildAt(0);
1265+
CClassType valType = analysis.typecheck(valNode, env, exceptions);
1266+
StaticAnalysis.requireType(valType, Mixed.TYPE, valType.getTarget(), env, exceptions);
1267+
ParseTree typeNode = ast.getChildAt(1);
1268+
CClassType typeType = analysis.typecheck(typeNode, env, exceptions);
1269+
StaticAnalysis.requireType(typeType, CClassType.TYPE, typeNode.getTarget(), env, exceptions);
1270+
1271+
// Get cast-to type.
1272+
if(!(typeNode.getData() instanceof CClassType)) {
1273+
assert !exceptions.isEmpty() : "Missing compile-time type error for cast type argument.";
12621274
return CClassType.AUTO;
12631275
}
1264-
return (CClassType) ast.getChildAt(1).getData();
1276+
CClassType castToType = (CClassType) typeNode.getData();
1277+
1278+
// Generate redundancy warning for casts to the value type.
1279+
if(castToType.equals(valType)) {
1280+
env.getEnv(CompilerEnvironment.class).addCompilerWarning(ast.getFileOptions(),
1281+
new CompilerWarning("Redundant cast to " + castToType.getSimpleName(), ast.getTarget(),
1282+
FileOptions.SuppressWarning.UselessCode));
1283+
}
1284+
1285+
// Generate compile error for impossible casts.
1286+
if(!InstanceofUtil.isInstanceof(valType, castToType, env)
1287+
&& !InstanceofUtil.isInstanceof(castToType, valType, env)) {
1288+
exceptions.add(new ConfigCompileException("Cannot cast from "
1289+
+ valType.getSimpleName() + " to " + castToType.getSimpleName() + ".", ast.getTarget()));
1290+
}
1291+
1292+
// Return type that is being cast to.
1293+
return castToType;
12651294
}
12661295
}
12671296
}

0 commit comments

Comments
 (0)