14
14
//
15
15
// ===----------------------------------------------------------------------===//
16
16
17
- #include " swift/Subsystems.h"
18
- #include " swift/AST/AccessScope.h"
19
17
#include " swift/AST/ASTContext.h"
20
18
#include " swift/AST/ASTWalker.h"
19
+ #include " swift/AST/AccessScope.h"
21
20
#include " swift/AST/Decl.h"
22
21
#include " swift/AST/Expr.h"
23
- #include " swift/AST/Module.h"
24
- #include " swift/AST/ParameterList.h"
25
- #include " swift/AST/Pattern.h"
26
- #include " swift/AST/Stmt.h"
27
22
#include " swift/AST/ForeignErrorConvention.h"
28
23
#include " swift/AST/GenericEnvironment.h"
29
24
#include " swift/AST/Initializer.h"
25
+ #include " swift/AST/Module.h"
26
+ #include " swift/AST/ParameterList.h"
27
+ #include " swift/AST/Pattern.h"
30
28
#include " swift/AST/PrettyStackTrace.h"
31
29
#include " swift/AST/ProtocolConformance.h"
30
+ #include " swift/AST/Stmt.h"
32
31
#include " swift/Basic/SourceManager.h"
32
+ #include " swift/Subsystems.h"
33
33
#include " llvm/ADT/SmallBitVector.h"
34
34
#include " llvm/ADT/SmallString.h"
35
+ #include " llvm/Support/Debug.h"
35
36
#include " llvm/Support/raw_ostream.h"
36
37
#include < functional>
38
+ #include < type_traits>
37
39
using namespace swift ;
38
40
39
41
namespace {
@@ -71,69 +73,147 @@ struct ASTNodeBase {};
71
73
};
72
74
#include " swift/AST/PatternNodes.def"
73
75
74
- class Verifier : public ASTWalker {
75
- PointerUnion<ModuleDecl *, SourceFile *> M;
76
- ASTContext &Ctx;
77
- llvm::raw_ostream &Out;
78
- const bool HadError;
79
- SmallVector<bool , 8 > InImplicitBraceStmt;
80
-
81
- // / \brief The stack of functions we're visiting.
82
- SmallVector<DeclContext *, 4 > Functions;
83
-
84
- // / \brief The stack of scopes we're visiting.
85
- using ScopeLike = llvm::PointerUnion<DeclContext *, BraceStmt *>;
86
- SmallVector<ScopeLike, 4 > Scopes;
87
-
88
- // / The set of primary archetypes that are currently available.
89
- SmallVector<GenericEnvironment *, 2 > GenericEnv;
90
-
91
- // / \brief The stack of optional evaluations active at this point.
92
- SmallVector<OptionalEvaluationExpr *, 4 > OptionalEvaluations;
93
-
94
- // / \brief The set of opaque value expressions active at this point.
95
- llvm::DenseMap<OpaqueValueExpr *, unsigned > OpaqueValues;
76
+ template <typename Ty>
77
+ struct is_apply_expr
78
+ : public std::integral_constant<
79
+ bool ,
80
+ std::is_same<Ty, CallExpr>::value ||
81
+ std::is_same<Ty, PrefixUnaryExpr>::value ||
82
+ std::is_same<Ty, PostfixUnaryExpr>::value ||
83
+ std::is_same<Ty, BinaryExpr>::value ||
84
+ std::is_same<Ty, DotSyntaxCallExpr>::value ||
85
+ std::is_same<Ty, ConstructorRefCallExpr>::value> {};
86
+
87
+ template <typename Ty>
88
+ struct is_autoclosure_expr
89
+ : public std::integral_constant<bool ,
90
+ std::is_same<Ty, AutoClosureExpr>::value> {
91
+ };
92
+
93
+ template <typename Ty>
94
+ struct is_apply_or_autoclosure_expr
95
+ : public std::integral_constant<
96
+ bool , is_apply_expr<Ty>::value || is_autoclosure_expr<Ty>::value> {};
97
+
98
+ template <typename Verifier, typename Kind>
99
+ std::pair<bool , Expr *> dispatchVisitPreExprHelper (
100
+ Verifier &V,
101
+ typename std::enable_if<
102
+ is_apply_expr<typename std::remove_pointer<Kind>::type>::value,
103
+ Kind>::type node) {
104
+ if (V.shouldVerify (node)) {
105
+ // Whitelist any inout_to_pointer or array_to_pointer that we see in
106
+ // the proper position.
107
+ V.updateExprToPointerWhitelist (node, node->getArg ());
108
+ return {true , node};
109
+ }
110
+ V.cleanup (node);
111
+ return {false , node};
112
+ }
96
113
97
- // / The set of opened existential archetypes that are currently
98
- // / active.
99
- llvm::DenseSet<ArchetypeType *> OpenedExistentialArchetypes;
114
+ template <typename Verifier, typename Kind>
115
+ std::pair<bool , Expr *> dispatchVisitPreExprHelper (
116
+ Verifier &V,
117
+ typename std::enable_if<
118
+ is_autoclosure_expr<typename std::remove_pointer<Kind>::type>::value,
119
+ Kind>::type node) {
120
+ if (V.shouldVerify (node)) {
121
+ // Whitelist any inout_to_pointer or array_to_pointer that we see in
122
+ // the proper position.
123
+ V.updateExprToPointerWhitelist (node, node->getSingleExpressionBody ());
124
+ return {true , node};
125
+ }
126
+ V.cleanup (node);
127
+ return {false , node};
128
+ }
100
129
101
- // / A key into ClosureDiscriminators is a combination of a
102
- // / ("canonicalized") local DeclContext* and a flag for whether to
103
- // / use the explicit closure sequence (false) or the implicit
104
- // / closure sequence (true).
105
- typedef llvm::PointerIntPair<DeclContext*,1 ,bool > ClosureDiscriminatorKey;
106
- llvm::DenseMap<ClosureDiscriminatorKey,
107
- llvm::SmallBitVector> ClosureDiscriminators;
108
- DeclContext *CanonicalTopLevelContext = nullptr ;
130
+ template <typename Verifier, typename Kind>
131
+ std::pair<bool , Expr *> dispatchVisitPreExprHelper (
132
+ Verifier &V, typename std::enable_if<
133
+ !is_apply_or_autoclosure_expr<
134
+ typename std::remove_pointer<Kind>::type>::value,
135
+ Kind>::type node) {
136
+ if (V.shouldVerify (node)) {
137
+ return {true , node};
138
+ }
139
+ V.cleanup (node);
140
+ return {false , node};
141
+ }
109
142
110
- Verifier (PointerUnion<ModuleDecl *, SourceFile *> M, DeclContext *DC)
143
+ class Verifier : public ASTWalker {
144
+ PointerUnion<ModuleDecl *, SourceFile *> M;
145
+ ASTContext &Ctx;
146
+ llvm::raw_ostream &Out;
147
+ const bool HadError;
148
+ SmallVector<bool , 8 > InImplicitBraceStmt;
149
+
150
+ // / \brief The stack of functions we're visiting.
151
+ SmallVector<DeclContext *, 4 > Functions;
152
+
153
+ // / \brief The stack of scopes we're visiting.
154
+ using ScopeLike = llvm::PointerUnion<DeclContext *, BraceStmt *>;
155
+ SmallVector<ScopeLike, 4 > Scopes;
156
+
157
+ // / The set of primary archetypes that are currently available.
158
+ SmallVector<GenericEnvironment *, 2 > GenericEnv;
159
+
160
+ // / \brief The stack of optional evaluations active at this point.
161
+ SmallVector<OptionalEvaluationExpr *, 4 > OptionalEvaluations;
162
+
163
+ // / \brief The set of opaque value expressions active at this point.
164
+ llvm::DenseMap<OpaqueValueExpr *, unsigned > OpaqueValues;
165
+
166
+ // / The set of opened existential archetypes that are currently
167
+ // / active.
168
+ llvm::DenseSet<ArchetypeType *> OpenedExistentialArchetypes;
169
+
170
+ // / The set of inout to pointer expr that match the following pattern:
171
+ // /
172
+ // / (call-expr
173
+ // / (brace-stmt
174
+ // / ... maybe other arguments ...
175
+ // / (inject_into_optional
176
+ // / (inout_to_pointer ...))
177
+ // / ... maybe other arguments ...))
178
+ // /
179
+ // / Any other inout to pointer expr that we see is invalid and the verifier
180
+ // / will assert.
181
+ llvm::DenseSet<InOutToPointerExpr *> WhitelistedInOutToPointerExpr;
182
+ llvm::DenseSet<ArrayToPointerExpr *> WhitelistedArrayToPointerExpr;
183
+
184
+ // / A key into ClosureDiscriminators is a combination of a
185
+ // / ("canonicalized") local DeclContext* and a flag for whether to
186
+ // / use the explicit closure sequence (false) or the implicit
187
+ // / closure sequence (true).
188
+ typedef llvm::PointerIntPair<DeclContext *, 1 , bool > ClosureDiscriminatorKey;
189
+ llvm::DenseMap<ClosureDiscriminatorKey, llvm::SmallBitVector>
190
+ ClosureDiscriminators;
191
+ DeclContext *CanonicalTopLevelContext = nullptr ;
192
+
193
+ Verifier (PointerUnion<ModuleDecl *, SourceFile *> M, DeclContext *DC)
111
194
: M(M),
112
195
Ctx (M.is<ModuleDecl *>() ? M.get<ModuleDecl *>()->getASTContext()
113
- : M.get<SourceFile *>()->getASTContext()),
114
- Out(llvm::errs()),
115
- HadError(Ctx.hadError())
116
- {
117
- Scopes.push_back (DC);
118
- GenericEnv.push_back (DC->getGenericEnvironmentOfContext ());
119
- }
120
-
121
- public:
122
- Verifier (ModuleDecl *M, DeclContext *DC)
123
- : Verifier(PointerUnion<ModuleDecl *, SourceFile *>(M), DC) { }
124
- Verifier (SourceFile &SF, DeclContext *DC)
125
- : Verifier(&SF, DC) { }
196
+ : M.get<SourceFile *>()->getASTContext()),
197
+ Out(llvm::errs()), HadError(Ctx.hadError()) {
198
+ Scopes.push_back (DC);
199
+ GenericEnv.push_back (DC->getGenericEnvironmentOfContext ());
200
+ }
126
201
127
- static Verifier forDecl (const Decl *D) {
128
- DeclContext *DC = D->getDeclContext ();
129
- DeclContext *topDC = DC->getModuleScopeContext ();
130
- if (auto SF = dyn_cast<SourceFile>(topDC))
131
- return Verifier (*SF, DC);
132
- return Verifier (topDC->getParentModule (), DC);
133
- }
202
+ public:
203
+ Verifier (ModuleDecl *M, DeclContext *DC)
204
+ : Verifier(PointerUnion<ModuleDecl *, SourceFile *>(M), DC) {}
205
+ Verifier (SourceFile &SF, DeclContext *DC) : Verifier(&SF, DC) {}
206
+
207
+ static Verifier forDecl (const Decl *D) {
208
+ DeclContext *DC = D->getDeclContext ();
209
+ DeclContext *topDC = DC->getModuleScopeContext ();
210
+ if (auto SF = dyn_cast<SourceFile>(topDC))
211
+ return Verifier (*SF, DC);
212
+ return Verifier (topDC->getParentModule (), DC);
213
+ }
134
214
135
- std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
136
- switch (E->getKind ()) {
215
+ std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
216
+ switch (E->getKind ()) {
137
217
#define DISPATCH (ID ) return dispatchVisitPreExpr(static_cast <ID##Expr*>(E))
138
218
#define EXPR (ID, PARENT ) \
139
219
case ExprKind::ID: \
@@ -243,7 +323,6 @@ struct ASTNodeBase {};
243
323
llvm_unreachable (" Unhandled declaration kind" );
244
324
}
245
325
246
- private:
247
326
// / Helper template for dispatching pre-visitation.
248
327
// / If we're visiting in pre-order, don't validate the node yet;
249
328
// / just check whether we should stop further descent.
@@ -255,13 +334,11 @@ struct ASTNodeBase {};
255
334
}
256
335
257
336
// / Helper template for dispatching pre-visitation.
337
+ // /
258
338
// / If we're visiting in pre-order, don't validate the node yet;
259
339
// / just check whether we should stop further descent.
260
340
template <class T > std::pair<bool , Expr *> dispatchVisitPreExpr (T node) {
261
- if (shouldVerify (node))
262
- return { true , node };
263
- cleanup (node);
264
- return { false , node };
341
+ return dispatchVisitPreExprHelper<Verifier, T>(*this , node);
265
342
}
266
343
267
344
// / Helper template for dispatching pre-visitation.
@@ -1089,7 +1166,14 @@ struct ASTNodeBase {};
1089
1166
void verifyChecked (InOutToPointerExpr *E) {
1090
1167
PrettyStackTraceExpr debugStack (Ctx,
1091
1168
" verifying InOutToPointer" , E);
1092
-
1169
+
1170
+ if (!WhitelistedInOutToPointerExpr.count (E)) {
1171
+ Out << " Unwhitelisted InOutToPointerExpr?!\n " ;
1172
+ E->print (Out);
1173
+ Out << " \n " ;
1174
+ abort ();
1175
+ }
1176
+
1093
1177
auto fromElement = E->getSubExpr ()->getType ()->getInOutObjectType ();
1094
1178
auto toElement = E->getType ()->getAnyPointerElementType ();
1095
1179
@@ -1116,6 +1200,13 @@ struct ASTNodeBase {};
1116
1200
PrettyStackTraceExpr debugStack (Ctx,
1117
1201
" verifying ArrayToPointer" , E);
1118
1202
1203
+ if (!WhitelistedArrayToPointerExpr.count (E)) {
1204
+ Out << " ArrayToPointer in invalid position?!\n " ;
1205
+ E->print (Out);
1206
+ Out << " \n " ;
1207
+ abort ();
1208
+ }
1209
+
1119
1210
// The source may be optionally inout.
1120
1211
auto fromArray = E->getSubExpr ()->getType ()->getInOutObjectType ();
1121
1212
@@ -1249,6 +1340,48 @@ struct ASTNodeBase {};
1249
1340
verifyCheckedBase (E);
1250
1341
}
1251
1342
1343
+ void updateExprToPointerWhitelist (Expr *Base, Expr *Arg) {
1344
+ auto handleSubExpr = [&](Expr *SubExpr) {
1345
+ // if we have an inject into optional, strip it off.
1346
+ if (auto *InjectIntoOpt = dyn_cast<InjectIntoOptionalExpr>(SubExpr)) {
1347
+ SubExpr = InjectIntoOpt->getSubExpr ();
1348
+ }
1349
+
1350
+ if (auto *InOutToPtr = dyn_cast<InOutToPointerExpr>(SubExpr)) {
1351
+ WhitelistedInOutToPointerExpr.insert (InOutToPtr);
1352
+ return ;
1353
+ }
1354
+
1355
+ if (auto *ArrayToPtr = dyn_cast<ArrayToPointerExpr>(SubExpr)) {
1356
+ WhitelistedArrayToPointerExpr.insert (ArrayToPtr);
1357
+ }
1358
+ };
1359
+
1360
+ // If we have a tuple_shuffle, strip it off. We want to visit the
1361
+ // underlying paren or tuple expr.
1362
+ if (auto *TupleShuffle = dyn_cast<TupleShuffleExpr>(Arg)) {
1363
+ Arg = TupleShuffle->getSubExpr ();
1364
+ }
1365
+
1366
+ if (auto *ParentExprArg = dyn_cast<ParenExpr>(Arg)) {
1367
+ return handleSubExpr (ParentExprArg->getSubExpr ());
1368
+ }
1369
+
1370
+ if (auto *TupleArg = dyn_cast<TupleExpr>(Arg)) {
1371
+ for (auto *SubExpr : TupleArg->getElements ()) {
1372
+ handleSubExpr (SubExpr);
1373
+ }
1374
+ return ;
1375
+ }
1376
+
1377
+ // Otherwise, just run it through handle sub expr. This case can happen if
1378
+ // we have an autoclosure.
1379
+ if (isa<AutoClosureExpr>(Base)) {
1380
+ handleSubExpr (Arg);
1381
+ return ;
1382
+ }
1383
+ }
1384
+
1252
1385
void verifyChecked (ApplyExpr *E) {
1253
1386
PrettyStackTraceExpr debugStack (Ctx, " verifying ApplyExpr" , E);
1254
1387
0 commit comments