]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/safe.c
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/safe.c
12 #include "expression.h"
14 #include "aggregate.h"
17 bool MODimplicitConv(MOD modfrom
, MOD modto
);
19 /*************************************************************
20 * Check for unsafe access in @safe code:
21 * 1. read overlapped pointers
22 * 2. write misaligned pointers
23 * 3. write overlapped storage classes
24 * Print error if unsafe.
27 * e = expression to check
28 * readonly = if access is read-only
29 * printmsg = print error message if true
34 bool checkUnsafeAccess(Scope
*sc
, Expression
*e
, bool readonly
, bool printmsg
)
36 if (e
->op
!= TOKdotvar
)
38 DotVarExp
*dve
= (DotVarExp
*)e
;
39 if (VarDeclaration
*v
= dve
->var
->isVarDeclaration())
41 if (sc
->intypeof
|| !sc
->func
|| !sc
->func
->isSafeBypassingInference())
44 AggregateDeclaration
*ad
= v
->toParent2()->isAggregateDeclaration();
48 if (v
->overlapped
&& v
->type
->hasPointers() && sc
->func
->setUnsafe())
51 e
->error("field %s.%s cannot access pointers in @safe code that overlap other fields",
52 ad
->toChars(), v
->toChars());
56 if (readonly
|| !e
->type
->isMutable())
59 if (v
->type
->hasPointers() && v
->type
->toBasetype()->ty
!= Tstruct
)
61 if ((ad
->type
->alignment() < target
.ptrsize
||
62 (v
->offset
& (target
.ptrsize
- 1))) &&
63 sc
->func
->setUnsafe())
66 e
->error("field %s.%s cannot modify misaligned pointers in @safe code",
67 ad
->toChars(), v
->toChars());
72 if (v
->overlapUnsafe
&& sc
->func
->setUnsafe())
75 e
->error("field %s.%s cannot modify fields in @safe code that overlap fields with other storage classes",
76 ad
->toChars(), v
->toChars());
84 /**********************************************
85 * Determine if it is @safe to cast e from tfrom to tto.
87 * e = expression to be cast
89 * tto = type to cast e to
93 bool isSafeCast(Expression
*e
, Type
*tfrom
, Type
*tto
)
95 // Implicit conversions are always safe
96 if (tfrom
->implicitConvTo(tto
))
99 if (!tto
->hasPointers())
102 Type
*ttob
= tto
->toBasetype();
104 if (ttob
->ty
== Tclass
&& tfrom
->ty
== Tclass
)
106 ClassDeclaration
*cdfrom
= tfrom
->isClassHandle();
107 ClassDeclaration
*cdto
= ttob
->isClassHandle();
110 if (!cdfrom
->isBaseOf(cdto
, &offset
))
113 if (cdfrom
->isCPPinterface() || cdto
->isCPPinterface())
116 if (!MODimplicitConv(tfrom
->mod
, ttob
->mod
))
121 if (ttob
->ty
== Tarray
&& tfrom
->ty
== Tsarray
) // Bugzilla 12502
122 tfrom
= tfrom
->nextOf()->arrayOf();
124 if ((ttob
->ty
== Tarray
&& tfrom
->ty
== Tarray
) ||
125 (ttob
->ty
== Tpointer
&& tfrom
->ty
== Tpointer
))
127 Type
*ttobn
= ttob
->nextOf()->toBasetype();
128 Type
*tfromn
= tfrom
->nextOf()->toBasetype();
130 /* From void[] to anything mutable is unsafe because:
133 * int[] ai = cast(int[]) av;
137 if (tfromn
->ty
== Tvoid
&& ttobn
->isMutable())
139 if (ttob
->ty
== Tarray
&& e
->op
== TOKarrayliteral
)
144 // If the struct is opaque we don't know about the struct members then the cast becomes unsafe
145 if ((ttobn
->ty
== Tstruct
&& !((TypeStruct
*)ttobn
)->sym
->members
) ||
146 (tfromn
->ty
== Tstruct
&& !((TypeStruct
*)tfromn
)->sym
->members
))
149 const bool frompointers
= tfromn
->hasPointers();
150 const bool topointers
= ttobn
->hasPointers();
152 if (frompointers
&& !topointers
&& ttobn
->isMutable())
155 if (!frompointers
&& topointers
)
159 ttobn
->ty
!= Tfunction
&& tfromn
->ty
!= Tfunction
&&
160 (ttob
->ty
== Tarray
|| ttobn
->size() <= tfromn
->size()) &&
161 MODimplicitConv(tfromn
->mod
, ttobn
->mod
))