IdentityMutationFinder extends Expr2ExprMutationFinder { @Override public void visitFunctionCallExpr(FunctionCallExpr functionCallExpr) { visitExpr(functionCallExpr); FunctionPrototype bestMatch = null; for (FunctionPrototype candidate : typer.getPrototypes(functionCallExpr.getCallee())) { if (candidate.getNumParameters() == functionCallExpr.getNumArgs()) { if (bestMatch == null || callMatchesPrototype(functionCallExpr, candidate)) { bestMatch = candidate; } } } for (int i = 0; i < functionCallExpr.getNumArgs(); i++) { boolean isLValue = false; if (bestMatch != null) { final Type argType = bestMatch.getParameters().get(i).getType(); if (argType.hasQualifier(TypeQualifier.INOUT_PARAM) || argType.hasQualifier(TypeQualifier.OUT_PARAM)) { isLValue = true; } } if (!isLValue) { visit(functionCallExpr.getArg(i)); } } } IdentityMutationFinder(TranslationUnit tu,
                                IRandom generator,
                                GenerationParams generationParams); @Override void visitForStmt(ForStmt forStmt); @Override void visitBinaryExpr(BinaryExpr binaryExpr); @Override void visitUnaryExpr(UnaryExpr unaryExpr); @Override void visitFunctionCallExpr(FunctionCallExpr functionCallExpr); @Override void visitArrayIndexExpr(ArrayIndexExpr arrayIndexExpr); @Override void visitVariablesDeclaration(VariablesDeclaration variablesDeclaration); @Override void visitInitializer(Initializer initializer);  }
@Test public void testMatrixIdentityOk() throws Exception { final String program = "#version 300 es\n" + "precision highp float;\n" + "void main() {" + " mat2 m;" + " m;" + "}"; for (int i = 0; i < 20; i++) { final TranslationUnit tu = ParseHelper.parse(program); IdentityMutationFinder identityMutationFinder = new IdentityMutationFinder(tu, new RandomWrapper(i), GenerationParams.small(ShaderKind.FRAGMENT, false)); identityMutationFinder.findMutations().forEach(Expr2ExprMutation::apply); new StandardVisitor() { @Override public void visitFunctionCallExpr(FunctionCallExpr functionCallExpr) { super.visitFunctionCallExpr(functionCallExpr); if (!functionCallExpr.getCallee().equals(Constants.GLF_IDENTITY)) { return; } if (!(functionCallExpr.getArgs().get(0) instanceof VariableIdentifierExpr)) { return; } if (!(((VariableIdentifierExpr) functionCallExpr.getArgs().get(0)).getName() .equals("m"))) { return; } if (!(functionCallExpr.getArgs().get(1) instanceof BinaryExpr)) { return; } final BinaryExpr binaryExpr = (BinaryExpr) functionCallExpr.getArgs().get(1); if (!Arrays.asList(BinOp.DIV, BinOp.MUL).contains(binaryExpr.getOp())) { return; } if (!(binaryExpr.getRhs() instanceof TypeConstructorExpr)) { return; } final TypeConstructorExpr typeConstructorExpr = (TypeConstructorExpr) binaryExpr.getRhs(); if (!typeConstructorExpr.getTypename().equals(BasicType.MAT2X2.toString())) { return; } if (binaryExpr.getOp() == BinOp.MUL) { assertTrue(typeConstructorExpr.getNumArgs() == 1); if (typeConstructorExpr.getArg(0) instanceof FloatConstantExpr) { assertEquals("1.0", ((FloatConstantExpr) typeConstructorExpr.getArg(0)).getValue()); } } else { assertEquals(binaryExpr.getOp(), BinOp.DIV); assertTrue(typeConstructorExpr.getNumArgs() == 4); for (int i = 0; i < 4; i++) { if (typeConstructorExpr.getArg(i) instanceof FloatConstantExpr) { assertEquals("1.0", ((FloatConstantExpr) typeConstructorExpr.getArg(i)).getValue()); } } } } }.visit(tu); } }