mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-02 06:05:57 +00:00
Now formatting errors according to GCC standard format. Thanks @RoyJacobs. Closes #551
This commit is contained in:
commit
4b543b7de5
@ -384,7 +384,7 @@ public class KickC implements Callable<Integer> {
|
||||
compiler.compile(cFiles, effectiveDefines);
|
||||
} catch(CompileError e) {
|
||||
// Print the error and exit with compile error
|
||||
System.err.println(e.getMessage());
|
||||
System.err.println(e.format());
|
||||
return COMPILE_ERROR;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ public class AsmFragmentTemplate {
|
||||
*/
|
||||
private void initAsm() {
|
||||
// Parse the body ASM
|
||||
this.bodyAsm = AsmParser.parseAsm(this.body, new StatementSource(signature + ".asm", 1, this.body, 0, 0));
|
||||
this.bodyAsm = AsmParser.parseAsm(this.body, new StatementSource(signature + ".asm", 1, 1, this.body, -1, -1));
|
||||
// Generate a dummy instance to find clobber & cycles
|
||||
ProgramScope scope = new ProgramScope();
|
||||
LinkedHashMap<String, Value> bindings = new LinkedHashMap<>();
|
||||
|
@ -7,15 +7,15 @@ import org.antlr.v4.runtime.Token;
|
||||
/** Signals some error in the code (or compilation) */
|
||||
public class CompileError extends RuntimeException {
|
||||
|
||||
private String source;
|
||||
private StatementSource source;
|
||||
|
||||
public CompileError(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CompileError(String message, StatementSource source) {
|
||||
super(message+"\n"+(source==null?"":source.toString()));
|
||||
this.source = (source==null?"":source.toString());
|
||||
super(message);
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public CompileError(String message, Token token) {
|
||||
@ -30,8 +30,25 @@ public class CompileError extends RuntimeException {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
public StatementSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the CompileError using the GCC format, so that it may be easily parsed by IDEs and automated tools.
|
||||
* See https://www.gnu.org/prep/standards/html_node/Errors.html
|
||||
* <ul>
|
||||
* <li> sourcefile:lineno: message
|
||||
* <li> sourcefile:lineno:column: message
|
||||
* </ul>
|
||||
*/
|
||||
public String format() {
|
||||
StatementSource source = getSource();
|
||||
if(source != null && source.getFileName() != null) {
|
||||
return source.format() + " error: " + getMessage();
|
||||
} else {
|
||||
return getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class Initializers {
|
||||
} else {
|
||||
// Add an zero-filled array initializer
|
||||
if(typeSpec.getArraySpec().getArraySize() == null) {
|
||||
throw new CompileError("Error! Array has no declared size. ", statementSource);
|
||||
throw new CompileError("Array has no declared size.", statementSource);
|
||||
}
|
||||
return new ConstantArrayFilled(typePointer.getElementType(), typeSpec.getArraySpec().getArraySize());
|
||||
}
|
||||
@ -130,7 +130,7 @@ public class Initializers {
|
||||
if(SymbolTypeConversion.assignmentTypeMatch(typeSpec.getType(), inferredType))
|
||||
initValue = new CastValue(typeSpec.getType(), initValue);
|
||||
else
|
||||
throw new CompileError("ERROR! Type mismatch (" + typeSpec.getType().getTypeName() + ") cannot be assigned from (" + inferredType.getTypeName() + ").", source);
|
||||
throw new CompileError("Type mismatch (" + typeSpec.getType().getTypeName() + ") cannot be assigned from (" + inferredType.getTypeName() + ").", source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ public class VariableBuilderConfig {
|
||||
Optimization optimization = getOptimization(paramElements);
|
||||
MemoryArea memoryArea = getMemoryArea(paramElements);
|
||||
if((memoryArea == null && optimization == null) || paramElements.size() > 0)
|
||||
throw new CompileError("Error! Malformed var_model parameter " + pragmaParam, statementSource);
|
||||
throw new CompileError("Malformed var_model parameter " + pragmaParam, statementSource);
|
||||
for(Scope scope : scopes) {
|
||||
for(Type type : types) {
|
||||
MemoryArea mem = (memoryArea != null) ? memoryArea : getSetting(scope, type).memoryArea;
|
||||
|
@ -9,7 +9,10 @@ import org.antlr.v4.runtime.misc.Interval;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/** Contains information about the source of a program statement */
|
||||
public class StatementSource implements Serializable {
|
||||
@ -18,6 +21,8 @@ public class StatementSource implements Serializable {
|
||||
private String fileName;
|
||||
/** The line number of the start of the source. */
|
||||
private Integer lineNumber;
|
||||
/** The char position on the line of the start of the source. */
|
||||
private Integer charPosInLine;
|
||||
/** The source code. */
|
||||
private String code;
|
||||
/** The index of the first char of the source in the file. */
|
||||
@ -25,24 +30,26 @@ public class StatementSource implements Serializable {
|
||||
/** The index of the last char of the source in the file. */
|
||||
private int stopIndex;
|
||||
|
||||
public StatementSource(String fileName, Integer lineNumber, String code, int startIndex, int stopIndex) {
|
||||
public StatementSource(String fileName, Integer lineNumber, Integer charPosInLine, String code, int startIndex, int stopIndex) {
|
||||
this.fileName = fileName;
|
||||
this.lineNumber = lineNumber;
|
||||
this.charPosInLine = charPosInLine;
|
||||
this.code = code;
|
||||
this.startIndex = startIndex;
|
||||
this.stopIndex = stopIndex;
|
||||
}
|
||||
|
||||
/** An empty statement source. */
|
||||
public static StatementSource NONE = new StatementSource(null, null, null, 0, 0);
|
||||
public static StatementSource NONE = new StatementSource(null, null, null, null, -1, -1);
|
||||
|
||||
public StatementSource(Token tokenStart, Token tokenStop) {
|
||||
if(tokenStart != null && tokenStart.getStartIndex() != 0) {
|
||||
if(tokenStart != null && tokenStart.getStartIndex() >= 0) {
|
||||
this.startIndex = tokenStart.getStartIndex();
|
||||
CharStream stream = tokenStart.getInputStream();
|
||||
this.fileName = stream.getSourceName();
|
||||
this.lineNumber = tokenStart.getLine();
|
||||
if(tokenStop != null && tokenStop.getStopIndex() != 0) {
|
||||
this.charPosInLine = tokenStart.getCharPositionInLine();
|
||||
if(tokenStop != null && tokenStop.getStopIndex() >= this.startIndex) {
|
||||
this.stopIndex = tokenStop.getStopIndex();
|
||||
Interval interval = getInterval();
|
||||
this.code = stream.getText(interval);
|
||||
@ -198,6 +205,10 @@ public class StatementSource implements Serializable {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
public Integer getCharPosInLine() {
|
||||
return charPosInLine;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
@ -212,22 +223,30 @@ public class StatementSource implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if(getFileName() != null) {
|
||||
return "File " + getFileName() + "\nLine " + getLineNumber() + "\n" + getCode();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
return format();
|
||||
}
|
||||
|
||||
public String toStringShort() {
|
||||
if(getFileName() != null) {
|
||||
String fileName = getFileName();
|
||||
final int slashIdx = fileName.lastIndexOf("/");
|
||||
if(slashIdx>0)
|
||||
fileName = fileName.substring(slashIdx+1);
|
||||
return "File " + fileName + "\nLine " + getLineNumber() + "\n" + getCode();
|
||||
} else {
|
||||
/**
|
||||
* Format the statement source in GCC format
|
||||
* https://www.gnu.org/prep/standards/html_node/Errors.html
|
||||
* <li> sourcefile:lineno:
|
||||
* <li> sourcefile:lineno:column:
|
||||
*
|
||||
* @return The formatted source location
|
||||
*/
|
||||
public String format() {
|
||||
if(getFileName() == null)
|
||||
return "";
|
||||
Path currentPath = new File(".").toPath().toAbsolutePath();
|
||||
Path sourcePath = Paths.get(getFileName());
|
||||
Path relativePath = currentPath.relativize(sourcePath);
|
||||
String relativeFileName = relativePath.toString();
|
||||
if(getCharPosInLine() == null || getCharPosInLine() == 0) {
|
||||
// No relevant column idx - format without
|
||||
return String.format("%s:%s:", relativeFileName, getLineNumber());
|
||||
} else {
|
||||
// Format with column idx
|
||||
return String.format("%s:%s:%s:", relativeFileName, getLineNumber(), getCharPosInLine() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ public class AsmParser {
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
|
||||
StatementSource subSource =
|
||||
new StatementSource(source.getFileName(), source.getLineNumber() + line, source.getCode(), source.getStartIndex(), source.getStopIndex());
|
||||
new StatementSource(source.getFileName(), source.getLineNumber() + line, charPositionInLine, source.getCode(), source.getStartIndex(), source.getStopIndex());
|
||||
|
||||
throw new CompileError("Error parsing assembler. " + msg, subSource);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import dk.camelot64.kickc.SourceLoader;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.TargetPlatform;
|
||||
import dk.camelot64.kickc.model.statements.StatementSource;
|
||||
import dk.camelot64.kickc.preprocessor.CPreprocessor;
|
||||
import org.antlr.v4.runtime.*;
|
||||
|
||||
@ -95,7 +96,8 @@ public class CParser {
|
||||
int charPositionInLine,
|
||||
String msg,
|
||||
RecognitionException e) {
|
||||
throw new CompileError("Error parsing file " + recognizer.getInputStream().getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
|
||||
StatementSource source = new StatementSource(recognizer.getInputStream().getSourceName(), line, charPositionInLine, null, -1, -1);
|
||||
throw new CompileError("Error parsing file: " + msg, source);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -290,7 +292,8 @@ public class CParser {
|
||||
int charPositionInLine,
|
||||
String msg,
|
||||
RecognitionException e) {
|
||||
throw new CompileError("Error parsing file " + charStream.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
|
||||
StatementSource source = new StatementSource(charStream.getSourceName(), line, charPositionInLine, null, -1,-1);
|
||||
throw new CompileError("Error parsing file: " + msg, source);
|
||||
}
|
||||
});
|
||||
return lexer;
|
||||
|
@ -133,16 +133,16 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
for(KickCParser.PragmaContext pragmaConstructorFor : pragmaConstructorFors) {
|
||||
final List<KickCParser.PragmaParamContext> names = pragmaConstructorFor.pragmaParam();
|
||||
if(names.size() < 2)
|
||||
throw new CompileError("Error! #pragma constructor_for requires at least 2 parameters.", new StatementSource(pragmaConstructorFor));
|
||||
throw new CompileError("#pragma constructor_for requires at least 2 parameters.", new StatementSource(pragmaConstructorFor));
|
||||
final String constructorProcName = pragmaParamName(names.get(0));
|
||||
final Procedure constructorProc = program.getScope().getLocalProcedure(constructorProcName);
|
||||
if(constructorProc == null)
|
||||
throw new CompileError("Error! Constructor procedure not found " + constructorProcName, new StatementSource(pragmaConstructorFor));
|
||||
throw new CompileError("Constructor procedure not found " + constructorProcName, new StatementSource(pragmaConstructorFor));
|
||||
for(int i = 1; i < names.size(); i++) {
|
||||
final String procName = pragmaParamName(names.get(i));
|
||||
final Procedure proc = program.getScope().getLocalProcedure(procName);
|
||||
if(proc == null)
|
||||
throw new CompileError("Error! Procedure not found " + procName, new StatementSource(pragmaConstructorFor));
|
||||
throw new CompileError("Procedure not found " + procName, new StatementSource(pragmaConstructorFor));
|
||||
if(program.getLog().isVerboseParse())
|
||||
program.getLog().append("Added constructor procedure " + constructorProc.getRef().toString() + " to procedure " + proc.getRef().toString());
|
||||
proc.getConstructorRefs().add(constructorProc.getRef());
|
||||
@ -272,7 +272,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
*/
|
||||
private static KickCParser.PragmaParamContext pragmaParamSingle(KickCParser.PragmaContext ctx) {
|
||||
if(ctx.pragmaParam().size() != 1)
|
||||
throw new CompileError("Error! #pragma expects a single parameter!", new StatementSource(ctx));
|
||||
throw new CompileError("#pragma expects a single parameter!", new StatementSource(ctx));
|
||||
return ctx.pragmaParam().get(0);
|
||||
}
|
||||
|
||||
@ -285,10 +285,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
*/
|
||||
private static Number pragmaParamNumber(KickCParser.PragmaParamContext paramCtx) {
|
||||
if(!(paramCtx instanceof KickCParser.PragmaParamNumberContext))
|
||||
throw new CompileError("Error! Expected a NUMBER parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
throw new CompileError("Expected a NUMBER parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
final Number number = NumberParser.parseLiteral(((KickCParser.PragmaParamNumberContext) paramCtx).NUMBER().getText());
|
||||
if(number == null)
|
||||
throw new CompileError("Error! Expected a NUMBER parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
throw new CompileError("Expected a NUMBER parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
return number;
|
||||
}
|
||||
|
||||
@ -301,11 +301,11 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
*/
|
||||
private static Procedure.CallingConvention pragmaParamCallingConvention(KickCParser.PragmaParamContext paramCtx) {
|
||||
if(!(paramCtx instanceof KickCParser.PragmaParamCallingConventionContext))
|
||||
throw new CompileError("Error! Expected a CALLINGCONVENTION parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
throw new CompileError("Expected a CALLINGCONVENTION parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
final String callingConventionName = ((KickCParser.PragmaParamCallingConventionContext) paramCtx).CALLINGCONVENTION().getText();
|
||||
final Procedure.CallingConvention callingConvention = Procedure.CallingConvention.getCallingConvension(callingConventionName);
|
||||
if(callingConvention == null)
|
||||
throw new CompileError("Error! Expected a CALLINGCONVENTION parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
throw new CompileError("Expected a CALLINGCONVENTION parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
return callingConvention;
|
||||
}
|
||||
|
||||
@ -319,7 +319,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
*/
|
||||
private static String pragmaParamName(KickCParser.PragmaParamContext paramCtx) {
|
||||
if(!(paramCtx instanceof KickCParser.PragmaParamNameContext))
|
||||
throw new CompileError("Error! Expected a NAME parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
throw new CompileError("Expected a NAME parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
return ((KickCParser.PragmaParamNameContext) paramCtx).NAME().getText();
|
||||
}
|
||||
|
||||
@ -332,7 +332,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
*/
|
||||
private static String pragmaParamString(KickCParser.PragmaParamContext paramCtx) {
|
||||
if(!(paramCtx instanceof KickCParser.PragmaParamStringContext))
|
||||
throw new CompileError("Error! Expected a STRING parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
throw new CompileError("Expected a STRING parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
final String stringLiteral = ((KickCParser.PragmaParamStringContext) paramCtx).STRING().getText();
|
||||
return stringLiteral.substring(1, stringLiteral.length() - 1);
|
||||
}
|
||||
@ -363,7 +363,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
zp++;
|
||||
}
|
||||
} else {
|
||||
throw new CompileError("Error! Expected a NUMBER or RANGE parameter. Found '" + reserveCtx.getText() + "'.", new StatementSource(reserveCtx.getParent()));
|
||||
throw new CompileError("Expected a NUMBER or RANGE parameter. Found '" + reserveCtx.getText() + "'.", new StatementSource(reserveCtx.getParent()));
|
||||
}
|
||||
}
|
||||
return reservedZps;
|
||||
@ -409,7 +409,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
if(existingSymbol != null) {
|
||||
// Already declared - check equality
|
||||
if(!(existingSymbol instanceof Procedure) || !SymbolTypeConversion.procedureDeclarationMatch((Procedure) existingSymbol, procedure))
|
||||
throw new CompileError("Error! Conflicting declarations for: " + procedure.getFullName(), new StatementSource(ctx));
|
||||
throw new CompileError("Conflicting declarations for: " + procedure.getFullName(), new StatementSource(ctx));
|
||||
} else {
|
||||
// Not declared before - add it
|
||||
program.getScope().add(procedure);
|
||||
@ -429,7 +429,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
// Check that the body has not already been added
|
||||
final StatementSequence statementSequence = getCurrentProcedureCompilation().getStatementSequence();
|
||||
if(statementSequence != null && statementSequence.getStatements().size() > 0)
|
||||
throw new CompileError("Error! Redefinition of function: " + procedure.getFullName(), StatementSource.procedureBegin(ctx));
|
||||
throw new CompileError("Redefinition of function: " + procedure.getFullName(), StatementSource.procedureBegin(ctx));
|
||||
// Add the body
|
||||
addStatement(new StatementProcedureBegin(procedure.getRef(), StatementSource.procedureBegin(ctx), Comment.NO_COMMENTS));
|
||||
// Add parameter assignments
|
||||
@ -729,7 +729,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
String clobberString = ctx.STRING().getText().toUpperCase(Locale.ENGLISH);
|
||||
clobberString = clobberString.substring(1, clobberString.length() - 1);
|
||||
if(!clobberString.matches("[AXY]*")) {
|
||||
throw new CompileError("Error! Illegal clobber value " + clobberString, new StatementSource(ctx));
|
||||
throw new CompileError("Illegal clobber value " + clobberString, new StatementSource(ctx));
|
||||
}
|
||||
CpuClobber clobber = new CpuClobber(clobberString);
|
||||
return new AsmDirectiveClobber(clobber);
|
||||
@ -1668,7 +1668,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
} else {
|
||||
lValue = getCurrentScope().findVariable(varName);
|
||||
if(lValue == null) {
|
||||
throw new CompileError("Error! Loop variable not declared " + varName, statementSource);
|
||||
throw new CompileError("Loop variable not declared " + varName, statementSource);
|
||||
}
|
||||
}
|
||||
boolean initialAssignment = (varDecl.getEffectiveType() != null);
|
||||
@ -1869,7 +1869,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
RValue rValue;
|
||||
if(exprCtx != null) {
|
||||
if(SymbolType.VOID.equals(procedure.getReturnType())) {
|
||||
throw new CompileError("Error! Return value from void function " + procedure.getFullName(), new StatementSource(ctx));
|
||||
throw new CompileError("Return value from void function " + procedure.getFullName(), new StatementSource(ctx));
|
||||
}
|
||||
PrePostModifierHandler.addPreModifiers(this, exprCtx, new StatementSource(ctx));
|
||||
rValue = (RValue) this.visit(exprCtx);
|
||||
@ -2096,7 +2096,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
varDecl.setVarDeclType(arrayDeclType);
|
||||
return null;
|
||||
} else {
|
||||
throw new CompileError("ERROR! Non-standard array declaration. Allow using commandline option -Warraytype", new StatementSource(ctx));
|
||||
throw new CompileError("Non-standard array declaration. Allow using commandline option -Warraytype", new StatementSource(ctx));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2187,7 +2187,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
throw new CompileError("const variable may not be modified " + val.toString(), new StatementSource(ctx));
|
||||
}
|
||||
if(!(val instanceof LValue)) {
|
||||
throw new CompileError("Error! Illegal assignment Lvalue " + val.toString(), new StatementSource(ctx));
|
||||
throw new CompileError("Illegal assignment Lvalue " + val.toString(), new StatementSource(ctx));
|
||||
}
|
||||
LValue lValue = (LValue) val;
|
||||
if(lValue instanceof VariableRef && ((VariableRef) lValue).isIntermediate()) {
|
||||
@ -2207,7 +2207,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
// Assignment (rValue/lValue)
|
||||
Object value = visit(ctx.expr(0));
|
||||
if(!(value instanceof LValue)) {
|
||||
throw new CompileError("Error! Illegal assignment Lvalue " + value.toString(), new StatementSource(ctx));
|
||||
throw new CompileError("Illegal assignment Lvalue " + value.toString(), new StatementSource(ctx));
|
||||
}
|
||||
LValue lValue = (LValue) value;
|
||||
if(lValue instanceof VariableRef && ((VariableRef) lValue).isIntermediate()) {
|
||||
@ -2616,7 +2616,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
// Either forward reference or a non-existing variable. Create a forward reference for later resolving.
|
||||
return new ForwardVariableRef(ctx.NAME().getText());
|
||||
}
|
||||
throw new CompileError("Error! Unhandled symbol " + symbol.toString(program));
|
||||
throw new CompileError("Unhandled symbol " + symbol.toString(program));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,20 +24,20 @@ public class Pass1AssertInterrupts extends Pass1Base {
|
||||
ProcedureRef procedureRef = ((StatementCalling) statement).getProcedure();
|
||||
Procedure procedure = getScope().getProcedure(procedureRef);
|
||||
if(procedure.getInterruptType()!=null) {
|
||||
throw new CompileError("Error! Interrupts cannot be called.", statement.getSource());
|
||||
throw new CompileError("Interrupts cannot be called.", statement.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Procedure procedure : getScope().getAllProcedures(true)) {
|
||||
if(procedure.getInterruptType()!=null) {
|
||||
if(procedure.isDeclaredInline()) {
|
||||
throw new CompileError("Error! Interrupts cannot be inlined. " + procedure.toString());
|
||||
throw new CompileError("Interrupts cannot be inlined. " + procedure.toString());
|
||||
}
|
||||
if(procedure.getParameters().size()>0) {
|
||||
throw new CompileError("Error! Interrupts cannot have parameters. " + procedure.toString());
|
||||
throw new CompileError("Interrupts cannot have parameters. " + procedure.toString());
|
||||
}
|
||||
if(!SymbolType.VOID.equals(procedure.getReturnType())) {
|
||||
throw new CompileError("Error! Interrupts cannot return anything. " + procedure.toString());
|
||||
throw new CompileError("Interrupts cannot return anything. " + procedure.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class Pass1AssertNoLValueIntermediate extends Pass1Base {
|
||||
VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable();
|
||||
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(intermediateVar, getGraph(), getScope());
|
||||
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
|
||||
throw new CompileError("Error! LValue is illegal. " + statement + " - definition of lValue " + varAssignment, varAssignment.getSource());
|
||||
throw new CompileError("LValue is illegal. " + statement + " - definition of lValue " + varAssignment, varAssignment.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public class Pass1AssertNoModifyVars extends Pass1Base {
|
||||
if(!statementLValue.isInitialAssignment() && statementLValue.getlValue() instanceof VariableRef) {
|
||||
Variable assignedVar = getScope().getVariable((VariableRef) statementLValue.getlValue());
|
||||
if(assignedVar.isNoModify())
|
||||
throw new CompileError("Error! const variable may not be modified! " + assignedVar.toString(), statement);
|
||||
throw new CompileError("const variable may not be modified! " + assignedVar.toString(), statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
|
||||
Collection<VariableRef> used = referenceInfos.getUsedVars(statement);
|
||||
for(VariableRef usedRef : used) {
|
||||
if(!defined.contains(usedRef)) {
|
||||
throw new CompileError("Error! Variable used before being defined " + usedRef.toString(getProgram()) + " in " + statement.toString(getProgram(), false), statement.getSource());
|
||||
throw new CompileError("Variable used before being defined " + usedRef.toString(getProgram()) + " in " + statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
}
|
||||
Collection<VariableRef> defd = referenceInfos.getDefinedVars(statement);
|
||||
@ -143,7 +143,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
|
||||
// Found used variables - check that they are defined
|
||||
for(SymbolVariableRef usedRef : used) {
|
||||
if(!defined.contains(usedRef)) {
|
||||
throw new CompileError("Error! Variable used before being defined " + usedRef.toString(getProgram()) + " in " + phiBlock.toString(getProgram(), false), phiBlock.getSource());
|
||||
throw new CompileError("Variable used before being defined " + usedRef.toString(getProgram()) + " in " + phiBlock.toString(getProgram(), false), phiBlock.getSource());
|
||||
}
|
||||
}
|
||||
// Add all variables fefined by the PHI block
|
||||
|
@ -43,7 +43,7 @@ public class Pass1CallVoidReturns extends Pass2SsaOptimization {
|
||||
if(usages.size() > 0) {
|
||||
final Integer usageIdx = usages.iterator().next();
|
||||
final Statement usage = getProgram().getStatementInfos().getStatement(usageIdx);
|
||||
throw new CompileError("Error! Function " + procedure.getLocalName() + " does not return a value! ", usage);
|
||||
throw new CompileError("Function " + procedure.getLocalName() + " does not return a value! ", usage);
|
||||
} else {
|
||||
// Delete the temporary variable
|
||||
final Variable var = getScope().getVar(tmpVar);
|
||||
|
@ -64,10 +64,10 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
|
||||
final List<RValue> parameters = printfCall.getParameters();
|
||||
final RValue formatParameter = getParameterValue(parameters, 0, printfCall);
|
||||
if(!(formatParameter instanceof ConstantValue))
|
||||
throw new CompileError("Error! Only constant printf() format parameter supported!", statement);
|
||||
throw new CompileError("Only constant printf() format parameter supported!", statement);
|
||||
final ConstantLiteral formatLiteral = ((ConstantValue) formatParameter).calculateLiteral(getProgram().getScope());
|
||||
if(!(formatLiteral instanceof ConstantString))
|
||||
throw new CompileError("Error! printf() format parameter must be a string!", statement);
|
||||
throw new CompileError("printf() format parameter must be a string!", statement);
|
||||
final String formatString = ((ConstantString) formatLiteral).getString();
|
||||
final StringEncoding formatEncoding = ((ConstantString) formatLiteral).getEncoding();
|
||||
|
||||
@ -103,10 +103,10 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
|
||||
final String paramField = matcher.group(1);
|
||||
// Ensure that all fields use parameter index syntax!
|
||||
if(paramField == null && fieldParamIdx && !typeField.equals("%"))
|
||||
throw new CompileError("Error! If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!", statement);
|
||||
throw new CompileError("If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!", statement);
|
||||
if(paramField != null) {
|
||||
if(!fieldParamIdx && paramIdx > 1)
|
||||
throw new CompileError("Error! If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!", statement);
|
||||
throw new CompileError("If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!", statement);
|
||||
fieldParamIdx = true;
|
||||
paramIdx = Integer.parseInt(paramField.substring(0, paramField.length() - 1));
|
||||
}
|
||||
@ -256,7 +256,7 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
|
||||
*/
|
||||
private RValue getParameterValue(List<RValue> parameters, int paramIdx, StatementCall printfCall) {
|
||||
if(parameters.size()<=paramIdx)
|
||||
throw new CompileError("Error! printf missing parameter with index "+paramIdx, printfCall);
|
||||
throw new CompileError("printf missing parameter with index "+paramIdx, printfCall);
|
||||
return parameters.get(paramIdx);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ public class Pass1ResolveForwardReferences extends Pass1Base {
|
||||
programValue.set(symbol.getRef());
|
||||
} else {
|
||||
getLog().append("ERROR! Unknown variable " + varName);
|
||||
throw new CompileError("ERROR! Unknown variable " + varName, currentStmt.getSource());
|
||||
throw new CompileError("Unknown variable " + varName, currentStmt.getSource());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -38,10 +38,10 @@ public class Pass2RangeResolving extends Pass2SsaOptimization {
|
||||
ConstantLiteral firstLiteral = ((ConstantValue) rangeValue.getRangeFirst()).calculateLiteral(getScope());
|
||||
ConstantLiteral lastLiteral = ((ConstantValue) rangeValue.getRangeLast()).calculateLiteral(getScope());
|
||||
if(!(firstLiteral instanceof ConstantEnumerable)) {
|
||||
throw new CompileError("Error! Ranged for() has non-integer first value in the range " + currentStmt.getSource().toString());
|
||||
throw new CompileError("Ranged for() has non-integer first value in the range " + currentStmt.getSource().toString(), currentStmt);
|
||||
}
|
||||
if(!(lastLiteral instanceof ConstantEnumerable)) {
|
||||
throw new CompileError("Error! Ranged for() has non-integer first value in the range " + currentStmt.getSource().toString());
|
||||
throw new CompileError("Ranged for() has non-integer first value in the range " + currentStmt.getSource().toString(), currentStmt);
|
||||
}
|
||||
|
||||
ConstantEnumerable first = (ConstantEnumerable) firstLiteral;
|
||||
|
@ -38,11 +38,11 @@ public class Pass3AssertConstants extends Pass2SsaAssertion {
|
||||
if(statement instanceof StatementKickAsm) {
|
||||
RValue bytes = ((StatementKickAsm) statement).getBytes();
|
||||
if(bytes != null && !(bytes instanceof ConstantValue)) {
|
||||
throw new CompileError("Error! KickAssembler bytes is not constant " + bytes.toString(), statement);
|
||||
throw new CompileError("KickAssembler bytes is not constant " + bytes.toString(), statement);
|
||||
}
|
||||
RValue cycles = ((StatementKickAsm) statement).getCycles();
|
||||
if(cycles != null && !(cycles instanceof ConstantValue)) {
|
||||
throw new CompileError("Error! KickAssembler cycles is not constant " + cycles.toString(), statement);
|
||||
throw new CompileError("KickAssembler cycles is not constant " + cycles.toString(), statement);
|
||||
}
|
||||
} else if(statement instanceof StatementAsm) {
|
||||
StatementAsm statementAsm = (StatementAsm) statement;
|
||||
@ -60,14 +60,14 @@ public class Pass3AssertConstants extends Pass2SsaAssertion {
|
||||
// Referencing load/store is fine!
|
||||
continue;
|
||||
else
|
||||
throw new CompileError("Error! Inline ASM reference is not constant " + label, statement);
|
||||
throw new CompileError("Inline ASM reference is not constant " + label, statement);
|
||||
}
|
||||
} else if(statement instanceof StatementKickAsm) {
|
||||
StatementKickAsm statementAsm = (StatementKickAsm) statement;
|
||||
List<SymbolRef> uses = statementAsm.getUses();
|
||||
for(SymbolRef use : uses) {
|
||||
if(!(use instanceof ConstantRef)) {
|
||||
throw new CompileError("Error! Inline KickAsm reference is not constant " + use, statement);
|
||||
throw new CompileError("Inline KickAsm reference is not constant " + use, statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,13 @@ public class Pass3AssertNoMulDivMod extends Pass2SsaAssertion {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(Operators.MULTIPLY.equals(assignment.getOperator())) {
|
||||
throw new CompileError("ERROR! Runtime multiplication not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
throw new CompileError("Runtime multiplication not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
if(Operators.DIVIDE.equals(assignment.getOperator())) {
|
||||
throw new CompileError("ERROR! Runtime division not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
throw new CompileError("Runtime division not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
if(Operators.MODULO.equals(assignment.getOperator())) {
|
||||
throw new CompileError("ERROR! Runtime modulo not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
throw new CompileError("Runtime modulo not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -804,7 +804,7 @@ public class Pass4CodeGeneration {
|
||||
generateStatementAsm(asm, block, statement, aluState, true);
|
||||
} catch(AsmFragmentTemplateSynthesizer.UnknownFragmentException e) {
|
||||
if(warnFragmentMissing) {
|
||||
program.getLog().append("Warning! Unknown fragment for statement " + statement.toString(program, false) + "\nMissing ASM fragment " + e.getFragmentSignature() + "\n" + statement.getSource().toStringShort());
|
||||
program.getLog().append("Warning! Unknown fragment for statement " + statement.toString(program, false) + "\nMissing ASM fragment " + e.getFragmentSignature() + "\n" + statement.getSource().format());
|
||||
asm.addLine(new AsmInlineKickAsm(".assert \"Missing ASM fragment " + e.getFragmentSignature() + "\", 0, 1", 0L, 0L));
|
||||
} else {
|
||||
throw new CompileError("Unknown fragment for statement " + statement.toString(program, false) + "\nMissing ASM fragment " + e.getFragmentSignature(), statement.getSource());
|
||||
|
@ -25,7 +25,7 @@ public class PassNAssertTypeDeref extends Pass2SsaAssertion {
|
||||
RValue pointer = ((PointerDereference) programValue.get()).getPointer();
|
||||
SymbolType pointertype = SymbolTypeInference.inferType(getProgram().getScope(), pointer);
|
||||
if(!SymbolType.VAR.equals(pointertype) && !(pointertype instanceof SymbolTypePointer))
|
||||
throw new CompileError("Error! Dereferencing a non-pointer type "+pointertype.getTypeName(), currentStmt);
|
||||
throw new CompileError("Dereferencing a non-pointer type "+pointertype.getTypeName(), currentStmt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class PassNAssertTypeMatch extends Pass2SsaAssertion {
|
||||
if(SymbolTypeConversion.assignmentTypeMatch(lValueType, rValueType)) return;
|
||||
// Types do not match
|
||||
getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false));
|
||||
throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource());
|
||||
throw new CompileError("Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ public class CPreprocessor implements TokenSource {
|
||||
final String fileName = fileNameToken.getText();
|
||||
cParser.includeCFile(fileName, true);
|
||||
} else {
|
||||
throw new CompileError("Error! #include not followed by file!", new StatementSource(inputToken, fileNameToken));
|
||||
throw new CompileError("#include not followed by file!", new StatementSource(inputToken, fileNameToken));
|
||||
}
|
||||
}
|
||||
|
||||
@ -286,7 +286,7 @@ public class CPreprocessor implements TokenSource {
|
||||
final Token paramToken = cTokenSource.nextToken();
|
||||
if(paramToken.getType() == KickCLexer.PAR_END) {
|
||||
if(!commaNext && macroParameters.size() > 0)
|
||||
throw new CompileError("Error! #define declared parameter list ends with COMMA.", paramToken);
|
||||
throw new CompileError("#define declared parameter list ends with COMMA.", paramToken);
|
||||
// We reached the end of the parameters
|
||||
break;
|
||||
} else if(!commaNext && paramToken.getType() == KickCLexer.NAME) {
|
||||
@ -298,7 +298,7 @@ public class CPreprocessor implements TokenSource {
|
||||
commaNext = false;
|
||||
else
|
||||
// Unexpected token
|
||||
throw new CompileError("Error! #define declared parameter not a NAME.", paramToken);
|
||||
throw new CompileError("#define declared parameter not a NAME.", paramToken);
|
||||
}
|
||||
}
|
||||
final ArrayList<Token> macroBody = readBody(cTokenSource);
|
||||
|
@ -170,11 +170,11 @@ public class TestPreprocessor {
|
||||
@Test
|
||||
public void testErrors() {
|
||||
// Declared parameters are not names
|
||||
assertError("#define f(x,1) x", "Error! #define declared parameter not a NAME.", true);
|
||||
assertError("#define f(x,1) x", "#define declared parameter not a NAME.", true);
|
||||
// Declared parameter list ends with comma
|
||||
assertError("#define f(x,y,) x", "#define declared parameter list ends with COMMA.", true);
|
||||
// Number of parameters not matching
|
||||
assertError("#define f(x,y) x+y\nf(7);", "Error! Wrong number of macro parameters. Expected 2 was 1", true);
|
||||
assertError("#define f(x,y) x+y\nf(7);", "Wrong number of macro parameters. Expected 2 was 1", true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,9 +216,10 @@ public class TestPreprocessor {
|
||||
System.out.println("Got error: " + e.getMessage());
|
||||
// expecting error!
|
||||
assertTrue(e.getMessage().contains(expectError), "Error message expected '" + expectError + "' - was:" + e.getMessage());
|
||||
if(expectLineNumber) {
|
||||
// expecting line number!
|
||||
assertTrue(e.getMessage().contains("Line"), "Error message expected line number - was:" + e.getMessage());
|
||||
if (expectLineNumber) {
|
||||
// expecting a source for the error, so it may be related back to a file/line
|
||||
assertNotNull(e.getSource());
|
||||
assertNotNull(e.getSource().getLineNumber());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
package dk.camelot64.kickc.test;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.Compiler;
|
||||
import dk.camelot64.kickc.SourceLoader;
|
||||
import dk.camelot64.kickc.TmpDirManager;
|
||||
import dk.camelot64.kickc.*;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
@ -28,8 +26,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Compile a number of source files and compare the resulting assembler with expected output
|
||||
@ -186,19 +183,29 @@ public class TestPrograms {
|
||||
compileAndCompare("pragma-unknown.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorFormatter() throws IOException, URISyntaxException {
|
||||
// Error on a char
|
||||
assertError("printf-error-6.c", "printf-error-6.c:7:5: error: printf missing parameter with index 1");
|
||||
// Error on a line
|
||||
assertError("library-constructor-error-2.c", "library-constructor-error-2.c:4: error: Procedure not found print");
|
||||
// Error without a line
|
||||
assertError("cstyle-decl-function-missing.c", "Error! Function body is never defined: sum", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLibraryConstructorError2() throws IOException, URISyntaxException {
|
||||
assertError("library-constructor-error-2.c", "Error! Procedure not found print");
|
||||
assertError("library-constructor-error-2.c", "Procedure not found print");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLibraryConstructorError1() throws IOException, URISyntaxException {
|
||||
assertError("library-constructor-error-1.c", "Error! Constructor procedure not found my_init");
|
||||
assertError("library-constructor-error-1.c", "Constructor procedure not found my_init");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLibraryConstructorError0() throws IOException, URISyntaxException {
|
||||
assertError("library-constructor-error-0.c", "Error! #pragma constructor_for requires at least 2 parameters.");
|
||||
assertError("library-constructor-error-0.c", "#pragma constructor_for requires at least 2 parameters.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -570,7 +577,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testDoubleCallProblem() throws IOException, URISyntaxException {
|
||||
assertError("double-call-problem.c", "Error! Function clrscr does not return a value! ");
|
||||
assertError("double-call-problem.c", "Function clrscr does not return a value! ");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -615,27 +622,27 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testPrintfError6() throws IOException, URISyntaxException {
|
||||
assertError("printf-error-6.c", "Error! printf missing parameter with index 1");
|
||||
assertError("printf-error-6.c", "printf missing parameter with index 1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintfError5() throws IOException, URISyntaxException {
|
||||
assertError("printf-error-5.c", "Error! printf() format parameter must be a string!");
|
||||
assertError("printf-error-5.c", "printf() format parameter must be a string!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintfError4() throws IOException, URISyntaxException {
|
||||
assertError("printf-error-4.c", "Error! Only constant printf() format parameter supported!");
|
||||
assertError("printf-error-4.c", "Only constant printf() format parameter supported!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintfError3() throws IOException, URISyntaxException {
|
||||
assertError("printf-error-3.c", "Error! If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!");
|
||||
assertError("printf-error-3.c", "If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintfError2() throws IOException, URISyntaxException {
|
||||
assertError("printf-error-2.c", "Error! If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!");
|
||||
assertError("printf-error-2.c", "If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -780,12 +787,12 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testCStyleDeclVarMismatch() throws IOException, URISyntaxException {
|
||||
assertError("cstyle-decl-var-mismatch.c", "Error! Conflicting declarations for: SCREEN");
|
||||
assertError("cstyle-decl-var-mismatch.c", "Conflicting declarations for: SCREEN");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCStyleDeclVarRedefinition() throws IOException, URISyntaxException {
|
||||
assertError("cstyle-decl-var-redefinition.c", "Error! Redefinition of variable: SCREEN");
|
||||
assertError("cstyle-decl-var-redefinition.c", "Redefinition of variable: SCREEN");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -800,12 +807,12 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testCStyleDeclFunctionRedefinition() throws IOException, URISyntaxException {
|
||||
assertError("cstyle-decl-function-redefinition.c", "Error! Redefinition of function: sum");
|
||||
assertError("cstyle-decl-function-redefinition.c", "Redefinition of function: sum");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCStyleDeclFunctionMismatch() throws IOException, URISyntaxException {
|
||||
assertError("cstyle-decl-function-mismatch.c", "Error! Conflicting declarations for: sum");
|
||||
assertError("cstyle-decl-function-mismatch.c", "Conflicting declarations for: sum");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -925,7 +932,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testVarModelUnknown() throws IOException, URISyntaxException {
|
||||
assertError("varmodel-unknown.c", "Error! Malformed var_model parameter");
|
||||
assertError("varmodel-unknown.c", "Malformed var_model parameter");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1414,7 +1421,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testFunctionAsArray() throws IOException, URISyntaxException {
|
||||
assertError("function-as-array.c", "Error! Dereferencing a non-pointer type void()");
|
||||
assertError("function-as-array.c", "Dereferencing a non-pointer type void()");
|
||||
}
|
||||
|
||||
//@Test
|
||||
@ -3679,7 +3686,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testUnrollInfinite() throws IOException, URISyntaxException {
|
||||
assertError("unroll-infinite.c", "Loop cannot be unrolled.", false);
|
||||
assertError("unroll-infinite.c", "Loop cannot be unrolled.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -3784,7 +3791,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testForRangedNpe() throws IOException, URISyntaxException {
|
||||
assertError("forranged-npe.c", "Error! Loop variable not declared i");
|
||||
assertError("forranged-npe.c", "Loop variable not declared i");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -3889,7 +3896,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testLoopNpe() throws IOException, URISyntaxException {
|
||||
assertError("loop-npe.c", "Error! Loop variable not declared");
|
||||
assertError("loop-npe.c", "Loop variable not declared");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -4229,7 +4236,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testArraysNonstandardSyntax() throws IOException, URISyntaxException {
|
||||
assertError("arrays-nonstandard-syntax.c", "ERROR! Non-standard array declaration.");
|
||||
assertError("arrays-nonstandard-syntax.c", "Non-standard array declaration.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -4735,7 +4742,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testReturnFromVoid() throws IOException, URISyntaxException {
|
||||
assertError("returnfromvoid.c", "Error! Return value from void function");
|
||||
assertError("returnfromvoid.c", "Return value from void function");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -4750,7 +4757,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testInvalidConstType() throws IOException, URISyntaxException {
|
||||
assertError("invalid-consttype.c", "Constant init-value has a non-matching type", false);
|
||||
assertError("invalid-consttype.c", "Constant init-value has a non-matching type");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -4890,16 +4897,22 @@ public class TestPrograms {
|
||||
assertError(kcFile, expectError, true);
|
||||
}
|
||||
|
||||
private void assertError(String kcFile, String expectError, boolean expectLineNumber) throws IOException, URISyntaxException {
|
||||
private void assertError(String kcFile, String expectError, boolean expectSource) throws IOException, URISyntaxException {
|
||||
try {
|
||||
compileAndCompare(kcFile);
|
||||
} catch(CompileError e) {
|
||||
System.out.println("Got error: " + e.getMessage());
|
||||
final String error = e.format();
|
||||
System.out.println("Got error: " + error);
|
||||
// expecting error!
|
||||
assertTrue(e.getMessage().contains(expectError), "Error message expected '" + expectError + "' - was:" + e.getMessage());
|
||||
if(expectLineNumber) {
|
||||
// expecting line number!
|
||||
assertTrue(e.getMessage().contains("Line"), "Error message expected line number - was:" + e.getMessage());
|
||||
assertTrue(error.contains(expectError), "Error message expected '" + expectError + "' - was:" + error);
|
||||
if(expectSource) {
|
||||
// expecting a source for the error, so it may be related back to a file/line
|
||||
assertNotNull(e.getSource(), "Error source expected");
|
||||
assertNotNull(e.getSource().getFileName(), "Error file name expected");
|
||||
assertNotNull(e.getSource().getLineNumber(), "Error line number expected");
|
||||
assertNotNull(e.getSource().getCharPosInLine(), "Error charpos expected");
|
||||
} else {
|
||||
assertTrue(e.getSource() == null || e.getSource().getFileName() == null, "No error information expected");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user