diff --git a/Semantic_Analizer_Tests/src/Basic_tests/OopNegativeSemanticTest.ttcn b/Semantic_Analizer_Tests/src/Basic_tests/OopNegativeSemanticTest.ttcn index 1f05090433a84f131adfb95b9520e3a59d19fbc6..492514df4c2c4eac255d0f0ae1c956f4f78edd1c 100755 --- a/Semantic_Analizer_Tests/src/Basic_tests/OopNegativeSemanticTest.ttcn +++ b/Semantic_Analizer_Tests/src/Basic_tests/OopNegativeSemanticTest.ttcn @@ -304,8 +304,8 @@ type class ClassWithPrivate { return 1; } - function f_override2(in float pl_float) return integer { - return 1; + function f_override2(in float pl_float) return charstring { + return "xyz"; } public function f_override3(in float pl_float) return integer { @@ -319,6 +319,10 @@ type class ClassWithPrivate { function f_override5() { } + + function f_override6(in float pl_float) return octetstring { + return 'AB'O; + } } type class ClassOverride1 { @@ -340,13 +344,17 @@ type class ClassWithPrivateExt extends ClassWithPrivate { return pl_float; } - public function f_override3(charstring pl_float) return charstring { - return pl_float; + public function f_override3(charstring pl_float) return integer { + return 42; } function f_override4() { } private function f_override5() { } + + public function f_override6(in float pl_float) return hexstring { + return 'AB'H; + } } // function with class parameter diff --git a/Semantic_Analizer_Tests/src/Basic_tests/OopPositiveBasicSyntax.ttcn b/Semantic_Analizer_Tests/src/Basic_tests/OopPositiveBasicSyntax.ttcn index f92e630f5c33a55ed6a0c975326eddb5dc3d583a..b0dd7c80fb3b20d24aa42d2025f40124104647ff 100644 --- a/Semantic_Analizer_Tests/src/Basic_tests/OopPositiveBasicSyntax.ttcn +++ b/Semantic_Analizer_Tests/src/Basic_tests/OopPositiveBasicSyntax.ttcn @@ -272,14 +272,14 @@ type class BaseFunctionClass { } type class FuncClass extends BaseFunctionClass { - public function f_get_one() return charstring { - return "xyz"; + public function f_get_one() return integer { + return 2; } private function f_test_super() { // type mismatches 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 @@ -430,7 +430,7 @@ testcase tc_basicSyntax() runs on CT { // constructor call without parameters var MinimalClass vl_minimalClass := MinimalClass.create; // 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 VariousMembers vl_various := VariousMembers.create("abc", "def"); diff --git a/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/ClassTypeBody.java b/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/ClassTypeBody.java index 11c2a59df93cb1278e22bbf20f5a1e91550021e7..ed2b72783734944b72e7f38c07ee56d257c9b0d5 100755 --- a/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/ClassTypeBody.java +++ b/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/ClassTypeBody.java @@ -28,6 +28,8 @@ import org.eclipse.titan.designer.AST.Location; import org.eclipse.titan.designer.AST.Reference; import org.eclipse.titan.designer.AST.ReferenceFinder; 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.TTCN3.IIncrementallyUpdateable; import org.eclipse.titan.designer.AST.TTCN3.TTCN3Scope; @@ -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 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 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 TRAITMETHODSONLY = "Trait classes can only declare methods"; public static final String TRAITMETHODHASBODY = "Trait method cannot have a function body"; @@ -269,6 +273,14 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl if (modifier == VisibilityModifier.Public || modifier == VisibilityModifier.Protected) { if (definition instanceof Def_Function && localDefinition instanceof Def_Function ) { 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())) { localDefinition.getIdentifier().getLocation().reportSemanticError(FORMALPARAMSDIFFER); definition.getIdentifier().getLocation().reportSemanticError(OVERRIDDENFORMALPARAM); diff --git a/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/Class_Type.java b/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/Class_Type.java index 2a7491c6f876eef6c3ed71aafa806b2af3cf09e6..9e7a945e74148c61ddd0ec35941e0cbbb0d03f06 100755 --- a/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/Class_Type.java +++ b/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/Class_Type.java @@ -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 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 final ClassTypeBody classBody; @@ -243,12 +247,14 @@ public final class Class_Type extends Type implements ITypeWithComponents { if (refs != null) { for (Reference ref : refs.getReferenceList()) { - final Assignment ass = ref.getRefdAssignment(timestamp, false); - final IType type = ass.getType(timestamp); - if (type instanceof Class_Type) { - Class_Type parent = (Class_Type)type; - if (parent.isTrait == false) { - superClass = parent; + final Assignment assignment = ref.getRefdAssignment(timestamp, false); + if (assignment != null) { + final IType type = assignment.getType(timestamp); + if (type instanceof Class_Type) { + final Class_Type parent = (Class_Type)type; + if (parent.isTrait == false) { + superClass = parent; + } } } } @@ -344,19 +350,19 @@ public final class Class_Type extends Type implements ITypeWithComponents { (Type)def.getType(timestamp), new Identifier(Identifier_type.ID_TTCN, name), instance, null); fpList.add(fp); - Reference refLeft = new Reference(new Identifier(Identifier_type.ID_TTCN, def.getIdentifier().getName()), Ref_Type.REF_THIS); - FieldSubReference subref = new FieldSubReference(def.getIdentifier()); + final Reference refLeft = new Reference(new Identifier(Identifier_type.ID_TTCN, def.getIdentifier().getName()), Ref_Type.REF_THIS); + final FieldSubReference subref = new FieldSubReference(def.getIdentifier()); refLeft.addSubReference(subref); - Reference refRight = new Reference(new Identifier(Identifier_type.ID_TTCN, def.getIdentifier().getName())); - Referenced_Value refdVal = new Referenced_Value(refRight); - SpecificValue_Template valTemplate = new SpecificValue_Template(refdVal); - Assignment_Statement assignment = new Assignment_Statement(refLeft, valTemplate); + final Reference refRight = new Reference(new Identifier(Identifier_type.ID_TTCN, def.getIdentifier().getName())); + final Referenced_Value refdVal = new Referenced_Value(refRight); + final SpecificValue_Template valTemplate = new SpecificValue_Template(refdVal); + final Assignment_Statement assignment = new Assignment_Statement(refLeft, valTemplate); sb.addStatement(assignment); } } FormalParameterList pl = null; if (superClass != null) { - FormalParameterList parentFpList = superClass.getConstructorFormalParameterList(); + final FormalParameterList parentFpList = superClass.getConstructorFormalParameterList(); if (parentFpList != null) { pl = new FormalParameterList(parentFpList); pl.addFormalParameterList(new FormalParameterList(fpList)); @@ -365,7 +371,7 @@ public final class Class_Type extends Type implements ITypeWithComponents { if (pl == null) { 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); classBody.addDefinition(constructor); } diff --git a/org.eclipse.titan.regressiontests/src/org/eclipse/titan/regressiontests/designer/statictests/Basic_tests/OOP_Semantic_tests.java b/org.eclipse.titan.regressiontests/src/org/eclipse/titan/regressiontests/designer/statictests/Basic_tests/OOP_Semantic_tests.java index 0786096efa3e3e689409786b421356610929ba57..93ffc58ec69e5f31eb9655fafe2ac7cb6638678d 100755 --- a/org.eclipse.titan.regressiontests/src/org/eclipse/titan/regressiontests/designer/statictests/Basic_tests/OOP_Semantic_tests.java +++ b/org.eclipse.titan.regressiontests/src/org/eclipse/titan/regressiontests/designer/statictests/Basic_tests/OOP_Semantic_tests.java @@ -179,7 +179,7 @@ public class OOP_Semantic_tests { private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() { //oopNegativeSemanticTest.ttcn - ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(96); + ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(100); int lineNum = 33; markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR)); lineNum += 10; @@ -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)); lineNum += 4; 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++) { 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 { markersToCheck.add(new MarkerToCheck("A class can only be cast to a superclass or subclass", lineNum, IMarker.SEVERITY_ERROR)); lineNum += 5; 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)); lineNum += 2; markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `charstring' was expected instead of `integer'", lineNum, IMarker.SEVERITY_ERROR)); lineNum += 19; 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++) { 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 { markersToCheck.add(new MarkerToCheck("Public method can only be overriden by a public method", lineNum, IMarker.SEVERITY_ERROR)); lineNum += 2; 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)); lineNum += 6; markersToCheck.add(new MarkerToCheck("Class functions cannot have a `runs on` clause", lineNum, IMarker.SEVERITY_ERROR));