@@ -2718,6 +2718,7 @@ Expression *copyLiteral(Expression *e)
27182718 {
27192719 e -> error ("Internal Compiler Error: CTFE literal %s" , e -> toChars ());
27202720 assert (0 );
2721+ return e ;
27212722 }
27222723}
27232724
@@ -3382,7 +3383,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
33823383 uinteger_t destarraylen = 0 ; // not for AAs
33833384
33843385 // Set the $ variable, and find the array literal to modify
3385- if (ie -> e1 -> type -> toBasetype ()-> ty != Taarray )
3386+ if (ie -> e1 -> type -> toBasetype ()-> ty != Taarray && ie -> e1 -> type -> toBasetype () -> ty != Tpointer )
33863387 {
33873388 Expression * oldval = ie -> e1 -> interpret (istate );
33883389 if (oldval -> op == TOKnull )
@@ -3417,11 +3418,28 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
34173418 StringExp * existingSE = NULL ;
34183419 AssocArrayLiteralExp * existingAA = NULL ;
34193420
3421+ Expression * aggregate = resolveReferences (ie -> e1 , istate -> localThis );
3422+
34203423 // Set the index to modify (for non-AAs), and check that it is in range
34213424 int indexToModify = 0 ;
34223425 if (ie -> e1 -> type -> toBasetype ()-> ty != Taarray )
34233426 {
34243427 indexToModify = index -> toInteger ();
3428+ if (ie -> e1 -> type -> toBasetype ()-> ty == Tpointer )
3429+ {
3430+ dinteger_t ofs ;
3431+ aggregate = aggregate -> interpret (istate , ctfeNeedLvalue );
3432+ if (aggregate == EXP_CANT_INTERPRET )
3433+ return EXP_CANT_INTERPRET ;
3434+ if (aggregate -> op == TOKnull )
3435+ {
3436+ error ("cannot index through null pointer %s" , ie -> e1 -> toChars ());
3437+ return EXP_CANT_INTERPRET ;
3438+ }
3439+ aggregate = getAggregateFromPointer (aggregate , & ofs );
3440+ indexToModify += ofs ;
3441+ destarraylen = resolveArrayLength (aggregate );
3442+ }
34253443 if (indexToModify >= destarraylen )
34263444 {
34273445 error ("array index %d is out of bounds [0..%d]" , indexToModify ,
@@ -3430,8 +3448,6 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
34303448 }
34313449 }
34323450
3433- Expression * aggregate = resolveReferences (ie -> e1 , istate -> localThis );
3434-
34353451 /* The only possible indexable LValue aggregates are array literals,
34363452 * slices of array literals, and AA literals.
34373453 */
@@ -4216,7 +4232,36 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
42164232#if LOG
42174233 printf ("IndexExp::interpret() %s\n" , toChars ());
42184234#endif
4235+ if (this -> e1 -> type -> toBasetype ()-> ty == Tpointer )
4236+ {
4237+ // Indexing a pointer. Note that there is no $ in this case.
4238+ e1 = this -> e1 -> interpret (istate );
4239+ if (e1 == EXP_CANT_INTERPRET )
4240+ return EXP_CANT_INTERPRET ;
42194241
4242+ e2 = this -> e2 -> interpret (istate );
4243+ if (e2 == EXP_CANT_INTERPRET )
4244+ return EXP_CANT_INTERPRET ;
4245+ dinteger_t indx = e2 -> toInteger ();
4246+ Expression * e ;
4247+ dinteger_t ofs ;
4248+ Expression * agg = getAggregateFromPointer (e1 , & ofs );
4249+ if (agg -> op == TOKnull )
4250+ {
4251+ error ("cannot index null pointer %s" , this -> e1 -> toChars ());
4252+ return EXP_CANT_INTERPRET ;
4253+ }
4254+ assert (agg -> op == TOKarrayliteral || agg -> op == TOKstring );
4255+ dinteger_t len = ArrayLength (Type ::tsize_t , agg )-> toInteger ();
4256+ Type * pointee = ((TypePointer * )agg -> type )-> next ;
4257+ if ((indx + ofs ) < 0 || (indx + ofs ) > len )
4258+ {
4259+ error ("pointer index [%jd] exceeds allocated memory block [0..%jd]" ,
4260+ indx + ofs , len );
4261+ return EXP_CANT_INTERPRET ;
4262+ }
4263+ return Index (type , agg , new IntegerExp (loc , indx + ofs , Type ::tsize_t ));
4264+ }
42204265 e1 = this -> e1 -> interpret (istate );
42214266 if (e1 == EXP_CANT_INTERPRET )
42224267 return EXP_CANT_INTERPRET ;
0 commit comments