@@ -2142,6 +2142,78 @@ namespace {
2142
2142
}
2143
2143
}
2144
2144
2145
+ void ResetKilledBounds (StmtDeclSetTy &KilledBounds, Stmt *St,
2146
+ BoundsContextTy &ObservedBounds) {
2147
+ auto I = KilledBounds.find (St);
2148
+ if (I == KilledBounds.end ())
2149
+ return ;
2150
+
2151
+ // KilledBounds stores a mapping of statements to all variables whose
2152
+ // bounds are killed by each statement. Here we reset the bounds of all
2153
+ // variables killed by the statement S to the declared bounds.
2154
+ for (const VarDecl *V : I->second ) {
2155
+ if (const BoundsExpr *Bounds = V->getBoundsExpr ())
2156
+
2157
+ // TODO: Throughout clang in general (and inside dataflow analysis in
2158
+ // particular) we repeatedly invoke ExpandBoundsToRange in order to
2159
+ // canonicalize the bounds of a variable to RangeBoundsExpr. Sometimes
2160
+ // we do this multiple times for the same variable. This is very
2161
+ // inefficient because ExpandBoundsToRange can allocate AST data
2162
+ // structures that are permanently allocated and increase the memory
2163
+ // usage of the compiler. The solution is to canonicalize the bounds
2164
+ // once and attach it to the VarDecl. See issue
2165
+ // https://github.com/microsoft/checkedc-clang/issues/830.
2166
+
2167
+ ObservedBounds[V] = S.ExpandBoundsToRange (V, Bounds);
2168
+ }
2169
+ }
2170
+
2171
+ void UpdateCtxWithWidenedBounds (BoundsMapTy &WidenedBounds,
2172
+ BoundsContextTy &ObservedBounds) {
2173
+ // WidenedBounds contains the mapping from _Nt_array_ptr to the offset by
2174
+ // which its declared bounds should be widened. In this function we apply
2175
+ // the offset to the declared bounds of the _Nt_array_ptr and update its
2176
+ // bounds in ObservedBounds.
2177
+
2178
+ for (const auto item : WidenedBounds) {
2179
+ const VarDecl *V = item.first ;
2180
+ unsigned Offset = item.second ;
2181
+
2182
+ // We normalize the declared bounds to RangBoundsExpr here so that we
2183
+ // can easily apply the offset to the upper bound.
2184
+
2185
+ // TODO: Throughout clang in general (and inside dataflow analysis in
2186
+ // particular) we repeatedly invoke ExpandBoundsToRange in order to
2187
+ // canonicalize the bounds of a variable to RangeBoundsExpr. Sometimes
2188
+ // we do this multiple times for the same variable. This is very
2189
+ // inefficient because ExpandBoundsToRange can allocate AST data
2190
+ // structures that are permanently allocated and increase the memory
2191
+ // usage of the compiler. The solution is to canonicalize the bounds
2192
+ // once and attach it to the VarDecl. See issue
2193
+ // https://github.com/microsoft/checkedc-clang/issues/830.
2194
+
2195
+ BoundsExpr *Bounds = S.ExpandBoundsToRange (V, V->getBoundsExpr ());
2196
+ if (RangeBoundsExpr *RBE = dyn_cast<RangeBoundsExpr>(Bounds)) {
2197
+ const llvm::APInt
2198
+ APIntOff (Context.getTargetInfo ().getPointerWidth (0 ), Offset);
2199
+ IntegerLiteral *WidenedOffset = CreateIntegerLiteral (APIntOff);
2200
+
2201
+ Expr *Lower = RBE->getLowerExpr ();
2202
+ Expr *Upper = RBE->getUpperExpr ();
2203
+
2204
+ // WidenedUpperBound = UpperBound + WidenedOffset.
2205
+ Expr *WidenedUpper = ExprCreatorUtil::CreateBinaryOperator (
2206
+ S, Upper, WidenedOffset,
2207
+ BinaryOperatorKind::BO_Add);
2208
+
2209
+ RangeBoundsExpr *R =
2210
+ new (Context) RangeBoundsExpr (Lower, WidenedUpper,
2211
+ SourceLocation (), SourceLocation ());
2212
+ ObservedBounds[V] = R;
2213
+ }
2214
+ }
2215
+ }
2216
+
2145
2217
// Walk the CFG, traversing basic blocks in reverse post-oder.
2146
2218
// For each element of a block, check bounds declarations. Skip
2147
2219
// CFG elements that are subexpressions of other CFG elements.
@@ -2177,13 +2249,28 @@ namespace {
2177
2249
StmtSet MemoryCheckedStmts;
2178
2250
StmtSet BoundsCheckedStmts;
2179
2251
IdentifyChecked (Body, MemoryCheckedStmts, BoundsCheckedStmts, CheckedScopeSpecifier::CSS_Unchecked);
2252
+
2253
+ // Run the bounds widening analysis on this function.
2254
+ BoundsAnalysis BA = getBoundsAnalyzer ();
2255
+ BA.WidenBounds (FD);
2256
+ if (S.getLangOpts ().DumpWidenedBounds )
2257
+ BA.DumpWidenedBounds (FD);
2258
+
2180
2259
PostOrderCFGView POView = PostOrderCFGView (Cfg);
2181
2260
ResetFacts ();
2182
2261
for (const CFGBlock *Block : POView) {
2183
2262
AFA.GetFacts (Facts);
2184
2263
CheckingState BlockState = GetIncomingBlockState (Block, BlockStates);
2185
- // TODO: update BlockState.ObservedBounds to reflect the widened bounds
2186
- // for the block.
2264
+
2265
+ // Get the widened bounds for the current block as computed by the
2266
+ // bounds widening analysis invoked by WidenBounds above.
2267
+ BoundsMapTy WidenedBounds = BA.GetWidenedBounds (Block);
2268
+ // Also get the bounds killed (if any) by each statement in the current
2269
+ // block.
2270
+ StmtDeclSetTy KilledBounds = BA.GetKilledBounds (Block);
2271
+ // Update the Observed bounds with the widened bounds calculated above.
2272
+ UpdateCtxWithWidenedBounds (WidenedBounds, BlockState.ObservedBounds );
2273
+
2187
2274
for (CFGElement Elem : *Block) {
2188
2275
if (Elem.getKind () == CFGElement::Statement) {
2189
2276
CFGStmt CS = Elem.castAs <CFGStmt>();
@@ -2218,8 +2305,11 @@ namespace {
2218
2305
// bounds for each variable v that is in scope are the widened
2219
2306
// bounds for v (if any), or the declared bounds for v (if any).
2220
2307
GetDeclaredBounds (this ->S , BlockState.ObservedBounds , S);
2221
- // TODO: update BlockState.ObservedBounds to reset any widened
2222
- // bounds that are killed by S to the declared variable bounds.
2308
+
2309
+ // If any bounds are killed by statement S, reset their bounds
2310
+ // to their declared bounds.
2311
+ ResetKilledBounds (KilledBounds, S, BlockState.ObservedBounds );
2312
+
2223
2313
BoundsContextTy InitialObservedBounds = BlockState.ObservedBounds ;
2224
2314
BlockState.G .clear ();
2225
2315
@@ -5191,13 +5281,6 @@ void Sema::CheckFunctionBodyBoundsDecls(FunctionDecl *FD, Stmt *Body) {
5191
5281
Checker.Check (Body, CheckedScopeSpecifier::CSS_Unchecked);
5192
5282
}
5193
5283
5194
- if (Cfg != nullptr ) {
5195
- BoundsAnalysis BA = Checker.getBoundsAnalyzer ();
5196
- BA.WidenBounds (FD);
5197
- if (getLangOpts ().DumpWidenedBounds )
5198
- BA.DumpWidenedBounds (FD);
5199
- }
5200
-
5201
5284
#if TRACE_CFG
5202
5285
llvm::outs () << " Done " << FD->getName () << " \n " ;
5203
5286
#endif
0 commit comments