Commit 02517dde authored by Miklos Magyari's avatar Miklos Magyari
Browse files

OOP: semantic check - abstract functions can only be declared in...


OOP: semantic check - abstract functions can only be declared in abstract/trait classes (issue #427)
Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent a507ef78
......@@ -75,6 +75,19 @@ type class @trait BadTraitClass {
}
type class ClassWithAbstract1 {
function @abstract f_abs();
}
type class @final ClassWithAbstract2 {
function @abstract f_abs();
}
type class @trait ClassWithAbstract3 {
function @abstract f_abs();
}
type class SuperClass {
var integer vl_a;
template MyUnion t_union := { a := 10 }
......
......@@ -83,7 +83,7 @@ type class MembersClass {
}
}
type class TraitClass {
type class @trait TraitClass {
public function @abstract f_func(in integer pl_in);
}
......
......@@ -49,6 +49,7 @@ import org.eclipse.titan.designer.AST.TTCN3.attributes.SingleWithAttribute;
import org.eclipse.titan.designer.AST.TTCN3.attributes.SingleWithAttribute.Attribute_Type;
import org.eclipse.titan.designer.AST.TTCN3.statements.StatementBlock;
import org.eclipse.titan.designer.AST.TTCN3.types.ClassTypeBody;
import org.eclipse.titan.designer.AST.TTCN3.types.Class_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Component_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Port_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Referenced_Type;
......@@ -115,6 +116,7 @@ public final class Def_Function extends Definition implements IParameterisedAssi
private static final String CLASSNORUNSON = "Class functions cannot have a `runs on` clause";
private static final String CLASSNOMTC = "Class functions cannot have an `mtc` clause";
private static final String CLASSNOSYSTEM = "Class functions cannot have a `system` clause";
private static final String ABSTRACTFUNCTION = "Abstract function can only be declared in an abstract or trait class";
private static final String KIND = "function";
......@@ -139,6 +141,8 @@ public final class Def_Function extends Definition implements IParameterisedAssi
private final boolean isClassFunction;
private final boolean isAbstract;
private final boolean isFinal;
private final Location modifierLocation;
// stores whether this function can be started or not
private boolean isStartable;
......@@ -148,7 +152,7 @@ public final class Def_Function extends Definition implements IParameterisedAssi
final Reference mtcReference, final Reference systemReference, final Reference portReference,
final Type returnType, final boolean returnsTemplate, final TemplateRestriction.Restriction_type templateRestriction,
final StatementBlock block,
boolean isClassFunction, boolean isAbstract, boolean isFinal) {
boolean isClassFunction, boolean isAbstract, boolean isFinal, Location modifierLocation) {
super(identifier);
assignmentType = (returnType == null) ? Assignment_type.A_FUNCTION : (returnsTemplate ? Assignment_type.A_FUNCTION_RTEMP
: Assignment_type.A_FUNCTION_RVAL);
......@@ -168,6 +172,7 @@ public final class Def_Function extends Definition implements IParameterisedAssi
this.isClassFunction = isClassFunction;
this.isAbstract = isAbstract;
this.isFinal = isFinal;
this.modifierLocation = modifierLocation;
this.prototype = EncodingPrototype_type.NONE;
inputType = null;
......@@ -200,7 +205,7 @@ public final class Def_Function extends Definition implements IParameterisedAssi
final Type returnType, final boolean returnsTemplate, final TemplateRestriction.Restriction_type templateRestriction,
final StatementBlock block) {
this(identifier, formalParameters, runsOnRef, mtcReference, systemReference, portReference, returnType,
returnsTemplate, templateRestriction, block, false, false, false);
returnsTemplate, templateRestriction, block, false, false, false, null);
}
/**
......@@ -421,6 +426,16 @@ public final class Def_Function extends Definition implements IParameterisedAssi
if (systemReference!= null) {
systemReference.getLocation().reportSemanticError(CLASSNOSYSTEM);
}
if (isAbstract()) {
final Scope parent = getMyScope().getParentScope();
if (parent instanceof ClassTypeBody) {
final Class_Type myclass = ((ClassTypeBody)parent).getMyType();
if (! (myclass.isAbstract() || myclass.isTrait())) {
modifierLocation.reportSemanticError(ABSTRACTFUNCTION);
}
}
}
} else {
if (runsOnRef != null && portReference != null) {
runsOnRef.getLocation().reportSemanticError("A `runs on' and a `port' clause cannot be present at the same time.");
......
......@@ -9186,12 +9186,13 @@ pr_ClassFunctionDef returns[Def_Function def_func]
boolean isAbstract = false;
boolean isFinal = false;
boolean isTrait = false;
Location modifierLocation = null;
}:
(
pr_ExtKeyword?
col = pr_FunctionKeyword
( fm = pr_FinalModifier { isFinal = $fm.isFinal; } )?
( am = pr_AbstractModifier { isAbstract = $am.isAbstract; } )?
( fm = pr_FinalModifier { isFinal = $fm.isFinal; modifierLocation = getLocation($fm.start); } )?
( am = pr_AbstractModifier { isAbstract = $am.isAbstract; modifierLocation = getLocation($am.start); } )?
pr_DeterministicModifier?
id = pr_Identifier
start1 = pr_LParen
......@@ -9217,7 +9218,8 @@ pr_ClassFunctionDef returns[Def_Function def_func]
if($id.identifier != null) {
if(parameters == null) { parameters = new FormalParameterList(new ArrayList<FormalParameter>()); }
parameters.setLocation(getLocation( $start1.start, $end.stop));
$def_func = new Def_Function($id.identifier, parameters, runsonHelper.runsonReference, runsonHelper.mtcReference, runsonHelper.systemReference, portReference, returnType, returnsTemplate, templateRestriction, statementBlock, true, isAbstract, isFinal);
$def_func = new Def_Function($id.identifier, parameters, runsonHelper.runsonReference, runsonHelper.mtcReference, runsonHelper.systemReference,
portReference, returnType, returnsTemplate, templateRestriction, statementBlock, true, isAbstract, isFinal, modifierLocation);
$def_func.setLocation(getLocation( $col.start, $sb.stop));
$def_func.setCommentLocation( getLastCommentLocation( $start ) );
}
......@@ -9255,7 +9257,7 @@ pr_ClassConstructorDef returns[Def_Function def_func]
if(parameters == null) { parameters = new FormalParameterList(new ArrayList<FormalParameter>()); }
parameters.setLocation(getLocation( $pstart.start, $pstop.stop));
Identifier id = new Identifier( Identifier_type.ID_TTCN, "create", getLocation($id.start, $id.stop ) );
$def_func = new Def_Function(id, parameters, null, null, null, null, null, false, null, statementBlock, true, false, false);
$def_func = new Def_Function(id, parameters, null, null, null, null, null, false, null, statementBlock, true, false, false, null);
$def_func.setLocation(getLocation( $id.start, $sb.stop));
$def_func.setCommentLocation( getLastCommentLocation( $start ) );
};
......
......@@ -45,7 +45,7 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(57);
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(59);
int lineNum = 28;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10;
......@@ -79,7 +79,11 @@ public class OOP_Semantic_tests {
lineNum += 5;
markersToCheck.add(new MarkerToCheck("Trait classes can only declare abstract methods", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Trait method cannot have a function body", ++lineNum, IMarker.SEVERITY_ERROR));
lineNum += 17;
lineNum += 7;
markersToCheck.add(new MarkerToCheck("Abstract function can only be declared in an abstract or trait class", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 4;
markersToCheck.add(new MarkerToCheck("Abstract function can only be declared in an abstract or trait class", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 19;
markersToCheck.add(new MarkerToCheck("Reference to non-existent field `nonexist' in union template for type `@classesNegativeSemantic.MyUnion'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 4;
markersToCheck.add(new MarkerToCheck("Local Definiton `vl_b' collides with definition inherited from class type `@classesNegativeSemantic.SubClass'", lineNum, IMarker.SEVERITY_ERROR));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment