Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Issue 6169 - [CTFE] pure functions cannot compute constants using functions not marked as pure #652

Merged
merged 1 commit into from 12 months ago

3 participants

Daniel Murphy Don Clugston Andrei Alexandrescu
Daniel Murphy
Collaborator

When running semantic on an expression used anywhere that forces compile time evaluation, use a scope flag to prevent purity and safety checks on function calls.
This allows more functions to be inferred @safe/pure.

http://d.puremagic.com/issues/show_bug.cgi?id=6169

Don Clugston
Collaborator

There's a huge similarity between this bug, and the gagging that occurs in speculative template instantiation (bug 4269, for example, which I'm currently working on). In both cases, semantic is run in a different mode, and a certain subset of errors need to be suppressed/ignored. I think they can both be treated in the same way.

Daniel Murphy
Collaborator

Yeah, this is a new type of gagging (eek) but as it can't leak outside expressions there hopefully won't be too many problems with it. The only ways I could think of for solving 4269 is to make semantic completely reversible for declarations or to suspend gagging when evaulating non-speculative declarations. The first options requires lots of work and has hundreds of corner cases, and the second doesn't work inside speculative declarations... I'll be interested to see your solution.

Don Clugston
Collaborator

I'm taking the second approach: ungag if non-speculative, when semantic is called from a speculative context.

Daniel Murphy
Collaborator

Ok, but I don't know how this will work for declarations that must be evaluated speculatively - basically anything can be inside a template declaration, and unless semantic can be re-run how can the errors be detected later?
eg

template Templ(T)
{
    static assert(is(T == int));
    int fun() {}
}
static assert(!__traits(compiles, Templ!(long).fun()));
enum x = Templ!(long).fun(); // semantic has already failed

The issue here isn't that semantic is being run gagged when it shouldn't be, it's that to generate the correct errors semantic has to be run again.

Don Clugston
Collaborator

Yeah, I dealt with that in a previous pull request. TemplateInstance has a member for speculative errors. If an error occurs, that counter gets updated. But it currently only applies to errors inside function bodies. It needs to be extended to work on other declarations.

Daniel Murphy
Collaborator

Won't that result in a generic 'errors instantiating' message rather than the specifics? I guess it would change this bug from accepts-invalid to a massive diagnostic problem.

Don Clugston
Collaborator

No. If there are semantic speculative errors, and a non-speculative instantiation is requested, the existing instantiation is discarded.
Code from TemplateInstance::semantic()

   // If both this and the previous instantiation were speculative,
    // use the number of errors that happened last time.
    if (inst->speculative && global.gag)
    {
        global.errors += inst->errors;
        global.gaggedErrors += inst->errors;
    }

    // If the first instantiation was speculative, but this is not:
    if (inst->speculative && !global.gag)
    {
        // If the first instantiation had failed, re-run semantic,
        // so that error messages are shown.
        if (inst->errors)
            goto L1;
        // It had succeeded, mark it is a non-speculative instantiation,
        // and reuse it.
        inst->speculative = 0;
    }
Daniel Murphy
Collaborator

Updated to match Don's recent ctfeInterpret changes.

There is one change: Runtime values in case statements are no longer allowed.

Don Clugston
Collaborator
donc commented

There is one change: Runtime values in case statements are no longer allowed.

Please undo that. Although I would love for that to happen, it's a language change so it needs to be in its own pull request.

Daniel Murphy
Collaborator

Ok, I'll leave the original behavior for case variables.

Daniel Murphy
Collaborator

Done.

Andrei Alexandrescu
Owner

OK to assign @donc to this? Please advise. I'm uneasy about two things: (a) inferring pure for regular functions makes for a big difference when compiling things separately vs. not. Not sure how bad that is. (b) disallowing runtime values for switch breaks code. This is a big one. Thoughts?

Don Clugston
Collaborator

The "disallowing runtime values" was removed from the pull request as part of the "restore case variables" commit.
The "inferring pure" part doesn't make a difference for separate compilation, it's simply the fact that whenever any compile-time constant is used, it is never impure, even if it was created by CTFE. If you know an expression is a compile-time literal, you don't need to analyze it further.

Daniel Murphy
Collaborator

@andralex
a) This allows more functions to be inferred as pure by excluding ctfe expressions from checks, as nothing run at compile time can break run-time purity and safety. It does not change the circumstances is which a function has purity inference run on it.
b) While I hate case variables with a passion, they are no longer removed by this pull request. I've updated the description to reflect that.

Brad Roberts braddr referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
Daniel Murphy
Collaborator

Updated.

Daniel Murphy
Collaborator

Updated again.

Daniel Murphy Fix Issue 6169 - [CTFE] pure functions cannot compute constants using…
… functions not marked as pure

When running semantic on an expression used anywhere that forces compile time evaluation, use a scope flag to prevent purity and safety checks on function calls.
This allows better purity/safety inferrence as well.
42d1af1
Don Clugston donc merged commit 15a5783 into from
Don Clugston donc closed this
Daniel Murphy yebblies deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

May 03, 2013
Daniel Murphy Fix Issue 6169 - [CTFE] pure functions cannot compute constants using…
… functions not marked as pure

When running semantic on an expression used anywhere that forces compile time evaluation, use a scope flag to prevent purity and safety checks on function calls.
This allows better purity/safety inferrence as well.
42d1af1
This page is out of date. Refresh to see the latest.
10  src/attrib.c
@@ -971,7 +971,7 @@ void PragmaDeclaration::semantic(Scope *sc)
971 971
             {
972 972
                 Expression *e = (*args)[i];
973 973
 
974  
-                e = e->semantic(sc);
  974
+                e = e->ctfeSemantic(sc);
975 975
                 e = resolveProperties(sc, e);
976 976
                 if (e->op != TOKerror && e->op != TOKtype)
977 977
                     e = e->ctfeInterpret();
@@ -999,7 +999,7 @@ void PragmaDeclaration::semantic(Scope *sc)
999 999
         {
1000 1000
             Expression *e = (*args)[0];
1001 1001
 
1002  
-            e = e->semantic(sc);
  1002
+            e = e->ctfeSemantic(sc);
1003 1003
             e = resolveProperties(sc, e);
1004 1004
             e = e->ctfeInterpret();
1005 1005
             (*args)[0] = e;
@@ -1027,7 +1027,7 @@ void PragmaDeclaration::semantic(Scope *sc)
1027 1027
         else
1028 1028
         {
1029 1029
             Expression *e = (*args)[0];
1030  
-            e = e->semantic(sc);
  1030
+            e = e->ctfeSemantic(sc);
1031 1031
             e = resolveProperties(sc, e);
1032 1032
             e = e->ctfeInterpret();
1033 1033
             (*args)[0] = e;
@@ -1050,7 +1050,7 @@ void PragmaDeclaration::semantic(Scope *sc)
1050 1050
                 for (size_t i = 0; i < args->dim; i++)
1051 1051
                 {
1052 1052
                     Expression *e = (*args)[i];
1053  
-                    e = e->semantic(sc);
  1053
+                    e = e->ctfeSemantic(sc);
1054 1054
                     e = resolveProperties(sc, e);
1055 1055
                     e = e->ctfeInterpret();
1056 1056
                     if (i == 0)
@@ -1428,7 +1428,7 @@ int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
1428 1428
 void CompileDeclaration::compileIt(Scope *sc)
1429 1429
 {
1430 1430
     //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars());
1431  
-    exp = exp->semantic(sc);
  1431
+    exp = exp->ctfeSemantic(sc);
1432 1432
     exp = resolveProperties(sc, exp);
1433 1433
     exp = exp->ctfeInterpret();
1434 1434
     StringExp *se = exp->toString();
2  src/cond.c
@@ -259,7 +259,7 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
259 259
         sc = sc->push(sc->scopesym);
260 260
         sc->sd = s;                     // s gets any addMember()
261 261
         sc->flags |= SCOPEstaticif;
262  
-        Expression *e = exp->semantic(sc);
  262
+        Expression *e = exp->ctfeSemantic(sc);
263 263
         e = resolveProperties(sc, e);
264 264
         sc->pop();
265 265
         if (!e->type->checkBoolean())
12  src/declaration.c
@@ -851,6 +851,11 @@ void VarDeclaration::semantic(Scope *sc)
851 851
     if (!type)
852 852
     {   inuse++;
853 853
 
  854
+        // Infering the type requires running semantic,
  855
+        // so mark the scope as ctfe if required
  856
+        if (storage_class & (STCmanifest | STCstatic))
  857
+            sc->needctfe++;
  858
+
854 859
         //printf("inferring type for %s with init %s\n", toChars(), init->toChars());
855 860
         ArrayInitializer *ai = init->isArrayInitializer();
856 861
         if (ai)
@@ -872,6 +877,8 @@ void VarDeclaration::semantic(Scope *sc)
872 877
         else
873 878
             type = init->inferType(sc);
874 879
 
  880
+        if (storage_class & (STCmanifest | STCstatic))
  881
+            sc->needctfe--;
875 882
 //      type = type->semantic(loc, sc);
876 883
 
877 884
         inuse--;
@@ -1585,7 +1592,10 @@ void VarDeclaration::semantic(Scope *sc)
1585 1592
                 {
1586 1593
                     Expression *exp;
1587 1594
                     exp = ei->exp->syntaxCopy();
1588  
-                    exp = exp->semantic(sc);
  1595
+                    if (isDataseg() || (storage_class & STCmanifest))
  1596
+                        exp = exp->ctfeSemantic(sc);
  1597
+                    else
  1598
+                        exp = exp->semantic(sc);
1589 1599
                     exp = resolveProperties(sc, exp);
1590 1600
                     Type *tb = type->toBasetype();
1591 1601
                     Type *ti = exp->type->toBasetype();
14  src/enum.c
@@ -252,7 +252,7 @@ void EnumDeclaration::semantic(Scope *sc)
252 252
         if (e)
253 253
         {
254 254
             assert(e->dyncast() == DYNCAST_EXPRESSION);
255  
-            e = e->semantic(sce);
  255
+            e = e->ctfeSemantic(sce);
256 256
             e = e->ctfeInterpret();
257 257
             if (memtype)
258 258
             {
@@ -299,7 +299,7 @@ void EnumDeclaration::semantic(Scope *sc)
299 299
             if (!emax)
300 300
             {
301 301
                 emax = t->getProperty(0, Id::max, 0);
302  
-                emax = emax->semantic(sce);
  302
+                emax = emax->ctfeSemantic(sce);
303 303
                 emax = emax->ctfeInterpret();
304 304
             }
305 305
 
@@ -307,14 +307,14 @@ void EnumDeclaration::semantic(Scope *sc)
307 307
             // But first check that (elast != t.max)
308 308
             assert(elast);
309 309
             e = new EqualExp(TOKequal, em->loc, elast, emax);
310  
-            e = e->semantic(sce);
  310
+            e = e->ctfeSemantic(sce);
311 311
             e = e->ctfeInterpret();
312 312
             if (e->toInteger())
313 313
                 error("overflow of enum value %s", elast->toChars());
314 314
 
315 315
             // Now set e to (elast + 1)
316 316
             e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
317  
-            e = e->semantic(sce);
  317
+            e = e->ctfeSemantic(sce);
318 318
             e = e->castTo(sce, elast->type);
319 319
             e = e->ctfeInterpret();
320 320
 
@@ -322,7 +322,7 @@ void EnumDeclaration::semantic(Scope *sc)
322 322
             {
323 323
                 // Check that e != elast (not always true for floats)
324 324
                 Expression *etest = new EqualExp(TOKequal, em->loc, e, elast);
325  
-                etest = etest->semantic(sce);
  325
+                etest = etest->ctfeSemantic(sce);
326 326
                 etest = etest->ctfeInterpret();
327 327
                 if (etest->toInteger())
328 328
                     error("enum member %s has inexact value, due to loss of precision", em->toChars());
@@ -361,13 +361,13 @@ void EnumDeclaration::semantic(Scope *sc)
361 361
 
362 362
                 // Compute if(e < minval)
363 363
                 ec = new CmpExp(TOKlt, em->loc, e, minval);
364  
-                ec = ec->semantic(sce);
  364
+                ec = ec->ctfeSemantic(sce);
365 365
                 ec = ec->ctfeInterpret();
366 366
                 if (ec->toInteger())
367 367
                     minval = e;
368 368
 
369 369
                 ec = new CmpExp(TOKgt, em->loc, e, maxval);
370  
-                ec = ec->semantic(sce);
  370
+                ec = ec->ctfeSemantic(sce);
371 371
                 ec = ec->ctfeInterpret();
372 372
                 if (ec->toInteger())
373 373
                     maxval = e;
71  src/expression.c
@@ -1537,6 +1537,29 @@ Expression *Expression::trySemantic(Scope *sc)
1537 1537
     return e;
1538 1538
 }
1539 1539
 
  1540
+/**********************************
  1541
+ * Shortcut to run semantic with purity and
  1542
+ * safety checking disabled for the immediate
  1543
+ * expressions
  1544
+ */
  1545
+
  1546
+Expression *Expression::ctfeSemantic(Scope *sc)
  1547
+{
  1548
+    if (sc)
  1549
+    {
  1550
+        assert(sc->needctfe >= 0);
  1551
+        sc->needctfe++;
  1552
+        Expression *e = semantic(sc);
  1553
+        sc->needctfe--;
  1554
+        assert(sc->needctfe >= 0);
  1555
+        return e;
  1556
+    }
  1557
+    else
  1558
+    {
  1559
+        return semantic(sc);
  1560
+    }
  1561
+}
  1562
+
1540 1563
 void Expression::print()
1541 1564
 {
1542 1565
     fprintf(stdmsg, "%s\n", toChars());
@@ -1876,7 +1899,8 @@ void Expression::checkPurity(Scope *sc, FuncDeclaration *f)
1876 1899
         // If the caller has a pure parent, then either the called func must be pure,
1877 1900
         // OR, they must have the same pure parent.
1878 1901
         if (/*outerfunc->isPure() &&*/    // comment out because we deduce purity now
1879  
-            !f->isPure() && calledparent != outerfunc)
  1902
+            !f->isPure() && calledparent != outerfunc &&
  1903
+            !sc->needctfe)
1880 1904
         {
1881 1905
             if (outerfunc->setImpure())
1882 1906
                 error("pure function '%s' cannot call impure function '%s'",
@@ -1977,6 +2001,7 @@ void Expression::checkPurity(Scope *sc, VarDeclaration *v, Expression *ethis)
1977 2001
 void Expression::checkSafety(Scope *sc, FuncDeclaration *f)
1978 2002
 {
1979 2003
     if (sc->func && !sc->intypeof &&
  2004
+        !(sc->needctfe) &&
1980 2005
         !f->isSafe() && !f->isTrusted())
1981 2006
     {
1982 2007
         if (sc->func->setUnsafe())
@@ -4968,7 +4993,10 @@ Expression *NewAnonClassExp::semantic(Scope *sc)
4968 4993
 #endif
4969 4994
 
4970 4995
     Expression *d = new DeclarationExp(loc, cd);
  4996
+    int needctfe = sc->needctfe;
  4997
+    sc->needctfe = 0;
4971 4998
     d = d->semantic(sc);
  4999
+    sc->needctfe = needctfe;
4972 5000
 
4973 5001
     Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
4974 5002
 
@@ -5392,6 +5420,11 @@ Expression *FuncExp::semantic(Scope *sc)
5392 5420
     printf("FuncExp::semantic(%s)\n", toChars());
5393 5421
     if (fd->treq) printf("  treq = %s\n", fd->treq->toChars());
5394 5422
 #endif
  5423
+    Expression *e = this;
  5424
+
  5425
+    int needctfe = sc->needctfe;
  5426
+    sc->needctfe = 0;
  5427
+
5395 5428
     if (!type || type == Type::tvoid)
5396 5429
     {
5397 5430
         /* fd->treq might be incomplete type,
@@ -5421,10 +5454,9 @@ Expression *FuncExp::semantic(Scope *sc)
5421 5454
             td->semantic(sc);
5422 5455
             type = Type::tvoid; // temporary type
5423 5456
 
5424  
-            if (!fd->treq)  // defer type determination
5425  
-                return this;
5426  
-
5427  
-            return inferType(fd->treq);
  5457
+            if (fd->treq)  // defer type determination
  5458
+                e = inferType(fd->treq);
  5459
+            goto Ldone;
5428 5460
         }
5429 5461
 
5430 5462
         unsigned olderrors = global.errors;
@@ -5479,7 +5511,9 @@ Expression *FuncExp::semantic(Scope *sc)
5479 5511
         }
5480 5512
         fd->tookAddressOf++;
5481 5513
     }
5482  
-    return this;
  5514
+Ldone:
  5515
+    sc->needctfe = needctfe;
  5516
+    return e;
5483 5517
 }
5484 5518
 
5485 5519
 // used from CallExp::semantic()
@@ -6563,7 +6597,7 @@ Expression *CompileExp::semantic(Scope *sc)
6563 6597
 #if LOGSEMANTIC
6564 6598
     printf("CompileExp::semantic('%s')\n", toChars());
6565 6599
 #endif
6566  
-    UnaExp::semantic(sc);
  6600
+    e1 = e1->ctfeSemantic(sc);
6567 6601
     e1 = resolveProperties(sc, e1);
6568 6602
     if (e1->op == TOKerror)
6569 6603
         return e1;
@@ -6616,7 +6650,7 @@ Expression *FileExp::semantic(Scope *sc)
6616 6650
 #if LOGSEMANTIC
6617 6651
     printf("FileExp::semantic('%s')\n", toChars());
6618 6652
 #endif
6619  
-    UnaExp::semantic(sc);
  6653
+    e1 = e1->ctfeSemantic(sc);
6620 6654
     e1 = resolveProperties(sc, e1);
6621 6655
     e1 = e1->ctfeInterpret();
6622 6656
     if (e1->op != TOKstring)
@@ -8371,12 +8405,12 @@ Expression *CallExp::semantic(Scope *sc)
8371 8405
             return new ErrorExp();
8372 8406
         }
8373 8407
 
8374  
-        if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug))
  8408
+        if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug) && !sc->needctfe)
8375 8409
         {
8376 8410
             if (sc->func->setImpure())
8377 8411
                 error("pure function '%s' cannot call impure %s '%s'", sc->func->toPrettyChars(), p, e1->toChars());
8378 8412
         }
8379  
-        if (sc->func && tf->trust <= TRUSTsystem)
  8413
+        if (sc->func && tf->trust <= TRUSTsystem && !sc->needctfe)
8380 8414
         {
8381 8415
             if (sc->func->setUnsafe())
8382 8416
                 error("safe function '%s' cannot call system %s '%s'", sc->func->toPrettyChars(), p, e1->toChars());
@@ -9557,14 +9591,22 @@ Expression *SliceExp::semantic(Scope *sc)
9557 9591
     }
9558 9592
 
9559 9593
     if (lwr)
9560  
-    {   lwr = lwr->semantic(sc2);
  9594
+    {
  9595
+        if (t->ty == Ttuple)
  9596
+            lwr = lwr->ctfeSemantic(sc2);
  9597
+        else
  9598
+            lwr = lwr->semantic(sc2);
9561 9599
         lwr = resolveProperties(sc2, lwr);
9562 9600
         lwr = lwr->implicitCastTo(sc2, Type::tsize_t);
9563 9601
         if (lwr->type == Type::terror)
9564 9602
             goto Lerr;
9565 9603
     }
9566 9604
     if (upr)
9567  
-    {   upr = upr->semantic(sc2);
  9605
+    {
  9606
+        if (t->ty == Ttuple)
  9607
+            upr = upr->ctfeSemantic(sc2);
  9608
+        else
  9609
+            upr = upr->semantic(sc2);
9568 9610
         upr = resolveProperties(sc2, upr);
9569 9611
         upr = upr->implicitCastTo(sc2, Type::tsize_t);
9570 9612
         if (upr->type == Type::terror)
@@ -10038,7 +10080,10 @@ Expression *IndexExp::semantic(Scope *sc)
10038 10080
         sc = sc->push(sym);
10039 10081
     }
10040 10082
 
10041  
-    e2 = e2->semantic(sc);
  10083
+    if (t1->ty == Ttuple)
  10084
+        e2 = e2->ctfeSemantic(sc);
  10085
+    else
  10086
+        e2 = e2->semantic(sc);
10042 10087
     e2 = resolveProperties(sc, e2);
10043 10088
     if (e2->type == Type::terror)
10044 10089
         goto Lerr;
1  src/expression.h
@@ -113,6 +113,7 @@ struct Expression : Object
113 113
     virtual int apply(apply_fp_t fp, void *param);
114 114
     virtual Expression *semantic(Scope *sc);
115 115
     Expression *trySemantic(Scope *sc);
  116
+    Expression *ctfeSemantic(Scope *sc);
116 117
 
117 118
     int dyncast() { return DYNCAST_EXPRESSION; }        // kludge for template.isExpression()
118 119
 
6  src/iasm.c
@@ -3671,7 +3671,7 @@ STATIC code *asm_db_parse(OP *pop)
3671 3671
 
3672 3672
             case TOKidentifier:
3673 3673
             {   Expression *e = new IdentifierExp(asmstate.loc, asmtok->ident);
3674  
-                e = e->semantic(asmstate.sc);
  3674
+                e = e->ctfeSemantic(asmstate.sc);
3675 3675
                 e = e->ctfeInterpret();
3676 3676
                 if (e->op == TOKint64)
3677 3677
                 {   dt.ul = e->toInteger();
@@ -3747,7 +3747,7 @@ int asm_getnum()
3747 3747
             Expression *e;
3748 3748
 
3749 3749
             e = new IdentifierExp(asmstate.loc, asmtok->ident);
3750  
-            e = e->semantic(asmstate.sc);
  3750
+            e = e->ctfeSemantic(asmstate.sc);
3751 3751
             e = e->ctfeInterpret();
3752 3752
             i = e->toInteger();
3753 3753
             v = (int) i;
@@ -4458,7 +4458,7 @@ STATIC OPND *asm_primary_exp()
4458 4458
                                 break;
4459 4459
                             }
4460 4460
                         }
4461  
-                        e = e->semantic(asmstate.sc);
  4461
+                        e = e->ctfeSemantic(asmstate.sc);
4462 4462
                         e = e->ctfeInterpret();
4463 4463
                         if (e->isConst())
4464 4464
                         {
7  src/init.c
@@ -558,7 +558,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
558 558
     {
559 559
         Expression *idx = index[i];
560 560
         if (idx)
561  
-        {   idx = idx->semantic(sc);
  561
+        {   idx = idx->ctfeSemantic(sc);
562 562
             idx = idx->ctfeInterpret();
563 563
             index[i] = idx;
564 564
             length = idx->toInteger();
@@ -942,7 +942,10 @@ bool arrayHasNonConstPointers(Expressions *elems)
942 942
 Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
943 943
 {
944 944
     //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
945  
-    exp = exp->semantic(sc);
  945
+    if (needInterpret)
  946
+        exp = exp->ctfeSemantic(sc);
  947
+    else
  948
+        exp = exp->semantic(sc);
946 949
     exp = resolveProperties(sc, exp);
947 950
     if (exp->op == TOKerror)
948 951
         return this;
12  src/mtype.c
@@ -3599,12 +3599,12 @@ Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
3599 3599
         sym->parent = sc->scopesym;
3600 3600
         sc = sc->push(sym);
3601 3601
 
3602  
-        exp = exp->semantic(sc);
  3602
+        exp = exp->ctfeSemantic(sc);
3603 3603
 
3604 3604
         sc->pop();
3605 3605
     }
3606 3606
     else
3607  
-        exp = exp->semantic(sc);
  3607
+        exp = exp->ctfeSemantic(sc);
3608 3608
     return exp;
3609 3609
 }
3610 3610
 
@@ -3614,7 +3614,7 @@ Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
3614 3614
     sym->parent = sc->scopesym;
3615 3615
     sc = sc->push(sym);
3616 3616
 
3617  
-    exp = exp->semantic(sc);
  3617
+    exp = exp->ctfeSemantic(sc);
3618 3618
 
3619 3619
     sc->pop();
3620 3620
     return exp;
@@ -3643,7 +3643,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
3643 3643
             sym->parent = sc->scopesym;
3644 3644
             sc = sc->push(sym);
3645 3645
 
3646  
-            dim = dim->semantic(sc);
  3646
+            dim = dim->ctfeSemantic(sc);
3647 3647
             dim = dim->ctfeInterpret();
3648 3648
             uinteger_t d = dim->toUInteger();
3649 3649
 
@@ -9132,11 +9132,11 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
9132 9132
             sym->parent = sc->scopesym;
9133 9133
             sc = sc->push(sym);
9134 9134
 
9135  
-            lwr = lwr->semantic(sc);
  9135
+            lwr = lwr->ctfeSemantic(sc);
9136 9136
             lwr = lwr->ctfeInterpret();
9137 9137
             uinteger_t i1 = lwr->toUInteger();
9138 9138
 
9139  
-            upr = upr->semantic(sc);
  9139
+            upr = upr->ctfeSemantic(sc);
9140 9140
             upr = upr->ctfeInterpret();
9141 9141
             uinteger_t i2 = upr->toUInteger();
9142 9142
 
2  src/scope.c
@@ -74,6 +74,7 @@ Scope::Scope()
74 74
     this->nofree = 0;
75 75
     this->noctor = 0;
76 76
     this->noaccesscheck = 0;
  77
+    this->needctfe = 0;
77 78
     this->intypeof = 0;
78 79
     this->speculative = 0;
79 80
     this->parameterSpecialization = 0;
@@ -123,6 +124,7 @@ Scope::Scope(Scope *enclosing)
123 124
     this->nofree = 0;
124 125
     this->noctor = enclosing->noctor;
125 126
     this->noaccesscheck = enclosing->noaccesscheck;
  127
+    this->needctfe = enclosing->needctfe;
126 128
     this->intypeof = enclosing->intypeof;
127 129
     this->speculative = enclosing->speculative;
128 130
     this->parameterSpecialization = enclosing->parameterSpecialization;
1  src/scope.h
@@ -68,6 +68,7 @@ struct Scope
68 68
     bool speculative;            // in __traits(compiles) or typeof(exp)
69 69
     int parameterSpecialization; // if in template parameter specialization
70 70
     int noaccesscheck;          // don't do access checks
  71
+    int needctfe;               // inside a ctfe-only expression
71 72
 
72 73
     unsigned callSuper;         // primitive flow analysis for constructors
73 74
 #define CSXthis_ctor    1       // called this()
14  src/statement.c
@@ -473,7 +473,7 @@ void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
473 473
 Statements *CompileStatement::flatten(Scope *sc)
474 474
 {
475 475
     //printf("CompileStatement::flatten() %s\n", exp->toChars());
476  
-    exp = exp->semantic(sc);
  476
+    exp = exp->ctfeSemantic(sc);
477 477
     exp = resolveProperties(sc, exp);
478 478
     exp = exp->ctfeInterpret();
479 479
     if (exp->op == TOKerror)
@@ -2851,7 +2851,7 @@ Statement *PragmaStatement::semantic(Scope *sc)
2851 2851
             {
2852 2852
                 Expression *e = (*args)[i];
2853 2853
 
2854  
-                e = e->semantic(sc);
  2854
+                e = e->ctfeSemantic(sc);
2855 2855
                 e = resolveProperties(sc, e);
2856 2856
                 if (e->op != TOKerror && e->op != TOKtype)
2857 2857
                     e = e->ctfeInterpret();
@@ -2883,7 +2883,7 @@ Statement *PragmaStatement::semantic(Scope *sc)
2883 2883
         {
2884 2884
             Expression *e = (*args)[0];
2885 2885
 
2886  
-            e = e->semantic(sc);
  2886
+            e = e->ctfeSemantic(sc);
2887 2887
             e = resolveProperties(sc, e);
2888 2888
             e = e->ctfeInterpret();
2889 2889
             (*args)[0] = e;
@@ -2909,7 +2909,7 @@ Statement *PragmaStatement::semantic(Scope *sc)
2909 2909
         else
2910 2910
         {
2911 2911
             Expression *e = (*args)[0];
2912  
-            e = e->semantic(sc);
  2912
+            e = e->ctfeSemantic(sc);
2913 2913
             e = resolveProperties(sc, e);
2914 2914
             e = e->ctfeInterpret();
2915 2915
             (*args)[0] = e;
@@ -3241,7 +3241,7 @@ Statement *CaseStatement::semantic(Scope *sc)
3241 3241
 {   SwitchStatement *sw = sc->sw;
3242 3242
 
3243 3243
     //printf("CaseStatement::semantic() %s\n", toChars());
3244  
-    exp = exp->semantic(sc);
  3244
+    exp = exp->ctfeSemantic(sc);
3245 3245
     exp = resolveProperties(sc, exp);
3246 3246
     if (sw)
3247 3247
     {
@@ -3358,12 +3358,12 @@ Statement *CaseRangeStatement::semantic(Scope *sc)
3358 3358
     if (sw->isFinal)
3359 3359
         error("case ranges not allowed in final switch");
3360 3360
 
3361  
-    first = first->semantic(sc);
  3361
+    first = first->ctfeSemantic(sc);
3362 3362
     first = resolveProperties(sc, first);
3363 3363
     first = first->implicitCastTo(sc, sw->condition->type);
3364 3364
     first = first->ctfeInterpret();
3365 3365
 
3366  
-    last = last->semantic(sc);
  3366
+    last = last->ctfeSemantic(sc);
3367 3367
     last = resolveProperties(sc, last);
3368 3368
     last = last->implicitCastTo(sc, sw->condition->type);
3369 3369
     last = last->ctfeInterpret();
4  src/staticassert.c
@@ -55,7 +55,7 @@ void StaticAssert::semantic2(Scope *sc)
55 55
     ScopeDsymbol *sd = new ScopeDsymbol();
56 56
     sc = sc->push(sd);
57 57
     sc->flags |= SCOPEstaticassert;
58  
-    Expression *e = exp->semantic(sc);
  58
+    Expression *e = exp->ctfeSemantic(sc);
59 59
     e = resolveProperties(sc, e);
60 60
     sc = sc->pop();
61 61
     if (!e->type->checkBoolean())
@@ -76,7 +76,7 @@ void StaticAssert::semantic2(Scope *sc)
76 76
         {   HdrGenState hgs;
77 77
             OutBuffer buf;
78 78
 
79  
-            msg = msg->semantic(sc);
  79
+            msg = msg->ctfeSemantic(sc);
80 80
             msg = resolveProperties(sc, msg);
81 81
             msg = msg->ctfeInterpret();
82 82
             hgs.console = 1;
2  src/struct.c
@@ -118,7 +118,7 @@ void AggregateDeclaration::semantic3(Scope *sc)
118 118
             ti->semantic3(sc);
119 119
             Dsymbol *s = ti->toAlias();
120 120
             Expression *e = new DsymbolExp(0, s, 0);
121  
-            e = e->semantic(ti->tempdecl->scope);
  121
+            e = e->ctfeSemantic(ti->tempdecl->scope);
122 122
             e = e->ctfeInterpret();
123 123
             getRTInfo = e;
124 124
         }
20  src/template.c
@@ -845,9 +845,8 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
845 845
             fd->vthis = fd->declareThis(paramscope, ad);
846 846
         }
847 847
 
848  
-        e = e->semantic(sc);
  848
+        e = e->ctfeSemantic(sc);
849 849
         e = resolveProperties(sc, e);
850  
-
851 850
         if (e->op == TOKerror)
852 851
             goto Lnomatch;
853 852
 
@@ -1907,7 +1906,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Scope *sc, Objec
1907 1906
             fd->vthis = fd->declareThis(paramscope, ad);
1908 1907
         }
1909 1908
 
1910  
-        e = e->semantic(paramscope);
  1909
+        e = e->ctfeSemantic(paramscope);
1911 1910
         e = resolveProperties(sc, e);
1912 1911
 
1913 1912
         if (fd && fd->vthis)
@@ -4086,7 +4085,7 @@ Object *aliasParameterSemantic(Loc loc, Scope *sc, Object *o)
4086 4085
         }
4087 4086
         else if (ea)
4088 4087
         {
4089  
-            ea = ea->semantic(sc);
  4088
+            ea = ea->ctfeSemantic(sc);
4090 4089
             o = ea->ctfeInterpret();
4091 4090
         }
4092 4091
     }
@@ -4402,7 +4401,7 @@ void TemplateValueParameter::semantic(Scope *sc)
4402 4401
     if (specValue)
4403 4402
     {   Expression *e = specValue;
4404 4403
 
4405  
-        e = e->semantic(sc);
  4404
+        e = e->ctfeSemantic(sc);
4406 4405
         e = e->implicitCastTo(sc, valType);
4407 4406
         e = e->ctfeInterpret();
4408 4407
         if (e->op == TOKint64 || e->op == TOKfloat64 ||
@@ -4414,7 +4413,7 @@ void TemplateValueParameter::semantic(Scope *sc)
4414 4413
     if (defaultValue)
4415 4414
     {   Expression *e = defaultValue;
4416 4415
 
4417  
-        e = e->semantic(sc);
  4416
+        e = e->ctfeSemantic(sc);
4418 4417
         e = e->implicitCastTo(sc, valType);
4419 4418
         e = e->ctfeInterpret();
4420 4419
         if (e->op == TOKint64)
@@ -4517,13 +4516,13 @@ MATCH TemplateValueParameter::matchArg(Scope *sc,
4517 4516
 
4518 4517
         Expression *e = specValue;
4519 4518
 
4520  
-        e = e->semantic(sc);
  4519
+        e = e->ctfeSemantic(sc);
4521 4520
         e = resolveProperties(sc, e);
4522 4521
         e = e->implicitCastTo(sc, vt);
4523 4522
         e = e->ctfeInterpret();
4524 4523
 
4525 4524
         ei = ei->syntaxCopy();
4526  
-        ei = ei->semantic(sc);
  4525
+        ei = ei->ctfeSemantic(sc);
4527 4526
         ei = ei->implicitCastTo(sc, vt);
4528 4527
         ei = ei->ctfeInterpret();
4529 4528
         //printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars());
@@ -5473,7 +5472,10 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
5473 5472
         {
5474 5473
         Lexpr:
5475 5474
             //printf("+[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars());
5476  
-            ea = ea->semantic(sc);
  5475
+            if (flags & 1)
  5476
+                ea = ea->semantic(sc);
  5477
+            else
  5478
+                ea = ea->ctfeSemantic(sc);
5477 5479
             if (flags & 1) // only used by __traits, must not interpret the args
5478 5480
                 ea = ea->optimize(WANTvalue);
5479 5481
             else if (ea->op == TOKvar)
8  test/fail_compilation/failsafea.d
... ...
@@ -0,0 +1,8 @@
  1
+
  2
+void systemfunc() @system {}
  3
+
  4
+@safe
  5
+void callingsystem()
  6
+{
  7
+    systemfunc();
  8
+}
8  test/fail_compilation/failsafeb.d
... ...
@@ -0,0 +1,8 @@
  1
+
  2
+void function() @system sysfuncptr;
  3
+
  4
+@safe
  5
+void callingsystem()
  6
+{
  7
+    sysfuncptr();
  8
+}
9  test/fail_compilation/failsafec.d
... ...
@@ -0,0 +1,9 @@
  1
+
  2
+void delegate() @system sysdelegate;
  3
+
  4
+@safe
  5
+void callingsystem()
  6
+{
  7
+    sysdelegate();
  8
+}
  9
+
8  test/runnable/Fix5140.d
@@ -55,8 +55,8 @@ void main(string[] args) nothrow
55 55
         static assert(getTemplCallingFunc() == "Fix5140.main.__lambda1");
56 56
         static assert(getCalleeFunc() == "imports.Fix5140a.getCalleeFunc");
57 57
 
58  
-        static assert(getCallingPrettyFunc() == "Fix5140.main.__lambda1(int x, int y) @system");
59  
-        static assert(getTemplCallingPrettyFunc() == "Fix5140.main.__lambda1(int x, int y) @system");
  58
+        static assert(getCallingPrettyFunc() == "Fix5140.main.__lambda1(int x, int y)");
  59
+        static assert(getTemplCallingPrettyFunc() == "Fix5140.main.__lambda1(int x, int y)");
60 60
         static assert(getCalleePrettyFunc(1, 1.0) == "string imports.Fix5140a.getCalleePrettyFunc(int x, float y)");
61 61
     };
62 62
     funcLiteral(1, 2);
@@ -73,8 +73,8 @@ void main(string[] args) nothrow
73 73
             static assert(getTemplCallingFunc() == "Fix5140.main.S.func!(\"foo\", int, symbol, int[],float[]).func");
74 74
             static assert(getCalleeFunc() == "imports.Fix5140a.getCalleeFunc");
75 75
 
76  
-            static assert(getCallingPrettyFunc() == "void Fix5140.main.S.func!(\"foo\", int, symbol, int[],float[]).func(int x) const @system");
77  
-            static assert(getTemplCallingPrettyFunc() == "void Fix5140.main.S.func!(\"foo\", int, symbol, int[],float[]).func(int x) const @system");
  76
+            static assert(getCallingPrettyFunc() == "void Fix5140.main.S.func!(\"foo\", int, symbol, int[],float[]).func(int x) const");
  77
+            static assert(getTemplCallingPrettyFunc() == "void Fix5140.main.S.func!(\"foo\", int, symbol, int[],float[]).func(int x) const");
78 78
             static assert(getCalleePrettyFunc(1, 1.0) == "string imports.Fix5140a.getCalleePrettyFunc(int x, float y)");
79 79
         }
80 80
     }
12  test/runnable/testsafe.d
@@ -170,18 +170,6 @@ void safeunions()
170 170
  
171 171
  
172 172
  
173  
-void systemfunc() @system {} 
174  
-void function() @system sysfuncptr; 
175  
-void delegate() @system sysdelegate; 
176  
- 
177  
-@safe 
178  
-void callingsystem() 
179  
-{ 
180  
-    static assert(!__traits(compiles, systemfunc())); 
181  
-    static assert(!__traits(compiles, sysfuncptr())); 
182  
-    static assert(!__traits(compiles, sysdelegate())); 
183  
-} 
184  
- 
185 173
 @safe 
186 174
 void safeexception() 
187 175
 { 
43  test/runnable/xtest46.d
@@ -2610,6 +2610,49 @@ void test129()
2610 2610
 
2611 2611
 /***************************************************/
2612 2612
 
  2613
+
  2614
+auto ctfefunc6169() { return ";"; }
  2615
+enum ctfefptr6169 = &ctfefunc6169;
  2616
+int ctfefunc6169a() { return 1; }
  2617
+template x6169(string c) { alias int x6169; }
  2618
+template TT6169(T...) { alias T TT6169; }
  2619
+
  2620
+void test6169() pure @safe
  2621
+{
  2622
+    enum a = ctfefunc6169();
  2623
+    static b = ctfefunc6169();
  2624
+    x6169!(ctfefunc6169()) tt;
  2625
+    mixin(ctfefunc6169());
  2626
+    static if(ctfefunc6169()) {}
  2627
+    pragma(msg, ctfefunc6169());
  2628
+    enum xx
  2629
+    {
  2630
+        k = 0,
  2631
+        j = ctfefunc6169a()
  2632
+    }
  2633
+    auto g = mixin('"' ~ ctfefunc6169() ~ '"');
  2634
+    //auto h = import("testx.d" ~ false ? ctfefunc() : "");
  2635
+    alias TT6169!(int, int)[ctfefunc6169a()..ctfefunc6169a()] i;
  2636
+    alias TT6169!(int, int)[ctfefunc6169a()] j;
  2637
+    int[ctfefunc6169a()+1] k;
  2638
+    alias int[ctfefunc6169a()] l;
  2639
+    switch(1)
  2640
+    {
  2641
+    //case ctfefunc6169a(): // Can't do this because of case variables
  2642
+    case ctfefunc6169a()+1:
  2643
+        ..
  2644
+    case ctfefunc6169a()+2:
  2645
+    default:
  2646
+        break;
  2647
+    }
  2648
+    static assert(ctfefunc6169a());
  2649
+    void fun(int i : ctfefunc6169a() = ctfefunc6169a(), alias j)() if (ctfefunc6169a()) {}
  2650
+    fun!(ctfefunc6169a(), ctfefunc6169())();
  2651
+    enum z = ctfefptr6169();
  2652
+}
  2653
+
  2654
+/***************************************************/
  2655
+
2613 2656
 const shared class C5107
2614 2657
 {
2615 2658
     int x;
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.