Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

fix Issue 8339 - is(typeof(...)) is reporting true when it's false du…

…e to nested function error

Avoid frame access check and disabled default construction in predicate templates.
  • Loading branch information...
commit 4a0546480078d51a0ad4dbf141c71bf818e034ec 1 parent 230c500
authored August 18, 2012

Showing 2 changed files with 17 additions and 8 deletions. Show diff stats Hide diff stats

  1. 8  std/format.d
  2. 17  std/traits.d
8  std/format.d
@@ -2270,19 +2270,19 @@ template hasToString(T, Char)
2270 2270
         // X* does not have toString, even if X is aggregate type has toString.
2271 2271
         enum hasToString = 0;
2272 2272
     }
2273  
-    else static if (is(typeof({ T val; FormatSpec!Char f; val.toString((const(char)[] s){}, f); })))
  2273
+    else static if (is(typeof({ T val = void; FormatSpec!Char f; val.toString((const(char)[] s){}, f); })))
2274 2274
     {
2275 2275
         enum hasToString = 4;
2276 2276
     }
2277  
-    else static if (is(typeof({ T val; val.toString((const(char)[] s){}, "%s"); })))
  2277
+    else static if (is(typeof({ T val = void; val.toString((const(char)[] s){}, "%s"); })))
2278 2278
     {
2279 2279
         enum hasToString = 3;
2280 2280
     }
2281  
-    else static if (is(typeof({ T val; val.toString((const(char)[] s){}); })))
  2281
+    else static if (is(typeof({ T val = void; val.toString((const(char)[] s){}); })))
2282 2282
     {
2283 2283
         enum hasToString = 2;
2284 2284
     }
2285  
-    else static if (is(typeof({ T val; return val.toString(); }()) S) && isSomeString!S)
  2285
+    else static if (is(typeof({ T val = void; return val.toString(); }()) S) && isSomeString!S)
2286 2286
     {
2287 2287
         enum hasToString = 1;
2288 2288
     }
17  std/traits.d
@@ -2067,7 +2067,7 @@ template hasElaborateCopyConstructor(S)
2067 2067
     else
2068 2068
     {
2069 2069
         enum hasElaborateCopyConstructor = is(typeof({
2070  
-            S s;
  2070
+            S s = void;
2071 2071
             return &s.__postblit;
2072 2072
         })) || anySatisfy!(.hasElaborateCopyConstructor, typeof(S.tupleof));
2073 2073
     }
@@ -2084,6 +2084,9 @@ unittest
2084 2084
     struct S3 { uint num; S1 s; }
2085 2085
     static assert(!hasElaborateCopyConstructor!S2);
2086 2086
     static assert( hasElaborateCopyConstructor!S3);
  2087
+
  2088
+    struct S4 { @disable this(); this(int n){} this(this){} }
  2089
+    static assert( hasElaborateCopyConstructor!S4);
2087 2090
 }
2088 2091
 
2089 2092
 /**
@@ -2101,7 +2104,7 @@ template hasElaborateAssign(S)
2101 2104
     else
2102 2105
     {
2103 2106
         enum hasElaborateAssign = is(typeof(S.init.opAssign(S.init))) ||
2104  
-                                  is(typeof(S.init.opAssign({ return S.init; }()))) ||
  2107
+                                  is(typeof(S.init.opAssign({ S s = void; return s; }()))) ||
2105 2108
             anySatisfy!(.hasElaborateAssign, typeof(S.tupleof));
2106 2109
     }
2107 2110
 }
@@ -2126,6 +2129,9 @@ unittest
2126 2129
         @disable void opAssign(U)(ref U u);
2127 2130
     }
2128 2131
     static assert( hasElaborateAssign!S4);
  2132
+
  2133
+    struct S5 { @disable this(); this(int n){} S s; }
  2134
+    static assert( hasElaborateAssign!S5);
2129 2135
 }
2130 2136
 
2131 2137
 /**
@@ -2950,8 +2956,8 @@ static assert(!isAssignable!(string, char[]));
2950 2956
 template isAssignable(Lhs, Rhs)
2951 2957
 {
2952 2958
     enum bool isAssignable = is(typeof({
2953  
-        Lhs l;
2954  
-        Rhs r;
  2959
+        Lhs l = void;
  2960
+        Rhs r = void;
2955 2961
         l = r;
2956 2962
         return l;
2957 2963
     }));
@@ -2964,6 +2970,9 @@ unittest
2964 2970
 
2965 2971
     static assert(!isAssignable!(int, long));
2966 2972
     static assert(!isAssignable!(string, char[]));
  2973
+
  2974
+    struct S { @disable this(); this(int n){} }
  2975
+    static assert( isAssignable!(S, S));
2967 2976
 }
2968 2977
 
2969 2978
 

0 notes on commit 4a05464

David Nadlinger

Hm, this leads to an interesting question: In release mode, DMD would refuse to compile this code (at least it does in similar cases), because the access of uninitialized data is detected during data flow analysis somewhere in the optimizer. Is failing compilation actually legal behavior? The runtime semantics of the code would be completely undefined, and emitting a warning would obviously be a good idea, but can the compiler refuse to accept the code altogether? If so, it should also be legal to perform this check at an earlier stage in the frontend, which would break code like in this commit.

Hara Kenji
Collaborator

First of all, the adding void initializer means "T is anyway constructible, but doesn't consider the way."
Particular types (struct that disabled default constructor, nested struct that requires enclosing frame pointer, etc.) would run additional checks, but void initializer can avoid them.

... Is failing compilation actually legal behavior?

The optimizer never check the codes inside typeof expressions.Then this static if never fails by the optimizer.

Bug 8339 is a lack of access check for frame pointer of nested struct, but it does not depends on runtime semantics, so I think your question is irrelevant.

David Nadlinger

dmd-internals is the right place for this discussion, see my message there.

Please sign in to comment.
Something went wrong with that request. Please try again.