Commit b034d937 authored by Miklos Magyari's avatar Miklos Magyari
Browse files

OOP: sematic check - overridden method return type


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 2329d438
...@@ -304,8 +304,8 @@ type class ClassWithPrivate { ...@@ -304,8 +304,8 @@ type class ClassWithPrivate {
return 1; return 1;
} }
function f_override2(in float pl_float) return integer { function f_override2(in float pl_float) return charstring {
return 1; return "xyz";
} }
public function f_override3(in float pl_float) return integer { public function f_override3(in float pl_float) return integer {
...@@ -319,6 +319,10 @@ type class ClassWithPrivate { ...@@ -319,6 +319,10 @@ type class ClassWithPrivate {
function f_override5() { function f_override5() {
} }
function f_override6(in float pl_float) return octetstring {
return 'AB'O;
}
} }
type class ClassOverride1 { type class ClassOverride1 {
...@@ -340,13 +344,17 @@ type class ClassWithPrivateExt extends ClassWithPrivate { ...@@ -340,13 +344,17 @@ type class ClassWithPrivateExt extends ClassWithPrivate {
return pl_float; return pl_float;
} }
public function f_override3(charstring pl_float) return charstring { public function f_override3(charstring pl_float) return integer {
return pl_float; return 42;
} }
function f_override4() { } function f_override4() { }
private function f_override5() { } private function f_override5() { }
public function f_override6(in float pl_float) return hexstring {
return 'AB'H;
}
} }
// function with class parameter // function with class parameter
......
...@@ -272,14 +272,14 @@ type class BaseFunctionClass { ...@@ -272,14 +272,14 @@ type class BaseFunctionClass {
} }
type class FuncClass extends BaseFunctionClass { type class FuncClass extends BaseFunctionClass {
public function f_get_one() return charstring { public function f_get_one() return integer {
return "xyz"; return 2;
} }
private function f_test_super() { private function f_test_super() {
// type mismatches // type mismatches
var integer vl_int := super.f_get_one(); var integer vl_int := super.f_get_one();
var charstring vl_cs:= f_get_one(); var integer vl_int2:= f_get_one();
} }
// class as a function parameter // class as a function parameter
...@@ -430,7 +430,7 @@ testcase tc_basicSyntax() runs on CT { ...@@ -430,7 +430,7 @@ testcase tc_basicSyntax() runs on CT {
// constructor call without parameters // constructor call without parameters
var MinimalClass vl_minimalClass := MinimalClass.create; var MinimalClass vl_minimalClass := MinimalClass.create;
// constructor call with empty parameter list // constructor call with empty parameter list
var MinimalClass vl_minimalClass2 := MinimalClass.create(); var MinimalClass vl_minimalClass2 := MinimalClass.create();
var ClassWithThis vl_thisClass := ClassWithThis.create(12, 13.0); var ClassWithThis vl_thisClass := ClassWithThis.create(12, 13.0);
var VariousMembers vl_various := VariousMembers.create("abc", "def"); var VariousMembers vl_various := VariousMembers.create("abc", "def");
......
...@@ -28,6 +28,8 @@ import org.eclipse.titan.designer.AST.Location; ...@@ -28,6 +28,8 @@ import org.eclipse.titan.designer.AST.Location;
import org.eclipse.titan.designer.AST.Reference; import org.eclipse.titan.designer.AST.Reference;
import org.eclipse.titan.designer.AST.ReferenceFinder; import org.eclipse.titan.designer.AST.ReferenceFinder;
import org.eclipse.titan.designer.AST.Scope; import org.eclipse.titan.designer.AST.Scope;
import org.eclipse.titan.designer.AST.IType;
import org.eclipse.titan.designer.AST.IType.Type_type;
import org.eclipse.titan.designer.AST.ReferenceFinder.Hit; import org.eclipse.titan.designer.AST.ReferenceFinder.Hit;
import org.eclipse.titan.designer.AST.TTCN3.IIncrementallyUpdateable; import org.eclipse.titan.designer.AST.TTCN3.IIncrementallyUpdateable;
import org.eclipse.titan.designer.AST.TTCN3.TTCN3Scope; import org.eclipse.titan.designer.AST.TTCN3.TTCN3Scope;
...@@ -57,6 +59,8 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl ...@@ -57,6 +59,8 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
public static final String OVERRIDDENFORMALPARAM = "Definition is overridden with different formal parameters"; public static final String OVERRIDDENFORMALPARAM = "Definition is overridden with different formal parameters";
public static final String PUBLICOVERRIDEPUBLIC = "Public method can only be overriden by a public method"; public static final String PUBLICOVERRIDEPUBLIC = "Public method can only be overriden by a public method";
public static final String PROTECTEDOVERRIDE = "Protected method can only be overriden by a public or protected method"; public static final String PROTECTEDOVERRIDE = "Protected method can only be overriden by a public or protected method";
public static final String RETURNTYPEMISMATCH = "Return type differs from the overridden method's return type";
public static final String OVERRIDDENRETURNTYPE = "Method is overridden with a different return type";
public static final String VISIBILITYPRIVATEPROTECTED = "Class field visibility must be private or protected"; public static final String VISIBILITYPRIVATEPROTECTED = "Class field visibility must be private or protected";
public static final String TRAITMETHODSONLY = "Trait classes can only declare methods"; public static final String TRAITMETHODSONLY = "Trait classes can only declare methods";
public static final String TRAITMETHODHASBODY = "Trait method cannot have a function body"; public static final String TRAITMETHODHASBODY = "Trait method cannot have a function body";
...@@ -269,6 +273,14 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl ...@@ -269,6 +273,14 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
if (modifier == VisibilityModifier.Public || modifier == VisibilityModifier.Protected) { if (modifier == VisibilityModifier.Public || modifier == VisibilityModifier.Protected) {
if (definition instanceof Def_Function && localDefinition instanceof Def_Function ) { if (definition instanceof Def_Function && localDefinition instanceof Def_Function ) {
if (! isConstructor(definition)) { if (! isConstructor(definition)) {
final IType returnType = definition.getType(timestamp);
final IType localReturnType = localDefinition.getType(timestamp);
final Type_type type = returnType != null ? returnType.getTypetypeTtcn3() : null;
final Type_type localType = localReturnType != null ? localReturnType.getTypetypeTtcn3() : null;
if (type != localType) {
localDefinition.getType(timestamp).getLocation().reportSemanticError(RETURNTYPEMISMATCH);
definition.getType(timestamp).getLocation().reportSemanticError(OVERRIDDENRETURNTYPE);
}
if (! ((Def_Function)definition).getFormalParameterList().isSame(timestamp, ((Def_Function)localDefinition).getFormalParameterList())) { if (! ((Def_Function)definition).getFormalParameterList().isSame(timestamp, ((Def_Function)localDefinition).getFormalParameterList())) {
localDefinition.getIdentifier().getLocation().reportSemanticError(FORMALPARAMSDIFFER); localDefinition.getIdentifier().getLocation().reportSemanticError(FORMALPARAMSDIFFER);
definition.getIdentifier().getLocation().reportSemanticError(OVERRIDDENFORMALPARAM); definition.getIdentifier().getLocation().reportSemanticError(OVERRIDDENFORMALPARAM);
......
...@@ -64,6 +64,10 @@ public final class Class_Type extends Type implements ITypeWithComponents { ...@@ -64,6 +64,10 @@ public final class Class_Type extends Type implements ITypeWithComponents {
private static final String UNKNOWNFIELD = "Unknown field reference"; private static final String UNKNOWNFIELD = "Unknown field reference";
private static final String PRIVATEINACCESSIBLE = "Private member is inaccessible due to its protection level"; private static final String PRIVATEINACCESSIBLE = "Private member is inaccessible due to its protection level";
/**
* The superclass of this class
* (the only non-trait class that this class extends)
**/
private Class_Type superClass = null; private Class_Type superClass = null;
private final ClassTypeBody classBody; private final ClassTypeBody classBody;
...@@ -243,12 +247,14 @@ public final class Class_Type extends Type implements ITypeWithComponents { ...@@ -243,12 +247,14 @@ public final class Class_Type extends Type implements ITypeWithComponents {
if (refs != null) { if (refs != null) {
for (Reference ref : refs.getReferenceList()) { for (Reference ref : refs.getReferenceList()) {
final Assignment ass = ref.getRefdAssignment(timestamp, false); final Assignment assignment = ref.getRefdAssignment(timestamp, false);
final IType type = ass.getType(timestamp); if (assignment != null) {
if (type instanceof Class_Type) { final IType type = assignment.getType(timestamp);
Class_Type parent = (Class_Type)type; if (type instanceof Class_Type) {
if (parent.isTrait == false) { final Class_Type parent = (Class_Type)type;
superClass = parent; if (parent.isTrait == false) {
superClass = parent;
}
} }
} }
} }
...@@ -344,19 +350,19 @@ public final class Class_Type extends Type implements ITypeWithComponents { ...@@ -344,19 +350,19 @@ public final class Class_Type extends Type implements ITypeWithComponents {
(Type)def.getType(timestamp), new Identifier(Identifier_type.ID_TTCN, name), (Type)def.getType(timestamp), new Identifier(Identifier_type.ID_TTCN, name),
instance, null); instance, null);
fpList.add(fp); fpList.add(fp);
Reference refLeft = new Reference(new Identifier(Identifier_type.ID_TTCN, def.getIdentifier().getName()), Ref_Type.REF_THIS); final Reference refLeft = new Reference(new Identifier(Identifier_type.ID_TTCN, def.getIdentifier().getName()), Ref_Type.REF_THIS);
FieldSubReference subref = new FieldSubReference(def.getIdentifier()); final FieldSubReference subref = new FieldSubReference(def.getIdentifier());
refLeft.addSubReference(subref); refLeft.addSubReference(subref);
Reference refRight = new Reference(new Identifier(Identifier_type.ID_TTCN, def.getIdentifier().getName())); final Reference refRight = new Reference(new Identifier(Identifier_type.ID_TTCN, def.getIdentifier().getName()));
Referenced_Value refdVal = new Referenced_Value(refRight); final Referenced_Value refdVal = new Referenced_Value(refRight);
SpecificValue_Template valTemplate = new SpecificValue_Template(refdVal); final SpecificValue_Template valTemplate = new SpecificValue_Template(refdVal);
Assignment_Statement assignment = new Assignment_Statement(refLeft, valTemplate); final Assignment_Statement assignment = new Assignment_Statement(refLeft, valTemplate);
sb.addStatement(assignment); sb.addStatement(assignment);
} }
} }
FormalParameterList pl = null; FormalParameterList pl = null;
if (superClass != null) { if (superClass != null) {
FormalParameterList parentFpList = superClass.getConstructorFormalParameterList(); final FormalParameterList parentFpList = superClass.getConstructorFormalParameterList();
if (parentFpList != null) { if (parentFpList != null) {
pl = new FormalParameterList(parentFpList); pl = new FormalParameterList(parentFpList);
pl.addFormalParameterList(new FormalParameterList(fpList)); pl.addFormalParameterList(new FormalParameterList(fpList));
...@@ -365,7 +371,7 @@ public final class Class_Type extends Type implements ITypeWithComponents { ...@@ -365,7 +371,7 @@ public final class Class_Type extends Type implements ITypeWithComponents {
if (pl == null) { if (pl == null) {
pl = new FormalParameterList(fpList); pl = new FormalParameterList(fpList);
} }
Def_Function constructor = new Def_Function(new Identifier(Identifier_type.ID_TTCN, "create"), pl, null); final Def_Function constructor = new Def_Function(new Identifier(Identifier_type.ID_TTCN, "create"), pl, null);
constructor.setLocation(NULL_Location.INSTANCE); constructor.setLocation(NULL_Location.INSTANCE);
classBody.addDefinition(constructor); classBody.addDefinition(constructor);
} }
......
...@@ -179,7 +179,7 @@ public class OOP_Semantic_tests { ...@@ -179,7 +179,7 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() { private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn //oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(96); ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(100);
int lineNum = 33; int lineNum = 33;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10; lineNum += 10;
...@@ -236,7 +236,9 @@ public class OOP_Semantic_tests { ...@@ -236,7 +236,9 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("Reference to non-existent field `nonexist' in union template for type `@classesNegativeSemantic.MyUnion'", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Reference to non-existent field `nonexist' in union template for type `@classesNegativeSemantic.MyUnion'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 4; lineNum += 4;
markersToCheck.add(new MarkerToCheck("A field of any visibility cannot be overriden by a subclass", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("A field of any visibility cannot be overriden by a subclass", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 11; lineNum += 4;
markersToCheck.add(new MarkerToCheck("Method is overridden with a different return type", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 7;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
markersToCheck.add(new MarkerToCheck("All formal parameters of a constructor shall be `in` parameters", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("All formal parameters of a constructor shall be `in` parameters", lineNum, IMarker.SEVERITY_ERROR));
} }
...@@ -280,13 +282,17 @@ public class OOP_Semantic_tests { ...@@ -280,13 +282,17 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("A class can only be cast to a superclass or subclass", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("A class can only be cast to a superclass or subclass", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 5; lineNum += 5;
markersToCheck.add(new MarkerToCheck("`super' reference is only valid inside class bodies", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("`super' reference is only valid inside class bodies", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10; lineNum += 4;
markersToCheck.add(new MarkerToCheck("Return type differs from the overridden method's return type", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 6;
markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `integer' was expected instead of `charstring'", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `integer' was expected instead of `charstring'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 2; lineNum += 2;
markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `charstring' was expected instead of `integer'", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `charstring' was expected instead of `integer'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 19; lineNum += 19;
markersToCheck.add(new MarkerToCheck("Definition is overridden with different formal parameters", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Definition is overridden with different formal parameters", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 19; lineNum += 12;
markersToCheck.add(new MarkerToCheck("Method is overridden with a different return type", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 11;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
markersToCheck.add(new MarkerToCheck("A field of any visibility cannot be overriden by a subclass", lineNum++, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("A field of any visibility cannot be overriden by a subclass", lineNum++, IMarker.SEVERITY_ERROR));
} }
...@@ -298,7 +304,9 @@ public class OOP_Semantic_tests { ...@@ -298,7 +304,9 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("Public method can only be overriden by a public method", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Public method can only be overriden by a public method", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 2; lineNum += 2;
markersToCheck.add(new MarkerToCheck("Protected method can only be overriden by a public or protected method", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Protected method can only be overriden by a public or protected method", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 5; lineNum += 2;
markersToCheck.add(new MarkerToCheck("Return type differs from the overridden method's return type", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 7;
markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `integer' was expected instead of `float'", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `integer' was expected instead of `float'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 6; lineNum += 6;
markersToCheck.add(new MarkerToCheck("Class functions cannot have a `runs on` clause", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Class functions cannot have a `runs on` clause", 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