Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Analysis/UninitializedValues.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- UninitializedValues.cpp - Find Uninitialized Values ----------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements uninitialized values analysis for source-level CFGs.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/Analysis/Analyses/UninitializedValues.h"
14
#include "clang/AST/Attr.h"
15
#include "clang/AST/Decl.h"
16
#include "clang/AST/DeclBase.h"
17
#include "clang/AST/Expr.h"
18
#include "clang/AST/OperationKinds.h"
19
#include "clang/AST/Stmt.h"
20
#include "clang/AST/StmtObjC.h"
21
#include "clang/AST/StmtVisitor.h"
22
#include "clang/AST/Type.h"
23
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
24
#include "clang/Analysis/AnalysisDeclContext.h"
25
#include "clang/Analysis/CFG.h"
26
#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
27
#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
28
#include "clang/Basic/LLVM.h"
29
#include "llvm/ADT/BitVector.h"
30
#include "llvm/ADT/DenseMap.h"
31
#include "llvm/ADT/PackedVector.h"
32
#include "llvm/ADT/SmallBitVector.h"
33
#include "llvm/ADT/SmallVector.h"
34
#include "llvm/Support/Casting.h"
35
#include <algorithm>
36
#include <cassert>
37
#include <optional>
38
39
using namespace clang;
40
41
#define DEBUG_LOGGING 0
42
43
0
static bool recordIsNotEmpty(const RecordDecl *RD) {
44
  // We consider a record decl to be empty if it contains only unnamed bit-
45
  // fields, zero-width fields, and fields of empty record type.
46
0
  for (const auto *FD : RD->fields()) {
47
0
    if (FD->isUnnamedBitfield())
48
0
      continue;
49
0
    if (FD->isZeroSize(FD->getASTContext()))
50
0
      continue;
51
    // The only case remaining to check is for a field declaration of record
52
    // type and whether that record itself is empty.
53
0
    if (const auto *FieldRD = FD->getType()->getAsRecordDecl();
54
0
        !FieldRD || recordIsNotEmpty(FieldRD))
55
0
      return true;
56
0
  }
57
0
  return false;
58
0
}
59
60
0
static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
61
0
  if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() &&
62
0
      !vd->isExceptionVariable() && !vd->isInitCapture() && !vd->isImplicit() &&
63
0
      vd->getDeclContext() == dc) {
64
0
    QualType ty = vd->getType();
65
0
    if (const auto *RD = ty->getAsRecordDecl())
66
0
      return recordIsNotEmpty(RD);
67
0
    return ty->isScalarType() || ty->isVectorType() || ty->isRVVSizelessBuiltinType();
68
0
  }
69
0
  return false;
70
0
}
71
72
//------------------------------------------------------------------------====//
73
// DeclToIndex: a mapping from Decls we track to value indices.
74
//====------------------------------------------------------------------------//
75
76
namespace {
77
78
class DeclToIndex {
79
  llvm::DenseMap<const VarDecl *, unsigned> map;
80
81
public:
82
0
  DeclToIndex() = default;
83
84
  /// Compute the actual mapping from declarations to bits.
85
  void computeMap(const DeclContext &dc);
86
87
  /// Return the number of declarations in the map.
88
0
  unsigned size() const { return map.size(); }
89
90
  /// Returns the bit vector index for a given declaration.
91
  std::optional<unsigned> getValueIndex(const VarDecl *d) const;
92
};
93
94
} // namespace
95
96
0
void DeclToIndex::computeMap(const DeclContext &dc) {
97
0
  unsigned count = 0;
98
0
  DeclContext::specific_decl_iterator<VarDecl> I(dc.decls_begin()),
99
0
                                               E(dc.decls_end());
100
0
  for ( ; I != E; ++I) {
101
0
    const VarDecl *vd = *I;
102
0
    if (isTrackedVar(vd, &dc))
103
0
      map[vd] = count++;
104
0
  }
105
0
}
106
107
0
std::optional<unsigned> DeclToIndex::getValueIndex(const VarDecl *d) const {
108
0
  llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d);
109
0
  if (I == map.end())
110
0
    return std::nullopt;
111
0
  return I->second;
112
0
}
113
114
//------------------------------------------------------------------------====//
115
// CFGBlockValues: dataflow values for CFG blocks.
116
//====------------------------------------------------------------------------//
117
118
// These values are defined in such a way that a merge can be done using
119
// a bitwise OR.
120
enum Value { Unknown = 0x0,         /* 00 */
121
             Initialized = 0x1,     /* 01 */
122
             Uninitialized = 0x2,   /* 10 */
123
             MayUninitialized = 0x3 /* 11 */ };
124
125
0
static bool isUninitialized(const Value v) {
126
0
  return v >= Uninitialized;
127
0
}
128
129
0
static bool isAlwaysUninit(const Value v) {
130
0
  return v == Uninitialized;
131
0
}
132
133
namespace {
134
135
using ValueVector = llvm::PackedVector<Value, 2, llvm::SmallBitVector>;
136
137
class CFGBlockValues {
138
  const CFG &cfg;
139
  SmallVector<ValueVector, 8> vals;
140
  ValueVector scratch;
141
  DeclToIndex declToIndex;
142
143
public:
144
  CFGBlockValues(const CFG &cfg);
145
146
0
  unsigned getNumEntries() const { return declToIndex.size(); }
147
148
  void computeSetOfDeclarations(const DeclContext &dc);
149
150
0
  ValueVector &getValueVector(const CFGBlock *block) {
151
0
    return vals[block->getBlockID()];
152
0
  }
153
154
  void setAllScratchValues(Value V);
155
  void mergeIntoScratch(ValueVector const &source, bool isFirst);
156
  bool updateValueVectorWithScratch(const CFGBlock *block);
157
158
0
  bool hasNoDeclarations() const {
159
0
    return declToIndex.size() == 0;
160
0
  }
161
162
  void resetScratch();
163
164
  ValueVector::reference operator[](const VarDecl *vd);
165
166
  Value getValue(const CFGBlock *block, const CFGBlock *dstBlock,
167
0
                 const VarDecl *vd) {
168
0
    std::optional<unsigned> idx = declToIndex.getValueIndex(vd);
169
0
    return getValueVector(block)[*idx];
170
0
  }
171
};
172
173
} // namespace
174
175
0
CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {}
176
177
0
void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) {
178
0
  declToIndex.computeMap(dc);
179
0
  unsigned decls = declToIndex.size();
180
0
  scratch.resize(decls);
181
0
  unsigned n = cfg.getNumBlockIDs();
182
0
  if (!n)
183
0
    return;
184
0
  vals.resize(n);
185
0
  for (auto &val : vals)
186
0
    val.resize(decls);
187
0
}
188
189
#if DEBUG_LOGGING
190
static void printVector(const CFGBlock *block, ValueVector &bv,
191
                        unsigned num) {
192
  llvm::errs() << block->getBlockID() << " :";
193
  for (const auto &i : bv)
194
    llvm::errs() << ' ' << i;
195
  llvm::errs() << " : " << num << '\n';
196
}
197
#endif
198
199
0
void CFGBlockValues::setAllScratchValues(Value V) {
200
0
  for (unsigned I = 0, E = scratch.size(); I != E; ++I)
201
0
    scratch[I] = V;
202
0
}
203
204
void CFGBlockValues::mergeIntoScratch(ValueVector const &source,
205
0
                                      bool isFirst) {
206
0
  if (isFirst)
207
0
    scratch = source;
208
0
  else
209
0
    scratch |= source;
210
0
}
211
212
0
bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) {
213
0
  ValueVector &dst = getValueVector(block);
214
0
  bool changed = (dst != scratch);
215
0
  if (changed)
216
0
    dst = scratch;
217
#if DEBUG_LOGGING
218
  printVector(block, scratch, 0);
219
#endif
220
0
  return changed;
221
0
}
222
223
0
void CFGBlockValues::resetScratch() {
224
0
  scratch.reset();
225
0
}
226
227
0
ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) {
228
0
  return scratch[*declToIndex.getValueIndex(vd)];
229
0
}
230
231
//------------------------------------------------------------------------====//
232
// Classification of DeclRefExprs as use or initialization.
233
//====------------------------------------------------------------------------//
234
235
namespace {
236
237
class FindVarResult {
238
  const VarDecl *vd;
239
  const DeclRefExpr *dr;
240
241
public:
242
0
  FindVarResult(const VarDecl *vd, const DeclRefExpr *dr) : vd(vd), dr(dr) {}
243
244
0
  const DeclRefExpr *getDeclRefExpr() const { return dr; }
245
0
  const VarDecl *getDecl() const { return vd; }
246
};
247
248
} // namespace
249
250
0
static const Expr *stripCasts(ASTContext &C, const Expr *Ex) {
251
0
  while (Ex) {
252
0
    Ex = Ex->IgnoreParenNoopCasts(C);
253
0
    if (const auto *CE = dyn_cast<CastExpr>(Ex)) {
254
0
      if (CE->getCastKind() == CK_LValueBitCast) {
255
0
        Ex = CE->getSubExpr();
256
0
        continue;
257
0
      }
258
0
    }
259
0
    break;
260
0
  }
261
0
  return Ex;
262
0
}
263
264
/// If E is an expression comprising a reference to a single variable, find that
265
/// variable.
266
0
static FindVarResult findVar(const Expr *E, const DeclContext *DC) {
267
0
  if (const auto *DRE =
268
0
          dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E)))
269
0
    if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
270
0
      if (isTrackedVar(VD, DC))
271
0
        return FindVarResult(VD, DRE);
272
0
  return FindVarResult(nullptr, nullptr);
273
0
}
274
275
namespace {
276
277
/// Classify each DeclRefExpr as an initialization or a use. Any
278
/// DeclRefExpr which isn't explicitly classified will be assumed to have
279
/// escaped the analysis and will be treated as an initialization.
280
class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
281
public:
282
  enum Class {
283
    Init,
284
    Use,
285
    SelfInit,
286
    ConstRefUse,
287
    Ignore
288
  };
289
290
private:
291
  const DeclContext *DC;
292
  llvm::DenseMap<const DeclRefExpr *, Class> Classification;
293
294
0
  bool isTrackedVar(const VarDecl *VD) const {
295
0
    return ::isTrackedVar(VD, DC);
296
0
  }
297
298
  void classify(const Expr *E, Class C);
299
300
public:
301
0
  ClassifyRefs(AnalysisDeclContext &AC) : DC(cast<DeclContext>(AC.getDecl())) {}
302
303
  void VisitDeclStmt(DeclStmt *DS);
304
  void VisitUnaryOperator(UnaryOperator *UO);
305
  void VisitBinaryOperator(BinaryOperator *BO);
306
  void VisitCallExpr(CallExpr *CE);
307
  void VisitCastExpr(CastExpr *CE);
308
  void VisitOMPExecutableDirective(OMPExecutableDirective *ED);
309
310
0
  void operator()(Stmt *S) { Visit(S); }
311
312
0
  Class get(const DeclRefExpr *DRE) const {
313
0
    llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I
314
0
        = Classification.find(DRE);
315
0
    if (I != Classification.end())
316
0
      return I->second;
317
318
0
    const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
319
0
    if (!VD || !isTrackedVar(VD))
320
0
      return Ignore;
321
322
0
    return Init;
323
0
  }
324
};
325
326
} // namespace
327
328
0
static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
329
0
  if (VD->getType()->isRecordType())
330
0
    return nullptr;
331
0
  if (Expr *Init = VD->getInit()) {
332
0
    const auto *DRE =
333
0
        dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
334
0
    if (DRE && DRE->getDecl() == VD)
335
0
      return DRE;
336
0
  }
337
0
  return nullptr;
338
0
}
339
340
0
void ClassifyRefs::classify(const Expr *E, Class C) {
341
  // The result of a ?: could also be an lvalue.
342
0
  E = E->IgnoreParens();
343
0
  if (const auto *CO = dyn_cast<ConditionalOperator>(E)) {
344
0
    classify(CO->getTrueExpr(), C);
345
0
    classify(CO->getFalseExpr(), C);
346
0
    return;
347
0
  }
348
349
0
  if (const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
350
0
    classify(BCO->getFalseExpr(), C);
351
0
    return;
352
0
  }
353
354
0
  if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) {
355
0
    classify(OVE->getSourceExpr(), C);
356
0
    return;
357
0
  }
358
359
0
  if (const auto *ME = dyn_cast<MemberExpr>(E)) {
360
0
    if (const auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
361
0
      if (!VD->isStaticDataMember())
362
0
        classify(ME->getBase(), C);
363
0
    }
364
0
    return;
365
0
  }
366
367
0
  if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
368
0
    switch (BO->getOpcode()) {
369
0
    case BO_PtrMemD:
370
0
    case BO_PtrMemI:
371
0
      classify(BO->getLHS(), C);
372
0
      return;
373
0
    case BO_Comma:
374
0
      classify(BO->getRHS(), C);
375
0
      return;
376
0
    default:
377
0
      return;
378
0
    }
379
0
  }
380
381
0
  FindVarResult Var = findVar(E, DC);
382
0
  if (const DeclRefExpr *DRE = Var.getDeclRefExpr())
383
0
    Classification[DRE] = std::max(Classification[DRE], C);
384
0
}
385
386
0
void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) {
387
0
  for (auto *DI : DS->decls()) {
388
0
    auto *VD = dyn_cast<VarDecl>(DI);
389
0
    if (VD && isTrackedVar(VD))
390
0
      if (const DeclRefExpr *DRE = getSelfInitExpr(VD))
391
0
        Classification[DRE] = SelfInit;
392
0
  }
393
0
}
394
395
0
void ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) {
396
  // Ignore the evaluation of a DeclRefExpr on the LHS of an assignment. If this
397
  // is not a compound-assignment, we will treat it as initializing the variable
398
  // when TransferFunctions visits it. A compound-assignment does not affect
399
  // whether a variable is uninitialized, and there's no point counting it as a
400
  // use.
401
0
  if (BO->isCompoundAssignmentOp())
402
0
    classify(BO->getLHS(), Use);
403
0
  else if (BO->getOpcode() == BO_Assign || BO->getOpcode() == BO_Comma)
404
0
    classify(BO->getLHS(), Ignore);
405
0
}
406
407
0
void ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) {
408
  // Increment and decrement are uses despite there being no lvalue-to-rvalue
409
  // conversion.
410
0
  if (UO->isIncrementDecrementOp())
411
0
    classify(UO->getSubExpr(), Use);
412
0
}
413
414
0
void ClassifyRefs::VisitOMPExecutableDirective(OMPExecutableDirective *ED) {
415
0
  for (Stmt *S : OMPExecutableDirective::used_clauses_children(ED->clauses()))
416
0
    classify(cast<Expr>(S), Use);
417
0
}
418
419
0
static bool isPointerToConst(const QualType &QT) {
420
0
  return QT->isAnyPointerType() && QT->getPointeeType().isConstQualified();
421
0
}
422
423
0
static bool hasTrivialBody(CallExpr *CE) {
424
0
  if (FunctionDecl *FD = CE->getDirectCallee()) {
425
0
    if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate())
426
0
      return FTD->getTemplatedDecl()->hasTrivialBody();
427
0
    return FD->hasTrivialBody();
428
0
  }
429
0
  return false;
430
0
}
431
432
0
void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
433
  // Classify arguments to std::move as used.
434
0
  if (CE->isCallToStdMove()) {
435
    // RecordTypes are handled in SemaDeclCXX.cpp.
436
0
    if (!CE->getArg(0)->getType()->isRecordType())
437
0
      classify(CE->getArg(0), Use);
438
0
    return;
439
0
  }
440
0
  bool isTrivialBody = hasTrivialBody(CE);
441
  // If a value is passed by const pointer to a function,
442
  // we should not assume that it is initialized by the call, and we
443
  // conservatively do not assume that it is used.
444
  // If a value is passed by const reference to a function,
445
  // it should already be initialized.
446
0
  for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
447
0
       I != E; ++I) {
448
0
    if ((*I)->isGLValue()) {
449
0
      if ((*I)->getType().isConstQualified())
450
0
        classify((*I), isTrivialBody ? Ignore : ConstRefUse);
451
0
    } else if (isPointerToConst((*I)->getType())) {
452
0
      const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
453
0
      const auto *UO = dyn_cast<UnaryOperator>(Ex);
454
0
      if (UO && UO->getOpcode() == UO_AddrOf)
455
0
        Ex = UO->getSubExpr();
456
0
      classify(Ex, Ignore);
457
0
    }
458
0
  }
459
0
}
460
461
0
void ClassifyRefs::VisitCastExpr(CastExpr *CE) {
462
0
  if (CE->getCastKind() == CK_LValueToRValue)
463
0
    classify(CE->getSubExpr(), Use);
464
0
  else if (const auto *CSE = dyn_cast<CStyleCastExpr>(CE)) {
465
0
    if (CSE->getType()->isVoidType()) {
466
      // Squelch any detected load of an uninitialized value if
467
      // we cast it to void.
468
      // e.g. (void) x;
469
0
      classify(CSE->getSubExpr(), Ignore);
470
0
    }
471
0
  }
472
0
}
473
474
//------------------------------------------------------------------------====//
475
// Transfer function for uninitialized values analysis.
476
//====------------------------------------------------------------------------//
477
478
namespace {
479
480
class TransferFunctions : public StmtVisitor<TransferFunctions> {
481
  CFGBlockValues &vals;
482
  const CFG &cfg;
483
  const CFGBlock *block;
484
  AnalysisDeclContext &ac;
485
  const ClassifyRefs &classification;
486
  ObjCNoReturn objCNoRet;
487
  UninitVariablesHandler &handler;
488
489
public:
490
  TransferFunctions(CFGBlockValues &vals, const CFG &cfg,
491
                    const CFGBlock *block, AnalysisDeclContext &ac,
492
                    const ClassifyRefs &classification,
493
                    UninitVariablesHandler &handler)
494
      : vals(vals), cfg(cfg), block(block), ac(ac),
495
        classification(classification), objCNoRet(ac.getASTContext()),
496
0
        handler(handler) {}
497
498
  void reportUse(const Expr *ex, const VarDecl *vd);
499
  void reportConstRefUse(const Expr *ex, const VarDecl *vd);
500
501
  void VisitBinaryOperator(BinaryOperator *bo);
502
  void VisitBlockExpr(BlockExpr *be);
503
  void VisitCallExpr(CallExpr *ce);
504
  void VisitDeclRefExpr(DeclRefExpr *dr);
505
  void VisitDeclStmt(DeclStmt *ds);
506
  void VisitGCCAsmStmt(GCCAsmStmt *as);
507
  void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS);
508
  void VisitObjCMessageExpr(ObjCMessageExpr *ME);
509
  void VisitOMPExecutableDirective(OMPExecutableDirective *ED);
510
511
0
  bool isTrackedVar(const VarDecl *vd) {
512
0
    return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl()));
513
0
  }
514
515
0
  FindVarResult findVar(const Expr *ex) {
516
0
    return ::findVar(ex, cast<DeclContext>(ac.getDecl()));
517
0
  }
518
519
0
  UninitUse getUninitUse(const Expr *ex, const VarDecl *vd, Value v) {
520
0
    UninitUse Use(ex, isAlwaysUninit(v));
521
522
0
    assert(isUninitialized(v));
523
0
    if (Use.getKind() == UninitUse::Always)
524
0
      return Use;
525
526
    // If an edge which leads unconditionally to this use did not initialize
527
    // the variable, we can say something stronger than 'may be uninitialized':
528
    // we can say 'either it's used uninitialized or you have dead code'.
529
    //
530
    // We track the number of successors of a node which have been visited, and
531
    // visit a node once we have visited all of its successors. Only edges where
532
    // the variable might still be uninitialized are followed. Since a variable
533
    // can't transfer from being initialized to being uninitialized, this will
534
    // trace out the subgraph which inevitably leads to the use and does not
535
    // initialize the variable. We do not want to skip past loops, since their
536
    // non-termination might be correlated with the initialization condition.
537
    //
538
    // For example:
539
    //
540
    //         void f(bool a, bool b) {
541
    // block1:   int n;
542
    //           if (a) {
543
    // block2:     if (b)
544
    // block3:       n = 1;
545
    // block4:   } else if (b) {
546
    // block5:     while (!a) {
547
    // block6:       do_work(&a);
548
    //               n = 2;
549
    //             }
550
    //           }
551
    // block7:   if (a)
552
    // block8:     g();
553
    // block9:   return n;
554
    //         }
555
    //
556
    // Starting from the maybe-uninitialized use in block 9:
557
    //  * Block 7 is not visited because we have only visited one of its two
558
    //    successors.
559
    //  * Block 8 is visited because we've visited its only successor.
560
    // From block 8:
561
    //  * Block 7 is visited because we've now visited both of its successors.
562
    // From block 7:
563
    //  * Blocks 1, 2, 4, 5, and 6 are not visited because we didn't visit all
564
    //    of their successors (we didn't visit 4, 3, 5, 6, and 5, respectively).
565
    //  * Block 3 is not visited because it initializes 'n'.
566
    // Now the algorithm terminates, having visited blocks 7 and 8, and having
567
    // found the frontier is blocks 2, 4, and 5.
568
    //
569
    // 'n' is definitely uninitialized for two edges into block 7 (from blocks 2
570
    // and 4), so we report that any time either of those edges is taken (in
571
    // each case when 'b == false'), 'n' is used uninitialized.
572
0
    SmallVector<const CFGBlock*, 32> Queue;
573
0
    SmallVector<unsigned, 32> SuccsVisited(cfg.getNumBlockIDs(), 0);
574
0
    Queue.push_back(block);
575
    // Specify that we've already visited all successors of the starting block.
576
    // This has the dual purpose of ensuring we never add it to the queue, and
577
    // of marking it as not being a candidate element of the frontier.
578
0
    SuccsVisited[block->getBlockID()] = block->succ_size();
579
0
    while (!Queue.empty()) {
580
0
      const CFGBlock *B = Queue.pop_back_val();
581
582
      // If the use is always reached from the entry block, make a note of that.
583
0
      if (B == &cfg.getEntry())
584
0
        Use.setUninitAfterCall();
585
586
0
      for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end();
587
0
           I != E; ++I) {
588
0
        const CFGBlock *Pred = *I;
589
0
        if (!Pred)
590
0
          continue;
591
592
0
        Value AtPredExit = vals.getValue(Pred, B, vd);
593
0
        if (AtPredExit == Initialized)
594
          // This block initializes the variable.
595
0
          continue;
596
0
        if (AtPredExit == MayUninitialized &&
597
0
            vals.getValue(B, nullptr, vd) == Uninitialized) {
598
          // This block declares the variable (uninitialized), and is reachable
599
          // from a block that initializes the variable. We can't guarantee to
600
          // give an earlier location for the diagnostic (and it appears that
601
          // this code is intended to be reachable) so give a diagnostic here
602
          // and go no further down this path.
603
0
          Use.setUninitAfterDecl();
604
0
          continue;
605
0
        }
606
607
0
        unsigned &SV = SuccsVisited[Pred->getBlockID()];
608
0
        if (!SV) {
609
          // When visiting the first successor of a block, mark all NULL
610
          // successors as having been visited.
611
0
          for (CFGBlock::const_succ_iterator SI = Pred->succ_begin(),
612
0
                                             SE = Pred->succ_end();
613
0
               SI != SE; ++SI)
614
0
            if (!*SI)
615
0
              ++SV;
616
0
        }
617
618
0
        if (++SV == Pred->succ_size())
619
          // All paths from this block lead to the use and don't initialize the
620
          // variable.
621
0
          Queue.push_back(Pred);
622
0
      }
623
0
    }
624
625
    // Scan the frontier, looking for blocks where the variable was
626
    // uninitialized.
627
0
    for (const auto *Block : cfg) {
628
0
      unsigned BlockID = Block->getBlockID();
629
0
      const Stmt *Term = Block->getTerminatorStmt();
630
0
      if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() &&
631
0
          Term) {
632
        // This block inevitably leads to the use. If we have an edge from here
633
        // to a post-dominator block, and the variable is uninitialized on that
634
        // edge, we have found a bug.
635
0
        for (CFGBlock::const_succ_iterator I = Block->succ_begin(),
636
0
             E = Block->succ_end(); I != E; ++I) {
637
0
          const CFGBlock *Succ = *I;
638
0
          if (Succ && SuccsVisited[Succ->getBlockID()] >= Succ->succ_size() &&
639
0
              vals.getValue(Block, Succ, vd) == Uninitialized) {
640
            // Switch cases are a special case: report the label to the caller
641
            // as the 'terminator', not the switch statement itself. Suppress
642
            // situations where no label matched: we can't be sure that's
643
            // possible.
644
0
            if (isa<SwitchStmt>(Term)) {
645
0
              const Stmt *Label = Succ->getLabel();
646
0
              if (!Label || !isa<SwitchCase>(Label))
647
                // Might not be possible.
648
0
                continue;
649
0
              UninitUse::Branch Branch;
650
0
              Branch.Terminator = Label;
651
0
              Branch.Output = 0; // Ignored.
652
0
              Use.addUninitBranch(Branch);
653
0
            } else {
654
0
              UninitUse::Branch Branch;
655
0
              Branch.Terminator = Term;
656
0
              Branch.Output = I - Block->succ_begin();
657
0
              Use.addUninitBranch(Branch);
658
0
            }
659
0
          }
660
0
        }
661
0
      }
662
0
    }
663
664
0
    return Use;
665
0
  }
666
};
667
668
} // namespace
669
670
0
void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
671
0
  Value v = vals[vd];
672
0
  if (isUninitialized(v))
673
0
    handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
674
0
}
675
676
0
void TransferFunctions::reportConstRefUse(const Expr *ex, const VarDecl *vd) {
677
0
  Value v = vals[vd];
678
0
  if (isAlwaysUninit(v))
679
0
    handler.handleConstRefUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
680
0
}
681
682
0
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
683
  // This represents an initialization of the 'element' value.
684
0
  if (const auto *DS = dyn_cast<DeclStmt>(FS->getElement())) {
685
0
    const auto *VD = cast<VarDecl>(DS->getSingleDecl());
686
0
    if (isTrackedVar(VD))
687
0
      vals[VD] = Initialized;
688
0
  }
689
0
}
690
691
void TransferFunctions::VisitOMPExecutableDirective(
692
0
    OMPExecutableDirective *ED) {
693
0
  for (Stmt *S : OMPExecutableDirective::used_clauses_children(ED->clauses())) {
694
0
    assert(S && "Expected non-null used-in-clause child.");
695
0
    Visit(S);
696
0
  }
697
0
  if (!ED->isStandaloneDirective())
698
0
    Visit(ED->getStructuredBlock());
699
0
}
700
701
0
void TransferFunctions::VisitBlockExpr(BlockExpr *be) {
702
0
  const BlockDecl *bd = be->getBlockDecl();
703
0
  for (const auto &I : bd->captures()) {
704
0
    const VarDecl *vd = I.getVariable();
705
0
    if (!isTrackedVar(vd))
706
0
      continue;
707
0
    if (I.isByRef()) {
708
0
      vals[vd] = Initialized;
709
0
      continue;
710
0
    }
711
0
    reportUse(be, vd);
712
0
  }
713
0
}
714
715
0
void TransferFunctions::VisitCallExpr(CallExpr *ce) {
716
0
  if (Decl *Callee = ce->getCalleeDecl()) {
717
0
    if (Callee->hasAttr<ReturnsTwiceAttr>()) {
718
      // After a call to a function like setjmp or vfork, any variable which is
719
      // initialized anywhere within this function may now be initialized. For
720
      // now, just assume such a call initializes all variables.  FIXME: Only
721
      // mark variables as initialized if they have an initializer which is
722
      // reachable from here.
723
0
      vals.setAllScratchValues(Initialized);
724
0
    }
725
0
    else if (Callee->hasAttr<AnalyzerNoReturnAttr>()) {
726
      // Functions labeled like "analyzer_noreturn" are often used to denote
727
      // "panic" functions that in special debug situations can still return,
728
      // but for the most part should not be treated as returning.  This is a
729
      // useful annotation borrowed from the static analyzer that is useful for
730
      // suppressing branch-specific false positives when we call one of these
731
      // functions but keep pretending the path continues (when in reality the
732
      // user doesn't care).
733
0
      vals.setAllScratchValues(Unknown);
734
0
    }
735
0
  }
736
0
}
737
738
0
void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
739
0
  switch (classification.get(dr)) {
740
0
  case ClassifyRefs::Ignore:
741
0
    break;
742
0
  case ClassifyRefs::Use:
743
0
    reportUse(dr, cast<VarDecl>(dr->getDecl()));
744
0
    break;
745
0
  case ClassifyRefs::Init:
746
0
    vals[cast<VarDecl>(dr->getDecl())] = Initialized;
747
0
    break;
748
0
  case ClassifyRefs::SelfInit:
749
0
    handler.handleSelfInit(cast<VarDecl>(dr->getDecl()));
750
0
    break;
751
0
  case ClassifyRefs::ConstRefUse:
752
0
    reportConstRefUse(dr, cast<VarDecl>(dr->getDecl()));
753
0
    break;
754
0
  }
755
0
}
756
757
0
void TransferFunctions::VisitBinaryOperator(BinaryOperator *BO) {
758
0
  if (BO->getOpcode() == BO_Assign) {
759
0
    FindVarResult Var = findVar(BO->getLHS());
760
0
    if (const VarDecl *VD = Var.getDecl())
761
0
      vals[VD] = Initialized;
762
0
  }
763
0
}
764
765
0
void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
766
0
  for (auto *DI : DS->decls()) {
767
0
    auto *VD = dyn_cast<VarDecl>(DI);
768
0
    if (VD && isTrackedVar(VD)) {
769
0
      if (getSelfInitExpr(VD)) {
770
        // If the initializer consists solely of a reference to itself, we
771
        // explicitly mark the variable as uninitialized. This allows code
772
        // like the following:
773
        //
774
        //   int x = x;
775
        //
776
        // to deliberately leave a variable uninitialized. Different analysis
777
        // clients can detect this pattern and adjust their reporting
778
        // appropriately, but we need to continue to analyze subsequent uses
779
        // of the variable.
780
0
        vals[VD] = Uninitialized;
781
0
      } else if (VD->getInit()) {
782
        // Treat the new variable as initialized.
783
0
        vals[VD] = Initialized;
784
0
      } else {
785
        // No initializer: the variable is now uninitialized. This matters
786
        // for cases like:
787
        //   while (...) {
788
        //     int n;
789
        //     use(n);
790
        //     n = 0;
791
        //   }
792
        // FIXME: Mark the variable as uninitialized whenever its scope is
793
        // left, since its scope could be re-entered by a jump over the
794
        // declaration.
795
0
        vals[VD] = Uninitialized;
796
0
      }
797
0
    }
798
0
  }
799
0
}
800
801
0
void TransferFunctions::VisitGCCAsmStmt(GCCAsmStmt *as) {
802
  // An "asm goto" statement is a terminator that may initialize some variables.
803
0
  if (!as->isAsmGoto())
804
0
    return;
805
806
0
  ASTContext &C = ac.getASTContext();
807
0
  for (const Expr *O : as->outputs()) {
808
0
    const Expr *Ex = stripCasts(C, O);
809
810
    // Strip away any unary operators. Invalid l-values are reported by other
811
    // semantic analysis passes.
812
0
    while (const auto *UO = dyn_cast<UnaryOperator>(Ex))
813
0
      Ex = stripCasts(C, UO->getSubExpr());
814
815
    // Mark the variable as potentially uninitialized for those cases where
816
    // it's used on an indirect path, where it's not guaranteed to be
817
    // defined.
818
0
    if (const VarDecl *VD = findVar(Ex).getDecl())
819
0
      if (vals[VD] != Initialized)
820
0
        vals[VD] = MayUninitialized;
821
0
  }
822
0
}
823
824
0
void TransferFunctions::VisitObjCMessageExpr(ObjCMessageExpr *ME) {
825
  // If the Objective-C message expression is an implicit no-return that
826
  // is not modeled in the CFG, set the tracked dataflow values to Unknown.
827
0
  if (objCNoRet.isImplicitNoReturn(ME)) {
828
0
    vals.setAllScratchValues(Unknown);
829
0
  }
830
0
}
831
832
//------------------------------------------------------------------------====//
833
// High-level "driver" logic for uninitialized values analysis.
834
//====------------------------------------------------------------------------//
835
836
static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
837
                       AnalysisDeclContext &ac, CFGBlockValues &vals,
838
                       const ClassifyRefs &classification,
839
                       llvm::BitVector &wasAnalyzed,
840
0
                       UninitVariablesHandler &handler) {
841
0
  wasAnalyzed[block->getBlockID()] = true;
842
0
  vals.resetScratch();
843
  // Merge in values of predecessor blocks.
844
0
  bool isFirst = true;
845
0
  for (CFGBlock::const_pred_iterator I = block->pred_begin(),
846
0
       E = block->pred_end(); I != E; ++I) {
847
0
    const CFGBlock *pred = *I;
848
0
    if (!pred)
849
0
      continue;
850
0
    if (wasAnalyzed[pred->getBlockID()]) {
851
0
      vals.mergeIntoScratch(vals.getValueVector(pred), isFirst);
852
0
      isFirst = false;
853
0
    }
854
0
  }
855
  // Apply the transfer function.
856
0
  TransferFunctions tf(vals, cfg, block, ac, classification, handler);
857
0
  for (const auto &I : *block) {
858
0
    if (std::optional<CFGStmt> cs = I.getAs<CFGStmt>())
859
0
      tf.Visit(const_cast<Stmt *>(cs->getStmt()));
860
0
  }
861
0
  CFGTerminator terminator = block->getTerminator();
862
0
  if (auto *as = dyn_cast_or_null<GCCAsmStmt>(terminator.getStmt()))
863
0
    if (as->isAsmGoto())
864
0
      tf.Visit(as);
865
0
  return vals.updateValueVectorWithScratch(block);
866
0
}
867
868
namespace {
869
870
/// PruneBlocksHandler is a special UninitVariablesHandler that is used
871
/// to detect when a CFGBlock has any *potential* use of an uninitialized
872
/// variable.  It is mainly used to prune out work during the final
873
/// reporting pass.
874
struct PruneBlocksHandler : public UninitVariablesHandler {
875
  /// Records if a CFGBlock had a potential use of an uninitialized variable.
876
  llvm::BitVector hadUse;
877
878
  /// Records if any CFGBlock had a potential use of an uninitialized variable.
879
  bool hadAnyUse = false;
880
881
  /// The current block to scribble use information.
882
  unsigned currentBlock = 0;
883
884
0
  PruneBlocksHandler(unsigned numBlocks) : hadUse(numBlocks, false) {}
885
886
0
  ~PruneBlocksHandler() override = default;
887
888
  void handleUseOfUninitVariable(const VarDecl *vd,
889
0
                                 const UninitUse &use) override {
890
0
    hadUse[currentBlock] = true;
891
0
    hadAnyUse = true;
892
0
  }
893
894
  void handleConstRefUseOfUninitVariable(const VarDecl *vd,
895
0
                                         const UninitUse &use) override {
896
0
    hadUse[currentBlock] = true;
897
0
    hadAnyUse = true;
898
0
  }
899
900
  /// Called when the uninitialized variable analysis detects the
901
  /// idiom 'int x = x'.  All other uses of 'x' within the initializer
902
  /// are handled by handleUseOfUninitVariable.
903
0
  void handleSelfInit(const VarDecl *vd) override {
904
0
    hadUse[currentBlock] = true;
905
0
    hadAnyUse = true;
906
0
  }
907
};
908
909
} // namespace
910
911
void clang::runUninitializedVariablesAnalysis(
912
    const DeclContext &dc,
913
    const CFG &cfg,
914
    AnalysisDeclContext &ac,
915
    UninitVariablesHandler &handler,
916
0
    UninitVariablesAnalysisStats &stats) {
917
0
  CFGBlockValues vals(cfg);
918
0
  vals.computeSetOfDeclarations(dc);
919
0
  if (vals.hasNoDeclarations())
920
0
    return;
921
922
0
  stats.NumVariablesAnalyzed = vals.getNumEntries();
923
924
  // Precompute which expressions are uses and which are initializations.
925
0
  ClassifyRefs classification(ac);
926
0
  cfg.VisitBlockStmts(classification);
927
928
  // Mark all variables uninitialized at the entry.
929
0
  const CFGBlock &entry = cfg.getEntry();
930
0
  ValueVector &vec = vals.getValueVector(&entry);
931
0
  const unsigned n = vals.getNumEntries();
932
0
  for (unsigned j = 0; j < n; ++j) {
933
0
    vec[j] = Uninitialized;
934
0
  }
935
936
  // Proceed with the workist.
937
0
  ForwardDataflowWorklist worklist(cfg, ac);
938
0
  llvm::BitVector previouslyVisited(cfg.getNumBlockIDs());
939
0
  worklist.enqueueSuccessors(&cfg.getEntry());
940
0
  llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);
941
0
  wasAnalyzed[cfg.getEntry().getBlockID()] = true;
942
0
  PruneBlocksHandler PBH(cfg.getNumBlockIDs());
943
944
0
  while (const CFGBlock *block = worklist.dequeue()) {
945
0
    PBH.currentBlock = block->getBlockID();
946
947
    // Did the block change?
948
0
    bool changed = runOnBlock(block, cfg, ac, vals,
949
0
                              classification, wasAnalyzed, PBH);
950
0
    ++stats.NumBlockVisits;
951
0
    if (changed || !previouslyVisited[block->getBlockID()])
952
0
      worklist.enqueueSuccessors(block);
953
0
    previouslyVisited[block->getBlockID()] = true;
954
0
  }
955
956
0
  if (!PBH.hadAnyUse)
957
0
    return;
958
959
  // Run through the blocks one more time, and report uninitialized variables.
960
0
  for (const auto *block : cfg)
961
0
    if (PBH.hadUse[block->getBlockID()]) {
962
0
      runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler);
963
0
      ++stats.NumBlockVisits;
964
0
    }
965
0
}
966
967
0
UninitVariablesHandler::~UninitVariablesHandler() = default;