[svn] r7656: nemerle/trunk/ncc: generation/Typer3.n testsuite/negative/bug-664.n testsuite/positive/before...

divan svnadmin at nemerle.org
Sat May 5 15:34:59 CEST 2007


Log:
Add 'this' before 'base()' usage checks (fix 664).

Author: divan
Date: Sat May  5 15:34:55 2007
New Revision: 7656

Added:
   nemerle/trunk/ncc/testsuite/negative/bug-664.n
   nemerle/trunk/ncc/testsuite/positive/before-base.n
Modified:
   nemerle/trunk/ncc/generation/Typer3.n

Modified: nemerle/trunk/ncc/generation/Typer3.n
==============================================================================
--- nemerle/trunk/ncc/generation/Typer3.n	(original)
+++ nemerle/trunk/ncc/generation/Typer3.n	Sat May  5 15:34:55 2007
@@ -1113,11 +1113,29 @@
     IsBaseCtor (_ : TExpr) : bool
     {
       | TExpr.Base (mth) =>
-          !CurrentType.GetConstructors (). Contains (mth)
+          ! mth.DeclaringType.Equals (CurrentType)
       | TExpr.MacroEnvelope (_, _, e) => IsBaseCtor (e)
       | _ => false
     }
 
+    IsThis (_ : TExpr) : bool
+    {
+      | TExpr.This => true
+      | TExpr.LocalRef as e
+       => (e.decl.ValKind is LocalValue.Kind.ClosurisedThisPointer)
+      | _ => false;
+    }
+
+    IsBaseField (f : IField) : bool
+    {
+      ! f.DeclaringType.Equals (CurrentType)
+    }
+
+    IsBaseMethod (m : IMethod) : bool
+    {
+      ! m.DeclaringType.Equals (CurrentType)
+    }
+
     //Return min*max ctor calls in expr
     CtorCalls (e : TExpr) : int*int 
     {
@@ -1379,6 +1397,42 @@
             | (_, y) => 
               Message.Warning ($"Base constructor call can happen $y times");
           }
+          //Check this usage before base()
+          //Allow this.* 
+          //Deny base.*, this, base
+          def f (_) {
+            | TExpr.Call (e, p, _) when IsCtor (e)
+             => _ = List.Map (p, x => ctor_calls (x.expr));
+                Some (true)
+            | TExpr.FieldMember (e, f) as expr when IsThis (e)
+             => when (IsBaseField (f))
+                  Message.Error (expr.loc,
+                    "using base class field before base is constructed");
+                Some (false)
+            | TExpr.MethodRef (e, m, _, _) as expr when IsThis (e)
+             => when (IsBaseMethod (m))
+                  Message.Error (expr.loc,
+                    "using base class method before base is constructed");
+                Some (false)
+            | e when IsThis (e)
+             => Message.Error (e.loc,
+                  "``this'' or ``base'' usage before base is constructed");
+                Some (false)
+            | _ => None ()
+          }
+          and ctor_calls (e) {
+            SimpleFlow (e, f, false, seq, fork)
+          }
+          and seq (_) {
+            | [] => false
+            | q :: _ when ctor_calls (q) => true
+            | _ :: w => seq (w)
+          }
+          and fork (l) {
+            List.Filter (l, seq) != []
+          }
+          _ = ctor_calls (e);
+          
         }
       }
       when (is_ctor && !CurrentType.IsValueType)

Added: nemerle/trunk/ncc/testsuite/negative/bug-664.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/negative/bug-664.n	Sat May  5 15:34:55 2007
@@ -0,0 +1,50 @@
+class Base {
+  public this (_ : Base) {
+  }
+}
+
+class Inh : Base {
+  public this () {
+    base (this) // E: ``this'' or ``base'' usage before base is constructed
+  }
+}
+
+class A
+{
+  protected x : int;
+  protected y () : int { 
+    1 
+  }
+  public this( x : int = 10 ) {
+    this.x = x;
+  }
+}
+
+class B : A
+{
+  new x : int;
+  new y () : int {
+    1
+  }
+  public this()
+  {
+    this.x = 1;
+    _ = base; // E: ``this'' or ``base'' usage before base is constructed
+    _ = this; // E: ``this'' or ``base'' usage before base is constructed
+    _ = base.x; // E: using base class field before base is constructed
+    _ = this.x;
+    System.Console.WriteLine ($"base.x = $(base.x)"); // E: using base class field before base is constructed
+    _ = base.y (); // E: using base class method before base is constructed
+    _ = this.y ();
+    
+    base (1);
+    
+    _ = base;
+    _ = this;
+    _ = base.x;
+    _ = this.x;
+    System.Console.WriteLine ($"base.x = $(base.x)");
+    _ = base.y ();
+    _ = this.y ();
+  }
+}

Added: nemerle/trunk/ncc/testsuite/positive/before-base.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/positive/before-base.n	Sat May  5 15:34:55 2007
@@ -0,0 +1,21 @@
+class A {
+  public this (x : int) {
+    System.Console.WriteLine (x)
+  }
+}
+
+class B : A {
+  x : int = 3;
+  public this () {
+    base (this.x)
+  }
+};
+
+_ = B ();
+
+
+/*
+BEGIN-OUTPUT
+3
+END-OUTPUT
+*/
\ No newline at end of file



More information about the svn mailing list