@@ -1568,8 +1568,51 @@ private void checkCall(StmtCall call) {
15681568 call .attrCallSignature ().checkSignatureCompatibility (call .attrFunctionSignature (), funcName , call );
15691569 }
15701570
1571+ /** Error when a field in this class hides a field from a superclass. */
1572+ private void checkFieldShadowing (ClassDef c ) {
1573+ // Iterate only the fields *declared* in this class:
1574+ for (NameLink nl : c .attrNameLinks ().values ()) {
1575+ NameDef def = nl .getDef ();
1576+ // consider only variables that are declared in this class body
1577+ if (!(def instanceof GlobalVarDef )) continue ;
1578+ if (nl .getDefinedIn () != c ) continue ; // not declared here
1579+
1580+ String name = def .getName ();
1581+
1582+ // Look up all visible declarations of the same name in this class scope:
1583+ ImmutableCollection <DefLink > all = c .attrNameLinks ().get (name );
1584+ for (DefLink other : all ) {
1585+ if (!(other instanceof NameLink )) continue ;
1586+ if (other .getDefinedIn () == c ) continue ; // skip "self" (duplicates in same class handled elsewhere)
1587+ NameDef od = other .getDef ();
1588+ if (!(od instanceof GlobalVarDef )) continue ;
1589+
1590+ // Is the other definition a superclass' field?
1591+ StructureDef owner = od .attrNearestStructureDef ();
1592+ if (owner instanceof ClassDef ) {
1593+ ClassDef superOwner = (ClassDef ) owner ;
1594+ if (isStrictSuperclassOf (superOwner , c )) {
1595+ // produce the requested error text
1596+ def .addError ("Variable " + name + " in class " + c .getName ()
1597+ + " hides variable " + name + " from superclass " + superOwner .getName ());
1598+ // one error per conflicting ancestor is enough
1599+ break ;
1600+ }
1601+ }
1602+ }
1603+ }
1604+ }
15711605
1572- // crude cap to avoid unbounded growth; tune as needed
1606+ private static boolean isStrictSuperclassOf (ClassDef sup , ClassDef sub ) {
1607+ WurstTypeClass t = sub .attrTypC ();
1608+ WurstTypeClass cur = (t != null ) ? t .extendedClass () : null ;
1609+ while (cur != null ) {
1610+ ClassDef cd = cur .getClassDef ();
1611+ if (cd == sup ) return true ;
1612+ cur = cur .extendedClass ();
1613+ }
1614+ return false ;
1615+ }
15731616
15741617 private static boolean isSubtypeCached (WurstType actual , WurstType expected , Annotation site ) {
15751618 if (actual == expected ) return true ;
@@ -1796,12 +1839,15 @@ private void checkReturnInFunc(StmtReturn s, FunctionImplementation func) {
17961839
17971840 private void visit (ClassDef classDef ) {
17981841 checkTypeName (classDef , classDef .getName ());
1799- if (!(classDef .getExtendedClass () instanceof NoTypeExpr ) && !(classDef .getExtendedClass ().attrTyp () instanceof WurstTypeClass )) {
1842+ if (!(classDef .getExtendedClass () instanceof NoTypeExpr )
1843+ && !(classDef .getExtendedClass ().attrTyp () instanceof WurstTypeClass )) {
18001844 classDef .getExtendedClass ().addError ("Classes may only extend other classes." );
18011845 }
18021846 if (classDef .isInnerClass () && !classDef .attrIsStatic ()) {
18031847 classDef .addError ("At the moment only static inner classes are supported." );
18041848 }
1849+
1850+ checkFieldShadowing (classDef );
18051851 }
18061852
18071853 private void checkTypeName (Element source , String name ) {
0 commit comments