clang 17.0.0git
AnalysisBasedWarnings.cpp
Go to the documentation of this file.
1//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=//
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 defines analysis_warnings::[Policy,Executor].
10// Together they are used by Sema to issue warnings based on inexpensive
11// static analysis algorithms in libAnalysis.
12//
13//===----------------------------------------------------------------------===//
14
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclObjC.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/ExprCXX.h"
21#include "clang/AST/ExprObjC.h"
23#include "clang/AST/ParentMap.h"
25#include "clang/AST/StmtCXX.h"
26#include "clang/AST/StmtObjC.h"
36#include "clang/Analysis/CFG.h"
43#include "llvm/ADT/ArrayRef.h"
44#include "llvm/ADT/BitVector.h"
45#include "llvm/ADT/MapVector.h"
46#include "llvm/ADT/SmallString.h"
47#include "llvm/ADT/SmallVector.h"
48#include "llvm/ADT/StringRef.h"
49#include "llvm/Support/Casting.h"
50#include <algorithm>
51#include <deque>
52#include <iterator>
53#include <optional>
54
55using namespace clang;
56
57//===----------------------------------------------------------------------===//
58// Unreachable code analysis.
59//===----------------------------------------------------------------------===//
60
61namespace {
62 class UnreachableCodeHandler : public reachable_code::Callback {
63 Sema &S;
64 SourceRange PreviousSilenceableCondVal;
65
66 public:
67 UnreachableCodeHandler(Sema &s) : S(s) {}
68
71 SourceRange SilenceableCondVal,
72 SourceRange R1,
73 SourceRange R2) override {
74 // Avoid reporting multiple unreachable code diagnostics that are
75 // triggered by the same conditional value.
76 if (PreviousSilenceableCondVal.isValid() &&
77 SilenceableCondVal.isValid() &&
78 PreviousSilenceableCondVal == SilenceableCondVal)
79 return;
80 PreviousSilenceableCondVal = SilenceableCondVal;
81
82 unsigned diag = diag::warn_unreachable;
83 switch (UK) {
85 diag = diag::warn_unreachable_break;
86 break;
88 diag = diag::warn_unreachable_return;
89 break;
91 diag = diag::warn_unreachable_loop_increment;
92 break;
94 break;
95 }
96
97 S.Diag(L, diag) << R1 << R2;
98
99 SourceLocation Open = SilenceableCondVal.getBegin();
100 if (Open.isValid()) {
101 SourceLocation Close = SilenceableCondVal.getEnd();
102 Close = S.getLocForEndOfToken(Close);
103 if (Close.isValid()) {
104 S.Diag(Open, diag::note_unreachable_silence)
105 << FixItHint::CreateInsertion(Open, "/* DISABLES CODE */ (")
106 << FixItHint::CreateInsertion(Close, ")");
107 }
108 }
109 }
110 };
111} // anonymous namespace
112
113/// CheckUnreachable - Check for unreachable code.
115 // As a heuristic prune all diagnostics not in the main file. Currently
116 // the majority of warnings in headers are false positives. These
117 // are largely caused by configuration state, e.g. preprocessor
118 // defined code, etc.
119 //
120 // Note that this is also a performance optimization. Analyzing
121 // headers many times can be expensive.
123 return;
124
125 UnreachableCodeHandler UC(S);
127}
128
129namespace {
130/// Warn on logical operator errors in CFGBuilder
131class LogicalErrorHandler : public CFGCallback {
132 Sema &S;
133
134public:
135 LogicalErrorHandler(Sema &S) : S(S) {}
136
137 static bool HasMacroID(const Expr *E) {
138 if (E->getExprLoc().isMacroID())
139 return true;
140
141 // Recurse to children.
142 for (const Stmt *SubStmt : E->children())
143 if (const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
144 if (HasMacroID(SubExpr))
145 return true;
146
147 return false;
148 }
149
150 void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override {
151 if (HasMacroID(B))
152 return;
153
154 SourceRange DiagRange = B->getSourceRange();
155 S.Diag(B->getExprLoc(), diag::warn_tautological_overlap_comparison)
156 << DiagRange << isAlwaysTrue;
157 }
158
160 bool isAlwaysTrue) override {
161 if (HasMacroID(B))
162 return;
163
164 SourceRange DiagRange = B->getSourceRange();
165 S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_always)
166 << DiagRange << isAlwaysTrue;
167 }
168
169 void compareBitwiseOr(const BinaryOperator *B) override {
170 if (HasMacroID(B))
171 return;
172
173 SourceRange DiagRange = B->getSourceRange();
174 S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_or) << DiagRange;
175 }
176
177 static bool hasActiveDiagnostics(DiagnosticsEngine &Diags,
178 SourceLocation Loc) {
179 return !Diags.isIgnored(diag::warn_tautological_overlap_comparison, Loc) ||
180 !Diags.isIgnored(diag::warn_comparison_bitwise_or, Loc);
181 }
182};
183} // anonymous namespace
184
185//===----------------------------------------------------------------------===//
186// Check for infinite self-recursion in functions
187//===----------------------------------------------------------------------===//
188
189// Returns true if the function is called anywhere within the CFGBlock.
190// For member functions, the additional condition of being call from the
191// this pointer is required.
193 // Process all the Stmt's in this block to find any calls to FD.
194 for (const auto &B : Block) {
195 if (B.getKind() != CFGElement::Statement)
196 continue;
197
198 const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
199 if (!CE || !CE->getCalleeDecl() ||
200 CE->getCalleeDecl()->getCanonicalDecl() != FD)
201 continue;
202
203 // Skip function calls which are qualified with a templated class.
204 if (const DeclRefExpr *DRE =
205 dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) {
206 if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
207 if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
208 isa<TemplateSpecializationType>(NNS->getAsType())) {
209 continue;
210 }
211 }
212 }
213
214 const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE);
215 if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
216 !MCE->getMethodDecl()->isVirtual())
217 return true;
218 }
219 return false;
220}
221
222// Returns true if every path from the entry block passes through a call to FD.
223static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
226 // Keep track of whether we found at least one recursive path.
227 bool foundRecursion = false;
228
229 const unsigned ExitID = cfg->getExit().getBlockID();
230
231 // Seed the work list with the entry block.
232 WorkList.push_back(&cfg->getEntry());
233
234 while (!WorkList.empty()) {
235 CFGBlock *Block = WorkList.pop_back_val();
236
237 for (auto I = Block->succ_begin(), E = Block->succ_end(); I != E; ++I) {
238 if (CFGBlock *SuccBlock = *I) {
239 if (!Visited.insert(SuccBlock).second)
240 continue;
241
242 // Found a path to the exit node without a recursive call.
243 if (ExitID == SuccBlock->getBlockID())
244 return false;
245
246 // If the successor block contains a recursive call, end analysis there.
247 if (hasRecursiveCallInPath(FD, *SuccBlock)) {
248 foundRecursion = true;
249 continue;
250 }
251
252 WorkList.push_back(SuccBlock);
253 }
254 }
255 }
256 return foundRecursion;
257}
258
259static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
260 const Stmt *Body, AnalysisDeclContext &AC) {
261 FD = FD->getCanonicalDecl();
262
263 // Only run on non-templated functions and non-templated members of
264 // templated classes.
267 return;
268
269 CFG *cfg = AC.getCFG();
270 if (!cfg) return;
271
272 // If the exit block is unreachable, skip processing the function.
273 if (cfg->getExit().pred_empty())
274 return;
275
276 // Emit diagnostic if a recursive function call is detected for all paths.
278 S.Diag(Body->getBeginLoc(), diag::warn_infinite_recursive_function);
279}
280
281//===----------------------------------------------------------------------===//
282// Check for throw in a non-throwing function.
283//===----------------------------------------------------------------------===//
284
285/// Determine whether an exception thrown by E, unwinding from ThrowBlock,
286/// can reach ExitBlock.
287static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock,
288 CFG *Body) {
290 llvm::BitVector Queued(Body->getNumBlockIDs());
291
292 Stack.push_back(&ThrowBlock);
293 Queued[ThrowBlock.getBlockID()] = true;
294
295 while (!Stack.empty()) {
296 CFGBlock &UnwindBlock = *Stack.back();
297 Stack.pop_back();
298
299 for (auto &Succ : UnwindBlock.succs()) {
300 if (!Succ.isReachable() || Queued[Succ->getBlockID()])
301 continue;
302
303 if (Succ->getBlockID() == Body->getExit().getBlockID())
304 return true;
305
306 if (auto *Catch =
307 dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
308 QualType Caught = Catch->getCaughtType();
309 if (Caught.isNull() || // catch (...) catches everything
310 !E->getSubExpr() || // throw; is considered cuaght by any handler
311 S.handlerCanCatch(Caught, E->getSubExpr()->getType()))
312 // Exception doesn't escape via this path.
313 break;
314 } else {
315 Stack.push_back(Succ);
316 Queued[Succ->getBlockID()] = true;
317 }
318 }
319 }
320
321 return false;
322}
323
325 CFG *BodyCFG,
326 llvm::function_ref<void(const CXXThrowExpr *, CFGBlock &)> Visit) {
327 llvm::BitVector Reachable(BodyCFG->getNumBlockIDs());
329 for (CFGBlock *B : *BodyCFG) {
330 if (!Reachable[B->getBlockID()])
331 continue;
332 for (CFGElement &E : *B) {
333 std::optional<CFGStmt> S = E.getAs<CFGStmt>();
334 if (!S)
335 continue;
336 if (auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
337 Visit(Throw, *B);
338 }
339 }
340}
341
343 const FunctionDecl *FD) {
344 if (!S.getSourceManager().isInSystemHeader(OpLoc) &&
345 FD->getTypeSourceInfo()) {
346 S.Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
347 if (S.getLangOpts().CPlusPlus11 &&
348 (isa<CXXDestructorDecl>(FD) ||
349 FD->getDeclName().getCXXOverloadedOperator() == OO_Delete ||
350 FD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete)) {
351 if (const auto *Ty = FD->getTypeSourceInfo()->getType()->
352 getAs<FunctionProtoType>())
353 S.Diag(FD->getLocation(), diag::note_throw_in_dtor)
354 << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
356 } else
357 S.Diag(FD->getLocation(), diag::note_throw_in_function)
359 }
360}
361
364 CFG *BodyCFG = AC.getCFG();
365 if (!BodyCFG)
366 return;
367 if (BodyCFG->getExit().pred_empty())
368 return;
369 visitReachableThrows(BodyCFG, [&](const CXXThrowExpr *Throw, CFGBlock &Block) {
370 if (throwEscapes(S, Throw, Block, BodyCFG))
372 });
373}
374
375static bool isNoexcept(const FunctionDecl *FD) {
376 const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
377 if (FPT->isNothrow() || FD->hasAttr<NoThrowAttr>())
378 return true;
379 return false;
380}
381
382//===----------------------------------------------------------------------===//
383// Check for missing return value.
384//===----------------------------------------------------------------------===//
385
393
394/// CheckFallThrough - Check that we don't fall off the end of a
395/// Statement that should return a value.
396///
397/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
398/// MaybeFallThrough iff we might or might not fall off the end,
399/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
400/// return. We assume NeverFallThrough iff we never fall off the end of the
401/// statement but we may return. We assume that functions not marked noreturn
402/// will return.
404 CFG *cfg = AC.getCFG();
405 if (!cfg) return UnknownFallThrough;
406
407 // The CFG leaves in dead things, and we don't want the dead code paths to
408 // confuse us, so we mark all live things first.
409 llvm::BitVector live(cfg->getNumBlockIDs());
410 unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(),
411 live);
412
413 bool AddEHEdges = AC.getAddEHEdges();
414 if (!AddEHEdges && count != cfg->getNumBlockIDs())
415 // When there are things remaining dead, and we didn't add EH edges
416 // from CallExprs to the catch clauses, we have to go back and
417 // mark them as live.
418 for (const auto *B : *cfg) {
419 if (!live[B->getBlockID()]) {
420 if (B->pred_begin() == B->pred_end()) {
421 const Stmt *Term = B->getTerminatorStmt();
422 if (Term && isa<CXXTryStmt>(Term))
423 // When not adding EH edges from calls, catch clauses
424 // can otherwise seem dead. Avoid noting them as dead.
426 continue;
427 }
428 }
429 }
430
431 // Now we know what is live, we check the live precessors of the exit block
432 // and look for fall through paths, being careful to ignore normal returns,
433 // and exceptional paths.
434 bool HasLiveReturn = false;
435 bool HasFakeEdge = false;
436 bool HasPlainEdge = false;
437 bool HasAbnormalEdge = false;
438
439 // Ignore default cases that aren't likely to be reachable because all
440 // enums in a switch(X) have explicit case statements.
443
446 I.hasMore(); ++I) {
447 const CFGBlock &B = **I;
448 if (!live[B.getBlockID()])
449 continue;
450
451 // Skip blocks which contain an element marked as no-return. They don't
452 // represent actually viable edges into the exit block, so mark them as
453 // abnormal.
454 if (B.hasNoReturnElement()) {
455 HasAbnormalEdge = true;
456 continue;
457 }
458
459 // Destructors can appear after the 'return' in the CFG. This is
460 // normal. We need to look pass the destructors for the return
461 // statement (if it exists).
463
464 for ( ; ri != re ; ++ri)
465 if (ri->getAs<CFGStmt>())
466 break;
467
468 // No more CFGElements in the block?
469 if (ri == re) {
470 const Stmt *Term = B.getTerminatorStmt();
471 if (Term && (isa<CXXTryStmt>(Term) || isa<ObjCAtTryStmt>(Term))) {
472 HasAbnormalEdge = true;
473 continue;
474 }
475 // A labeled empty statement, or the entry block...
476 HasPlainEdge = true;
477 continue;
478 }
479
480 CFGStmt CS = ri->castAs<CFGStmt>();
481 const Stmt *S = CS.getStmt();
482 if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
483 HasLiveReturn = true;
484 continue;
485 }
486 if (isa<ObjCAtThrowStmt>(S)) {
487 HasFakeEdge = true;
488 continue;
489 }
490 if (isa<CXXThrowExpr>(S)) {
491 HasFakeEdge = true;
492 continue;
493 }
494 if (isa<MSAsmStmt>(S)) {
495 // TODO: Verify this is correct.
496 HasFakeEdge = true;
497 HasLiveReturn = true;
498 continue;
499 }
500 if (isa<CXXTryStmt>(S)) {
501 HasAbnormalEdge = true;
502 continue;
503 }
504 if (!llvm::is_contained(B.succs(), &cfg->getExit())) {
505 HasAbnormalEdge = true;
506 continue;
507 }
508
509 HasPlainEdge = true;
510 }
511 if (!HasPlainEdge) {
512 if (HasLiveReturn)
513 return NeverFallThrough;
515 }
516 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
517 return MaybeFallThrough;
518 // This says AlwaysFallThrough for calls to functions that are not marked
519 // noreturn, that don't return. If people would like this warning to be more
520 // accurate, such functions should be marked as noreturn.
521 return AlwaysFallThrough;
522}
523
524namespace {
525
526struct CheckFallThroughDiagnostics {
527 unsigned diag_MaybeFallThrough_HasNoReturn;
528 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
529 unsigned diag_AlwaysFallThrough_HasNoReturn;
530 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
531 unsigned diag_NeverFallThroughOrReturn;
532 enum { Function, Block, Lambda, Coroutine } funMode;
533 SourceLocation FuncLoc;
534
535 static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
536 CheckFallThroughDiagnostics D;
537 D.FuncLoc = Func->getLocation();
538 D.diag_MaybeFallThrough_HasNoReturn =
539 diag::warn_falloff_noreturn_function;
540 D.diag_MaybeFallThrough_ReturnsNonVoid =
541 diag::warn_maybe_falloff_nonvoid_function;
542 D.diag_AlwaysFallThrough_HasNoReturn =
543 diag::warn_falloff_noreturn_function;
544 D.diag_AlwaysFallThrough_ReturnsNonVoid =
545 diag::warn_falloff_nonvoid_function;
546
547 // Don't suggest that virtual functions be marked "noreturn", since they
548 // might be overridden by non-noreturn functions.
549 bool isVirtualMethod = false;
550 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
551 isVirtualMethod = Method->isVirtual();
552
553 // Don't suggest that template instantiations be marked "noreturn"
554 bool isTemplateInstantiation = false;
555 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
556 isTemplateInstantiation = Function->isTemplateInstantiation();
557
558 if (!isVirtualMethod && !isTemplateInstantiation)
559 D.diag_NeverFallThroughOrReturn =
560 diag::warn_suggest_noreturn_function;
561 else
562 D.diag_NeverFallThroughOrReturn = 0;
563
564 D.funMode = Function;
565 return D;
566 }
567
568 static CheckFallThroughDiagnostics MakeForCoroutine(const Decl *Func) {
569 CheckFallThroughDiagnostics D;
570 D.FuncLoc = Func->getLocation();
571 D.diag_MaybeFallThrough_HasNoReturn = 0;
572 D.diag_MaybeFallThrough_ReturnsNonVoid =
573 diag::warn_maybe_falloff_nonvoid_coroutine;
574 D.diag_AlwaysFallThrough_HasNoReturn = 0;
575 D.diag_AlwaysFallThrough_ReturnsNonVoid =
576 diag::warn_falloff_nonvoid_coroutine;
577 D.funMode = Coroutine;
578 return D;
579 }
580
581 static CheckFallThroughDiagnostics MakeForBlock() {
582 CheckFallThroughDiagnostics D;
583 D.diag_MaybeFallThrough_HasNoReturn =
584 diag::err_noreturn_block_has_return_expr;
585 D.diag_MaybeFallThrough_ReturnsNonVoid =
586 diag::err_maybe_falloff_nonvoid_block;
587 D.diag_AlwaysFallThrough_HasNoReturn =
588 diag::err_noreturn_block_has_return_expr;
589 D.diag_AlwaysFallThrough_ReturnsNonVoid =
590 diag::err_falloff_nonvoid_block;
591 D.diag_NeverFallThroughOrReturn = 0;
592 D.funMode = Block;
593 return D;
594 }
595
596 static CheckFallThroughDiagnostics MakeForLambda() {
597 CheckFallThroughDiagnostics D;
598 D.diag_MaybeFallThrough_HasNoReturn =
599 diag::err_noreturn_lambda_has_return_expr;
600 D.diag_MaybeFallThrough_ReturnsNonVoid =
601 diag::warn_maybe_falloff_nonvoid_lambda;
602 D.diag_AlwaysFallThrough_HasNoReturn =
603 diag::err_noreturn_lambda_has_return_expr;
604 D.diag_AlwaysFallThrough_ReturnsNonVoid =
605 diag::warn_falloff_nonvoid_lambda;
606 D.diag_NeverFallThroughOrReturn = 0;
607 D.funMode = Lambda;
608 return D;
609 }
610
611 bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid,
612 bool HasNoReturn) const {
613 if (funMode == Function) {
614 return (ReturnsVoid ||
615 D.isIgnored(diag::warn_maybe_falloff_nonvoid_function,
616 FuncLoc)) &&
617 (!HasNoReturn ||
618 D.isIgnored(diag::warn_noreturn_function_has_return_expr,
619 FuncLoc)) &&
620 (!ReturnsVoid ||
621 D.isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
622 }
623 if (funMode == Coroutine) {
624 return (ReturnsVoid ||
625 D.isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
626 D.isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
627 FuncLoc)) &&
628 (!HasNoReturn);
629 }
630 // For blocks / lambdas.
631 return ReturnsVoid && !HasNoReturn;
632 }
633};
634
635} // anonymous namespace
636
637/// CheckFallThroughForBody - Check that we don't fall off the end of a
638/// function that should return a value. Check that we don't fall off the end
639/// of a noreturn function. We assume that functions and blocks not marked
640/// noreturn will return.
641static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
642 QualType BlockType,
643 const CheckFallThroughDiagnostics &CD,
646
647 bool ReturnsVoid = false;
648 bool HasNoReturn = false;
649 bool IsCoroutine = FSI->isCoroutine();
650
651 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
652 if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
653 ReturnsVoid = CBody->getFallthroughHandler() != nullptr;
654 else
655 ReturnsVoid = FD->getReturnType()->isVoidType();
656 HasNoReturn = FD->isNoReturn();
657 }
658 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
659 ReturnsVoid = MD->getReturnType()->isVoidType();
660 HasNoReturn = MD->hasAttr<NoReturnAttr>();
661 }
662 else if (isa<BlockDecl>(D)) {
663 if (const FunctionType *FT =
664 BlockType->getPointeeType()->getAs<FunctionType>()) {
665 if (FT->getReturnType()->isVoidType())
666 ReturnsVoid = true;
667 if (FT->getNoReturnAttr())
668 HasNoReturn = true;
669 }
670 }
671
673
674 // Short circuit for compilation speed.
675 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
676 return;
677 SourceLocation LBrace = Body->getBeginLoc(), RBrace = Body->getEndLoc();
678 auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
679 if (IsCoroutine)
680 S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType();
681 else
682 S.Diag(Loc, DiagID);
683 };
684
685 // cpu_dispatch functions permit empty function bodies for ICC compatibility.
687 return;
688
689 // Either in a function body compound statement, or a function-try-block.
690 switch (CheckFallThrough(AC)) {
692 break;
693
694 case MaybeFallThrough:
695 if (HasNoReturn)
696 EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
697 else if (!ReturnsVoid)
698 EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
699 break;
701 if (HasNoReturn)
702 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
703 else if (!ReturnsVoid)
704 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
705 break;
707 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
708 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
709 S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
710 } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
711 S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
712 } else {
713 S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
714 }
715 }
716 break;
717 case NeverFallThrough:
718 break;
719 }
720}
721
722//===----------------------------------------------------------------------===//
723// -Wuninitialized
724//===----------------------------------------------------------------------===//
725
726namespace {
727/// ContainsReference - A visitor class to search for references to
728/// a particular declaration (the needle) within any evaluated component of an
729/// expression (recursively).
730class ContainsReference : public ConstEvaluatedExprVisitor<ContainsReference> {
731 bool FoundReference;
732 const DeclRefExpr *Needle;
733
734public:
736
737 ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
738 : Inherited(Context), FoundReference(false), Needle(Needle) {}
739
740 void VisitExpr(const Expr *E) {
741 // Stop evaluating if we already have a reference.
742 if (FoundReference)
743 return;
744
745 Inherited::VisitExpr(E);
746 }
747
748 void VisitDeclRefExpr(const DeclRefExpr *E) {
749 if (E == Needle)
750 FoundReference = true;
751 else
753 }
754
755 bool doesContainReference() const { return FoundReference; }
756};
757} // anonymous namespace
758
759static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
760 QualType VariableTy = VD->getType().getCanonicalType();
761 if (VariableTy->isBlockPointerType() &&
762 !VD->hasAttr<BlocksAttr>()) {
763 S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization)
764 << VD->getDeclName()
765 << FixItHint::CreateInsertion(VD->getLocation(), "__block ");
766 return true;
767 }
768
769 // Don't issue a fixit if there is already an initializer.
770 if (VD->getInit())
771 return false;
772
773 // Don't suggest a fixit inside macros.
774 if (VD->getEndLoc().isMacroID())
775 return false;
776
778
779 // Suggest possible initialization (if any).
780 std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
781 if (Init.empty())
782 return false;
783
784 S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()
785 << FixItHint::CreateInsertion(Loc, Init);
786 return true;
787}
788
789/// Create a fixit to remove an if-like statement, on the assumption that its
790/// condition is CondVal.
791static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then,
792 const Stmt *Else, bool CondVal,
793 FixItHint &Fixit1, FixItHint &Fixit2) {
794 if (CondVal) {
795 // If condition is always true, remove all but the 'then'.
798 if (Else) {
799 SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getEndLoc());
800 Fixit2 =
802 }
803 } else {
804 // If condition is always false, remove all but the 'else'.
805 if (Else)
807 If->getBeginLoc(), Else->getBeginLoc()));
808 else
810 }
811}
812
813/// DiagUninitUse -- Helper function to produce a diagnostic for an
814/// uninitialized use of a variable.
815static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
816 bool IsCapturedByBlock) {
817 bool Diagnosed = false;
818
819 switch (Use.getKind()) {
821 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_var)
822 << VD->getDeclName() << IsCapturedByBlock
823 << Use.getUser()->getSourceRange();
824 return;
825
828 S.Diag(VD->getLocation(), diag::warn_sometimes_uninit_var)
829 << VD->getDeclName() << IsCapturedByBlock
830 << (Use.getKind() == UninitUse::AfterDecl ? 4 : 5)
831 << const_cast<DeclContext*>(VD->getLexicalDeclContext())
832 << VD->getSourceRange();
833 S.Diag(Use.getUser()->getBeginLoc(), diag::note_uninit_var_use)
834 << IsCapturedByBlock << Use.getUser()->getSourceRange();
835 return;
836
837 case UninitUse::Maybe:
839 // Carry on to report sometimes-uninitialized branches, if possible,
840 // or a 'may be used uninitialized' diagnostic otherwise.
841 break;
842 }
843
844 // Diagnose each branch which leads to a sometimes-uninitialized use.
845 for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end();
846 I != E; ++I) {
847 assert(Use.getKind() == UninitUse::Sometimes);
848
849 const Expr *User = Use.getUser();
850 const Stmt *Term = I->Terminator;
851
852 // Information used when building the diagnostic.
853 unsigned DiagKind;
854 StringRef Str;
855 SourceRange Range;
856
857 // FixIts to suppress the diagnostic by removing the dead condition.
858 // For all binary terminators, branch 0 is taken if the condition is true,
859 // and branch 1 is taken if the condition is false.
860 int RemoveDiagKind = -1;
861 const char *FixitStr =
862 S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false")
863 : (I->Output ? "1" : "0");
864 FixItHint Fixit1, Fixit2;
865
866 switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) {
867 default:
868 // Don't know how to report this. Just fall back to 'may be used
869 // uninitialized'. FIXME: Can this happen?
870 continue;
871
872 // "condition is true / condition is false".
873 case Stmt::IfStmtClass: {
874 const IfStmt *IS = cast<IfStmt>(Term);
875 DiagKind = 0;
876 Str = "if";
877 Range = IS->getCond()->getSourceRange();
878 RemoveDiagKind = 0;
879 CreateIfFixit(S, IS, IS->getThen(), IS->getElse(),
880 I->Output, Fixit1, Fixit2);
881 break;
882 }
883 case Stmt::ConditionalOperatorClass: {
884 const ConditionalOperator *CO = cast<ConditionalOperator>(Term);
885 DiagKind = 0;
886 Str = "?:";
887 Range = CO->getCond()->getSourceRange();
888 RemoveDiagKind = 0;
889 CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(),
890 I->Output, Fixit1, Fixit2);
891 break;
892 }
893 case Stmt::BinaryOperatorClass: {
894 const BinaryOperator *BO = cast<BinaryOperator>(Term);
895 if (!BO->isLogicalOp())
896 continue;
897 DiagKind = 0;
898 Str = BO->getOpcodeStr();
899 Range = BO->getLHS()->getSourceRange();
900 RemoveDiagKind = 0;
901 if ((BO->getOpcode() == BO_LAnd && I->Output) ||
902 (BO->getOpcode() == BO_LOr && !I->Output))
903 // true && y -> y, false || y -> y.
906 else
907 // false && y -> false, true || y -> true.
908 Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr);
909 break;
910 }
911
912 // "loop is entered / loop is exited".
913 case Stmt::WhileStmtClass:
914 DiagKind = 1;
915 Str = "while";
916 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
917 RemoveDiagKind = 1;
918 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
919 break;
920 case Stmt::ForStmtClass:
921 DiagKind = 1;
922 Str = "for";
923 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
924 RemoveDiagKind = 1;
925 if (I->Output)
926 Fixit1 = FixItHint::CreateRemoval(Range);
927 else
928 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
929 break;
930 case Stmt::CXXForRangeStmtClass:
931 if (I->Output == 1) {
932 // The use occurs if a range-based for loop's body never executes.
933 // That may be impossible, and there's no syntactic fix for this,
934 // so treat it as a 'may be uninitialized' case.
935 continue;
936 }
937 DiagKind = 1;
938 Str = "for";
939 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
940 break;
941
942 // "condition is true / loop is exited".
943 case Stmt::DoStmtClass:
944 DiagKind = 2;
945 Str = "do";
946 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
947 RemoveDiagKind = 1;
948 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
949 break;
950
951 // "switch case is taken".
952 case Stmt::CaseStmtClass:
953 DiagKind = 3;
954 Str = "case";
955 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
956 break;
957 case Stmt::DefaultStmtClass:
958 DiagKind = 3;
959 Str = "default";
960 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
961 break;
962 }
963
964 S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var)
965 << VD->getDeclName() << IsCapturedByBlock << DiagKind
966 << Str << I->Output << Range;
967 S.Diag(User->getBeginLoc(), diag::note_uninit_var_use)
968 << IsCapturedByBlock << User->getSourceRange();
969 if (RemoveDiagKind != -1)
970 S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond)
971 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
972
973 Diagnosed = true;
974 }
975
976 if (!Diagnosed)
977 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_maybe_uninit_var)
978 << VD->getDeclName() << IsCapturedByBlock
979 << Use.getUser()->getSourceRange();
980}
981
982/// Diagnose uninitialized const reference usages.
984 const UninitUse &Use) {
985 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_reference)
986 << VD->getDeclName() << Use.getUser()->getSourceRange();
987 return true;
988}
989
990/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
991/// uninitialized variable. This manages the different forms of diagnostic
992/// emitted for particular types of uses. Returns true if the use was diagnosed
993/// as a warning. If a particular use is one we omit warnings for, returns
994/// false.
995static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
996 const UninitUse &Use,
997 bool alwaysReportSelfInit = false) {
998 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) {
999 // Inspect the initializer of the variable declaration which is
1000 // being referenced prior to its initialization. We emit
1001 // specialized diagnostics for self-initialization, and we
1002 // specifically avoid warning about self references which take the
1003 // form of:
1004 //
1005 // int x = x;
1006 //
1007 // This is used to indicate to GCC that 'x' is intentionally left
1008 // uninitialized. Proven code paths which access 'x' in
1009 // an uninitialized state after this will still warn.
1010 if (const Expr *Initializer = VD->getInit()) {
1011 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
1012 return false;
1013
1014 ContainsReference CR(S.Context, DRE);
1015 CR.Visit(Initializer);
1016 if (CR.doesContainReference()) {
1017 S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
1018 << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
1019 return true;
1020 }
1021 }
1022
1023 DiagUninitUse(S, VD, Use, false);
1024 } else {
1025 const BlockExpr *BE = cast<BlockExpr>(Use.getUser());
1026 if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>())
1027 S.Diag(BE->getBeginLoc(),
1028 diag::warn_uninit_byref_blockvar_captured_by_block)
1029 << VD->getDeclName()
1031 else
1032 DiagUninitUse(S, VD, Use, true);
1033 }
1034
1035 // Report where the variable was declared when the use wasn't within
1036 // the initializer of that declaration & we didn't already suggest
1037 // an initialization fixit.
1038 if (!SuggestInitializationFixit(S, VD))
1039 S.Diag(VD->getBeginLoc(), diag::note_var_declared_here)
1040 << VD->getDeclName();
1041
1042 return true;
1043}
1044
1045namespace {
1046 class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> {
1047 public:
1048 FallthroughMapper(Sema &S)
1049 : FoundSwitchStatements(false),
1050 S(S) {
1051 }
1052
1053 bool foundSwitchStatements() const { return FoundSwitchStatements; }
1054
1055 void markFallthroughVisited(const AttributedStmt *Stmt) {
1056 bool Found = FallthroughStmts.erase(Stmt);
1057 assert(Found);
1058 (void)Found;
1059 }
1060
1062
1063 const AttrStmts &getFallthroughStmts() const {
1064 return FallthroughStmts;
1065 }
1066
1067 void fillReachableBlocks(CFG *Cfg) {
1068 assert(ReachableBlocks.empty() && "ReachableBlocks already filled");
1069 std::deque<const CFGBlock *> BlockQueue;
1070
1071 ReachableBlocks.insert(&Cfg->getEntry());
1072 BlockQueue.push_back(&Cfg->getEntry());
1073 // Mark all case blocks reachable to avoid problems with switching on
1074 // constants, covered enums, etc.
1075 // These blocks can contain fall-through annotations, and we don't want to
1076 // issue a warn_fallthrough_attr_unreachable for them.
1077 for (const auto *B : *Cfg) {
1078 const Stmt *L = B->getLabel();
1079 if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1080 BlockQueue.push_back(B);
1081 }
1082
1083 while (!BlockQueue.empty()) {
1084 const CFGBlock *P = BlockQueue.front();
1085 BlockQueue.pop_front();
1086 for (const CFGBlock *B : P->succs()) {
1087 if (B && ReachableBlocks.insert(B).second)
1088 BlockQueue.push_back(B);
1089 }
1090 }
1091 }
1092
1093 bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt,
1094 bool IsTemplateInstantiation) {
1095 assert(!ReachableBlocks.empty() && "ReachableBlocks empty");
1096
1097 int UnannotatedCnt = 0;
1098 AnnotatedCnt = 0;
1099
1100 std::deque<const CFGBlock*> BlockQueue(B.pred_begin(), B.pred_end());
1101 while (!BlockQueue.empty()) {
1102 const CFGBlock *P = BlockQueue.front();
1103 BlockQueue.pop_front();
1104 if (!P) continue;
1105
1106 const Stmt *Term = P->getTerminatorStmt();
1107 if (Term && isa<SwitchStmt>(Term))
1108 continue; // Switch statement, good.
1109
1110 const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel());
1111 if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end())
1112 continue; // Previous case label has no statements, good.
1113
1114 const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel());
1115 if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end())
1116 continue; // Case label is preceded with a normal label, good.
1117
1118 if (!ReachableBlocks.count(P)) {
1119 for (const CFGElement &Elem : llvm::reverse(*P)) {
1120 if (std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>()) {
1121 if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1122 // Don't issue a warning for an unreachable fallthrough
1123 // attribute in template instantiations as it may not be
1124 // unreachable in all instantiations of the template.
1125 if (!IsTemplateInstantiation)
1126 S.Diag(AS->getBeginLoc(),
1127 diag::warn_unreachable_fallthrough_attr);
1128 markFallthroughVisited(AS);
1129 ++AnnotatedCnt;
1130 break;
1131 }
1132 // Don't care about other unreachable statements.
1133 }
1134 }
1135 // If there are no unreachable statements, this may be a special
1136 // case in CFG:
1137 // case X: {
1138 // A a; // A has a destructor.
1139 // break;
1140 // }
1141 // // <<<< This place is represented by a 'hanging' CFG block.
1142 // case Y:
1143 continue;
1144 }
1145
1146 const Stmt *LastStmt = getLastStmt(*P);
1147 if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) {
1148 markFallthroughVisited(AS);
1149 ++AnnotatedCnt;
1150 continue; // Fallthrough annotation, good.
1151 }
1152
1153 if (!LastStmt) { // This block contains no executable statements.
1154 // Traverse its predecessors.
1155 std::copy(P->pred_begin(), P->pred_end(),
1156 std::back_inserter(BlockQueue));
1157 continue;
1158 }
1159
1160 ++UnannotatedCnt;
1161 }
1162 return !!UnannotatedCnt;
1163 }
1164
1165 // RecursiveASTVisitor setup.
1166 bool shouldWalkTypesOfTypeLocs() const { return false; }
1167
1168 bool VisitAttributedStmt(AttributedStmt *S) {
1169 if (asFallThroughAttr(S))
1170 FallthroughStmts.insert(S);
1171 return true;
1172 }
1173
1174 bool VisitSwitchStmt(SwitchStmt *S) {
1175 FoundSwitchStatements = true;
1176 return true;
1177 }
1178
1179 // We don't want to traverse local type declarations. We analyze their
1180 // methods separately.
1181 bool TraverseDecl(Decl *D) { return true; }
1182
1183 // We analyze lambda bodies separately. Skip them here.
1184 bool TraverseLambdaExpr(LambdaExpr *LE) {
1185 // Traverse the captures, but not the body.
1186 for (const auto C : zip(LE->captures(), LE->capture_inits()))
1187 TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
1188 return true;
1189 }
1190
1191 private:
1192
1193 static const AttributedStmt *asFallThroughAttr(const Stmt *S) {
1194 if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1195 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1196 return AS;
1197 }
1198 return nullptr;
1199 }
1200
1201 static const Stmt *getLastStmt(const CFGBlock &B) {
1202 if (const Stmt *Term = B.getTerminatorStmt())
1203 return Term;
1204 for (const CFGElement &Elem : llvm::reverse(B))
1205 if (std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>())
1206 return CS->getStmt();
1207 // Workaround to detect a statement thrown out by CFGBuilder:
1208 // case X: {} case Y:
1209 // case X: ; case Y:
1210 if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel()))
1211 if (!isa<SwitchCase>(SW->getSubStmt()))
1212 return SW->getSubStmt();
1213
1214 return nullptr;
1215 }
1216
1217 bool FoundSwitchStatements;
1218 AttrStmts FallthroughStmts;
1219 Sema &S;
1221 };
1222} // anonymous namespace
1223
1225 SourceLocation Loc) {
1226 TokenValue FallthroughTokens[] = {
1227 tok::l_square, tok::l_square,
1228 PP.getIdentifierInfo("fallthrough"),
1229 tok::r_square, tok::r_square
1230 };
1231
1232 TokenValue ClangFallthroughTokens[] = {
1233 tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"),
1234 tok::coloncolon, PP.getIdentifierInfo("fallthrough"),
1235 tok::r_square, tok::r_square
1236 };
1237
1238 bool PreferClangAttr = !PP.getLangOpts().CPlusPlus17 && !PP.getLangOpts().C2x;
1239
1240 StringRef MacroName;
1241 if (PreferClangAttr)
1242 MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);
1243 if (MacroName.empty())
1244 MacroName = PP.getLastMacroWithSpelling(Loc, FallthroughTokens);
1245 if (MacroName.empty() && !PreferClangAttr)
1246 MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);
1247 if (MacroName.empty()) {
1248 if (!PreferClangAttr)
1249 MacroName = "[[fallthrough]]";
1250 else if (PP.getLangOpts().CPlusPlus)
1251 MacroName = "[[clang::fallthrough]]";
1252 else
1253 MacroName = "__attribute__((fallthrough))";
1254 }
1255 return MacroName;
1256}
1257
1259 bool PerFunction) {
1260 FallthroughMapper FM(S);
1261 FM.TraverseStmt(AC.getBody());
1262
1263 if (!FM.foundSwitchStatements())
1264 return;
1265
1266 if (PerFunction && FM.getFallthroughStmts().empty())
1267 return;
1268
1269 CFG *Cfg = AC.getCFG();
1270
1271 if (!Cfg)
1272 return;
1273
1274 FM.fillReachableBlocks(Cfg);
1275
1276 for (const CFGBlock *B : llvm::reverse(*Cfg)) {
1277 const Stmt *Label = B->getLabel();
1278
1279 if (!isa_and_nonnull<SwitchCase>(Label))
1280 continue;
1281
1282 int AnnotatedCnt;
1283
1284 bool IsTemplateInstantiation = false;
1285 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(AC.getDecl()))
1286 IsTemplateInstantiation = Function->isTemplateInstantiation();
1287 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1288 IsTemplateInstantiation))
1289 continue;
1290
1291 S.Diag(Label->getBeginLoc(),
1292 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1293 : diag::warn_unannotated_fallthrough);
1294
1295 if (!AnnotatedCnt) {
1296 SourceLocation L = Label->getBeginLoc();
1297 if (L.isMacroID())
1298 continue;
1299
1300 const Stmt *Term = B->getTerminatorStmt();
1301 // Skip empty cases.
1302 while (B->empty() && !Term && B->succ_size() == 1) {
1303 B = *B->succ_begin();
1304 Term = B->getTerminatorStmt();
1305 }
1306 if (!(B->empty() && Term && isa<BreakStmt>(Term))) {
1307 Preprocessor &PP = S.getPreprocessor();
1308 StringRef AnnotationSpelling = getFallthroughAttrSpelling(PP, L);
1309 SmallString<64> TextToInsert(AnnotationSpelling);
1310 TextToInsert += "; ";
1311 S.Diag(L, diag::note_insert_fallthrough_fixit)
1312 << AnnotationSpelling
1313 << FixItHint::CreateInsertion(L, TextToInsert);
1314 }
1315 S.Diag(L, diag::note_insert_break_fixit)
1316 << FixItHint::CreateInsertion(L, "break; ");
1317 }
1318 }
1319
1320 for (const auto *F : FM.getFallthroughStmts())
1321 S.Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);
1322}
1323
1324static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
1325 const Stmt *S) {
1326 assert(S);
1327
1328 do {
1329 switch (S->getStmtClass()) {
1330 case Stmt::ForStmtClass:
1331 case Stmt::WhileStmtClass:
1332 case Stmt::CXXForRangeStmtClass:
1333 case Stmt::ObjCForCollectionStmtClass:
1334 return true;
1335 case Stmt::DoStmtClass: {
1336 Expr::EvalResult Result;
1337 if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))
1338 return true;
1339 return Result.Val.getInt().getBoolValue();
1340 }
1341 default:
1342 break;
1343 }
1344 } while ((S = PM.getParent(S)));
1345
1346 return false;
1347}
1348
1350 const sema::FunctionScopeInfo *CurFn,
1351 const Decl *D,
1352 const ParentMap &PM) {
1353 typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy;
1354 typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap;
1355 typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector;
1356 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1357 StmtUsesPair;
1358
1359 ASTContext &Ctx = S.getASTContext();
1360
1361 const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses();
1362
1363 // Extract all weak objects that are referenced more than once.
1365 for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
1366 I != E; ++I) {
1367 const WeakUseVector &Uses = I->second;
1368
1369 // Find the first read of the weak object.
1370 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1371 for ( ; UI != UE; ++UI) {
1372 if (UI->isUnsafe())
1373 break;
1374 }
1375
1376 // If there were only writes to this object, don't warn.
1377 if (UI == UE)
1378 continue;
1379
1380 // If there was only one read, followed by any number of writes, and the
1381 // read is not within a loop, don't warn. Additionally, don't warn in a
1382 // loop if the base object is a local variable -- local variables are often
1383 // changed in loops.
1384 if (UI == Uses.begin()) {
1385 WeakUseVector::const_iterator UI2 = UI;
1386 for (++UI2; UI2 != UE; ++UI2)
1387 if (UI2->isUnsafe())
1388 break;
1389
1390 if (UI2 == UE) {
1391 if (!isInLoop(Ctx, PM, UI->getUseExpr()))
1392 continue;
1393
1394 const WeakObjectProfileTy &Profile = I->first;
1395 if (!Profile.isExactProfile())
1396 continue;
1397
1398 const NamedDecl *Base = Profile.getBase();
1399 if (!Base)
1400 Base = Profile.getProperty();
1401 assert(Base && "A profile always has a base or property.");
1402
1403 if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1404 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1405 continue;
1406 }
1407 }
1408
1409 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
1410 }
1411
1412 if (UsesByStmt.empty())
1413 return;
1414
1415 // Sort by first use so that we emit the warnings in a deterministic order.
1417 llvm::sort(UsesByStmt,
1418 [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
1419 return SM.isBeforeInTranslationUnit(LHS.first->getBeginLoc(),
1420 RHS.first->getBeginLoc());
1421 });
1422
1423 // Classify the current code body for better warning text.
1424 // This enum should stay in sync with the cases in
1425 // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
1426 // FIXME: Should we use a common classification enum and the same set of
1427 // possibilities all throughout Sema?
1428 enum {
1429 Function,
1430 Method,
1431 Block,
1432 Lambda
1433 } FunctionKind;
1434
1435 if (isa<sema::BlockScopeInfo>(CurFn))
1436 FunctionKind = Block;
1437 else if (isa<sema::LambdaScopeInfo>(CurFn))
1438 FunctionKind = Lambda;
1439 else if (isa<ObjCMethodDecl>(D))
1440 FunctionKind = Method;
1441 else
1442 FunctionKind = Function;
1443
1444 // Iterate through the sorted problems and emit warnings for each.
1445 for (const auto &P : UsesByStmt) {
1446 const Stmt *FirstRead = P.first;
1447 const WeakObjectProfileTy &Key = P.second->first;
1448 const WeakUseVector &Uses = P.second->second;
1449
1450 // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy
1451 // may not contain enough information to determine that these are different
1452 // properties. We can only be 100% sure of a repeated use in certain cases,
1453 // and we adjust the diagnostic kind accordingly so that the less certain
1454 // case can be turned off if it is too noisy.
1455 unsigned DiagKind;
1456 if (Key.isExactProfile())
1457 DiagKind = diag::warn_arc_repeated_use_of_weak;
1458 else
1459 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1460
1461 // Classify the weak object being accessed for better warning text.
1462 // This enum should stay in sync with the cases in
1463 // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
1464 enum {
1465 Variable,
1466 Property,
1467 ImplicitProperty,
1468 Ivar
1469 } ObjectKind;
1470
1471 const NamedDecl *KeyProp = Key.getProperty();
1472 if (isa<VarDecl>(KeyProp))
1473 ObjectKind = Variable;
1474 else if (isa<ObjCPropertyDecl>(KeyProp))
1475 ObjectKind = Property;
1476 else if (isa<ObjCMethodDecl>(KeyProp))
1477 ObjectKind = ImplicitProperty;
1478 else if (isa<ObjCIvarDecl>(KeyProp))
1479 ObjectKind = Ivar;
1480 else
1481 llvm_unreachable("Unexpected weak object kind!");
1482
1483 // Do not warn about IBOutlet weak property receivers being set to null
1484 // since they are typically only used from the main thread.
1485 if (const ObjCPropertyDecl *Prop = dyn_cast<ObjCPropertyDecl>(KeyProp))
1486 if (Prop->hasAttr<IBOutletAttr>())
1487 continue;
1488
1489 // Show the first time the object was read.
1490 S.Diag(FirstRead->getBeginLoc(), DiagKind)
1491 << int(ObjectKind) << KeyProp << int(FunctionKind)
1492 << FirstRead->getSourceRange();
1493
1494 // Print all the other accesses as notes.
1495 for (const auto &Use : Uses) {
1496 if (Use.getUseExpr() == FirstRead)
1497 continue;
1498 S.Diag(Use.getUseExpr()->getBeginLoc(),
1499 diag::note_arc_weak_also_accessed_here)
1500 << Use.getUseExpr()->getSourceRange();
1501 }
1502 }
1503}
1504
1505namespace clang {
1506namespace {
1508typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
1509typedef std::list<DelayedDiag> DiagList;
1510
1511struct SortDiagBySourceLocation {
1513 SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}
1514
1515 bool operator()(const DelayedDiag &left, const DelayedDiag &right) {
1516 // Although this call will be slow, this is only called when outputting
1517 // multiple warnings.
1518 return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
1519 }
1520};
1521} // anonymous namespace
1522} // namespace clang
1523
1524namespace {
1525class UninitValsDiagReporter : public UninitVariablesHandler {
1526 Sema &S;
1527 typedef SmallVector<UninitUse, 2> UsesVec;
1528 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1529 // Prefer using MapVector to DenseMap, so that iteration order will be
1530 // the same as insertion order. This is needed to obtain a deterministic
1531 // order of diagnostics when calling flushDiagnostics().
1532 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1533 UsesMap uses;
1534 UsesMap constRefUses;
1535
1536public:
1537 UninitValsDiagReporter(Sema &S) : S(S) {}
1538 ~UninitValsDiagReporter() override { flushDiagnostics(); }
1539
1540 MappedType &getUses(UsesMap &um, const VarDecl *vd) {
1541 MappedType &V = um[vd];
1542 if (!V.getPointer())
1543 V.setPointer(new UsesVec());
1544 return V;
1545 }
1546
1547 void handleUseOfUninitVariable(const VarDecl *vd,
1548 const UninitUse &use) override {
1549 getUses(uses, vd).getPointer()->push_back(use);
1550 }
1551
1553 const UninitUse &use) override {
1554 getUses(constRefUses, vd).getPointer()->push_back(use);
1555 }
1556
1557 void handleSelfInit(const VarDecl *vd) override {
1558 getUses(uses, vd).setInt(true);
1559 getUses(constRefUses, vd).setInt(true);
1560 }
1561
1562 void flushDiagnostics() {
1563 for (const auto &P : uses) {
1564 const VarDecl *vd = P.first;
1565 const MappedType &V = P.second;
1566
1567 UsesVec *vec = V.getPointer();
1568 bool hasSelfInit = V.getInt();
1569
1570 // Specially handle the case where we have uses of an uninitialized
1571 // variable, but the root cause is an idiomatic self-init. We want
1572 // to report the diagnostic at the self-init since that is the root cause.
1573 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1576 /* isAlwaysUninit */ true),
1577 /* alwaysReportSelfInit */ true);
1578 else {
1579 // Sort the uses by their SourceLocations. While not strictly
1580 // guaranteed to produce them in line/column order, this will provide
1581 // a stable ordering.
1582 llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {
1583 // Prefer a more confident report over a less confident one.
1584 if (a.getKind() != b.getKind())
1585 return a.getKind() > b.getKind();
1586 return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();
1587 });
1588
1589 for (const auto &U : *vec) {
1590 // If we have self-init, downgrade all uses to 'may be uninitialized'.
1591 UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
1592
1593 if (DiagnoseUninitializedUse(S, vd, Use))
1594 // Skip further diagnostics for this variable. We try to warn only
1595 // on the first point at which a variable is used uninitialized.
1596 break;
1597 }
1598 }
1599
1600 // Release the uses vector.
1601 delete vec;
1602 }
1603
1604 uses.clear();
1605
1606 // Flush all const reference uses diags.
1607 for (const auto &P : constRefUses) {
1608 const VarDecl *vd = P.first;
1609 const MappedType &V = P.second;
1610
1611 UsesVec *vec = V.getPointer();
1612 bool hasSelfInit = V.getInt();
1613
1614 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1617 /* isAlwaysUninit */ true),
1618 /* alwaysReportSelfInit */ true);
1619 else {
1620 for (const auto &U : *vec) {
1622 break;
1623 }
1624 }
1625
1626 // Release the uses vector.
1627 delete vec;
1628 }
1629
1630 constRefUses.clear();
1631 }
1632
1633private:
1634 static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
1635 return llvm::any_of(*vec, [](const UninitUse &U) {
1636 return U.getKind() == UninitUse::Always ||
1637 U.getKind() == UninitUse::AfterCall ||
1638 U.getKind() == UninitUse::AfterDecl;
1639 });
1640 }
1641};
1642
1643/// Inter-procedural data for the called-once checker.
1644class CalledOnceInterProceduralData {
1645public:
1646 // Add the delayed warning for the given block.
1647 void addDelayedWarning(const BlockDecl *Block,
1649 DelayedBlockWarnings[Block].emplace_back(std::move(Warning));
1650 }
1651 // Report all of the warnings we've gathered for the given block.
1652 void flushWarnings(const BlockDecl *Block, Sema &S) {
1653 for (const PartialDiagnosticAt &Delayed : DelayedBlockWarnings[Block])
1654 S.Diag(Delayed.first, Delayed.second);
1655
1656 discardWarnings(Block);
1657 }
1658 // Discard all of the warnings we've gathered for the given block.
1659 void discardWarnings(const BlockDecl *Block) {
1660 DelayedBlockWarnings.erase(Block);
1661 }
1662
1663private:
1664 using DelayedDiagnostics = SmallVector<PartialDiagnosticAt, 2>;
1665 llvm::DenseMap<const BlockDecl *, DelayedDiagnostics> DelayedBlockWarnings;
1666};
1667
1668class CalledOnceCheckReporter : public CalledOnceCheckHandler {
1669public:
1670 CalledOnceCheckReporter(Sema &S, CalledOnceInterProceduralData &Data)
1671 : S(S), Data(Data) {}
1672 void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call,
1673 const Expr *PrevCall, bool IsCompletionHandler,
1674 bool Poised) override {
1675 auto DiagToReport = IsCompletionHandler
1676 ? diag::warn_completion_handler_called_twice
1677 : diag::warn_called_once_gets_called_twice;
1678 S.Diag(Call->getBeginLoc(), DiagToReport) << Parameter;
1679 S.Diag(PrevCall->getBeginLoc(), diag::note_called_once_gets_called_twice)
1680 << Poised;
1681 }
1682
1684 bool IsCompletionHandler) override {
1685 auto DiagToReport = IsCompletionHandler
1686 ? diag::warn_completion_handler_never_called
1687 : diag::warn_called_once_never_called;
1688 S.Diag(Parameter->getBeginLoc(), DiagToReport)
1689 << Parameter << /* Captured */ false;
1690 }
1691
1692 void handleNeverCalled(const ParmVarDecl *Parameter, const Decl *Function,
1693 const Stmt *Where, NeverCalledReason Reason,
1694 bool IsCalledDirectly,
1695 bool IsCompletionHandler) override {
1696 auto DiagToReport = IsCompletionHandler
1697 ? diag::warn_completion_handler_never_called_when
1698 : diag::warn_called_once_never_called_when;
1699 PartialDiagnosticAt Warning(Where->getBeginLoc(), S.PDiag(DiagToReport)
1700 << Parameter
1701 << IsCalledDirectly
1702 << (unsigned)Reason);
1703
1704 if (const auto *Block = dyn_cast<BlockDecl>(Function)) {
1705 // We shouldn't report these warnings on blocks immediately
1706 Data.addDelayedWarning(Block, std::move(Warning));
1707 } else {
1708 S.Diag(Warning.first, Warning.second);
1709 }
1710 }
1711
1713 const Decl *Where,
1714 bool IsCompletionHandler) override {
1715 auto DiagToReport = IsCompletionHandler
1716 ? diag::warn_completion_handler_never_called
1717 : diag::warn_called_once_never_called;
1718 S.Diag(Where->getBeginLoc(), DiagToReport)
1719 << Parameter << /* Captured */ true;
1720 }
1721
1722 void
1724 Data.flushWarnings(Block, S);
1725 }
1726
1727 void handleBlockWithNoGuarantees(const BlockDecl *Block) override {
1728 Data.discardWarnings(Block);
1729 }
1730
1731private:
1732 Sema &S;
1733 CalledOnceInterProceduralData &Data;
1734};
1735
1736constexpr unsigned CalledOnceWarnings[] = {
1737 diag::warn_called_once_never_called,
1738 diag::warn_called_once_never_called_when,
1739 diag::warn_called_once_gets_called_twice};
1740
1741constexpr unsigned CompletionHandlerWarnings[]{
1742 diag::warn_completion_handler_never_called,
1743 diag::warn_completion_handler_never_called_when,
1744 diag::warn_completion_handler_called_twice};
1745
1746bool shouldAnalyzeCalledOnceImpl(llvm::ArrayRef<unsigned> DiagIDs,
1747 const DiagnosticsEngine &Diags,
1748 SourceLocation At) {
1749 return llvm::any_of(DiagIDs, [&Diags, At](unsigned DiagID) {
1750 return !Diags.isIgnored(DiagID, At);
1751 });
1752}
1753
1754bool shouldAnalyzeCalledOnceConventions(const DiagnosticsEngine &Diags,
1755 SourceLocation At) {
1756 return shouldAnalyzeCalledOnceImpl(CompletionHandlerWarnings, Diags, At);
1757}
1758
1759bool shouldAnalyzeCalledOnceParameters(const DiagnosticsEngine &Diags,
1760 SourceLocation At) {
1761 return shouldAnalyzeCalledOnceImpl(CalledOnceWarnings, Diags, At) ||
1762 shouldAnalyzeCalledOnceConventions(Diags, At);
1763}
1764} // anonymous namespace
1765
1766//===----------------------------------------------------------------------===//
1767// -Wthread-safety
1768//===----------------------------------------------------------------------===//
1769namespace clang {
1770namespace threadSafety {
1771namespace {
1772class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
1773 Sema &S;
1774 DiagList Warnings;
1775 SourceLocation FunLocation, FunEndLocation;
1776
1777 const FunctionDecl *CurrentFunction;
1778 bool Verbose;
1779
1780 OptionalNotes getNotes() const {
1781 if (Verbose && CurrentFunction) {
1782 PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
1783 S.PDiag(diag::note_thread_warning_in_fun)
1784 << CurrentFunction);
1785 return OptionalNotes(1, FNote);
1786 }
1787 return OptionalNotes();
1788 }
1789
1790 OptionalNotes getNotes(const PartialDiagnosticAt &Note) const {
1791 OptionalNotes ONS(1, Note);
1792 if (Verbose && CurrentFunction) {
1793 PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
1794 S.PDiag(diag::note_thread_warning_in_fun)
1795 << CurrentFunction);
1796 ONS.push_back(std::move(FNote));
1797 }
1798 return ONS;
1799 }
1800
1801 OptionalNotes getNotes(const PartialDiagnosticAt &Note1,
1802 const PartialDiagnosticAt &Note2) const {
1803 OptionalNotes ONS;
1804 ONS.push_back(Note1);
1805 ONS.push_back(Note2);
1806 if (Verbose && CurrentFunction) {
1807 PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
1808 S.PDiag(diag::note_thread_warning_in_fun)
1809 << CurrentFunction);
1810 ONS.push_back(std::move(FNote));
1811 }
1812 return ONS;
1813 }
1814
1815 OptionalNotes makeLockedHereNote(SourceLocation LocLocked, StringRef Kind) {
1816 return LocLocked.isValid()
1817 ? getNotes(PartialDiagnosticAt(
1818 LocLocked, S.PDiag(diag::note_locked_here) << Kind))
1819 : getNotes();
1820 }
1821
1822 OptionalNotes makeUnlockedHereNote(SourceLocation LocUnlocked,
1823 StringRef Kind) {
1824 return LocUnlocked.isValid()
1825 ? getNotes(PartialDiagnosticAt(
1826 LocUnlocked, S.PDiag(diag::note_unlocked_here) << Kind))
1827 : getNotes();
1828 }
1829
1830 public:
1831 ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL)
1832 : S(S), FunLocation(FL), FunEndLocation(FEL),
1833 CurrentFunction(nullptr), Verbose(false) {}
1834
1835 void setVerbose(bool b) { Verbose = b; }
1836
1837 /// Emit all buffered diagnostics in order of sourcelocation.
1838 /// We need to output diagnostics produced while iterating through
1839 /// the lockset in deterministic order, so this function orders diagnostics
1840 /// and outputs them.
1841 void emitDiagnostics() {
1842 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
1843 for (const auto &Diag : Warnings) {
1844 S.Diag(Diag.first.first, Diag.first.second);
1845 for (const auto &Note : Diag.second)
1846 S.Diag(Note.first, Note.second);
1847 }
1848 }
1849
1850 void handleInvalidLockExp(SourceLocation Loc) override {
1851 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock)
1852 << Loc);
1853 Warnings.emplace_back(std::move(Warning), getNotes());
1854 }
1855
1856 void handleUnmatchedUnlock(StringRef Kind, Name LockName, SourceLocation Loc,
1857 SourceLocation LocPreviousUnlock) override {
1858 if (Loc.isInvalid())
1859 Loc = FunLocation;
1860 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_but_no_lock)
1861 << Kind << LockName);
1862 Warnings.emplace_back(std::move(Warning),
1863 makeUnlockedHereNote(LocPreviousUnlock, Kind));
1864 }
1865
1866 void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
1867 LockKind Expected, LockKind Received,
1868 SourceLocation LocLocked,
1869 SourceLocation LocUnlock) override {
1870 if (LocUnlock.isInvalid())
1871 LocUnlock = FunLocation;
1873 LocUnlock, S.PDiag(diag::warn_unlock_kind_mismatch)
1874 << Kind << LockName << Received << Expected);
1875 Warnings.emplace_back(std::move(Warning),
1876 makeLockedHereNote(LocLocked, Kind));
1877 }
1878
1879 void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation LocLocked,
1880 SourceLocation LocDoubleLock) override {
1881 if (LocDoubleLock.isInvalid())
1882 LocDoubleLock = FunLocation;
1883 PartialDiagnosticAt Warning(LocDoubleLock, S.PDiag(diag::warn_double_lock)
1884 << Kind << LockName);
1885 Warnings.emplace_back(std::move(Warning),
1886 makeLockedHereNote(LocLocked, Kind));
1887 }
1888
1889 void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
1890 SourceLocation LocLocked,
1891 SourceLocation LocEndOfScope,
1892 LockErrorKind LEK) override {
1893 unsigned DiagID = 0;
1894 switch (LEK) {
1896 DiagID = diag::warn_lock_some_predecessors;
1897 break;
1899 DiagID = diag::warn_expecting_lock_held_on_loop;
1900 break;
1902 DiagID = diag::warn_no_unlock;
1903 break;
1905 DiagID = diag::warn_expecting_locked;
1906 break;
1907 }
1908 if (LocEndOfScope.isInvalid())
1909 LocEndOfScope = FunEndLocation;
1910
1911 PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << Kind
1912 << LockName);
1913 Warnings.emplace_back(std::move(Warning),
1914 makeLockedHereNote(LocLocked, Kind));
1915 }
1916
1917 void handleExclusiveAndShared(StringRef Kind, Name LockName,
1918 SourceLocation Loc1,
1919 SourceLocation Loc2) override {
1921 S.PDiag(diag::warn_lock_exclusive_and_shared)
1922 << Kind << LockName);
1923 PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared)
1924 << Kind << LockName);
1925 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1926 }
1927
1928 void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
1929 AccessKind AK, SourceLocation Loc) override {
1930 assert((POK == POK_VarAccess || POK == POK_VarDereference) &&
1931 "Only works for variables");
1932 unsigned DiagID = POK == POK_VarAccess?
1933 diag::warn_variable_requires_any_lock:
1934 diag::warn_var_deref_requires_any_lock;
1935 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
1936 << D << getLockKindFromAccessKind(AK));
1937 Warnings.emplace_back(std::move(Warning), getNotes());
1938 }
1939
1940 void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
1941 ProtectedOperationKind POK, Name LockName,
1942 LockKind LK, SourceLocation Loc,
1943 Name *PossibleMatch) override {
1944 unsigned DiagID = 0;
1945 if (PossibleMatch) {
1946 switch (POK) {
1947 case POK_VarAccess:
1948 DiagID = diag::warn_variable_requires_lock_precise;
1949 break;
1950 case POK_VarDereference:
1951 DiagID = diag::warn_var_deref_requires_lock_precise;
1952 break;
1953 case POK_FunctionCall:
1954 DiagID = diag::warn_fun_requires_lock_precise;
1955 break;
1956 case POK_PassByRef:
1957 DiagID = diag::warn_guarded_pass_by_reference;
1958 break;
1959 case POK_PtPassByRef:
1960 DiagID = diag::warn_pt_guarded_pass_by_reference;
1961 break;
1962 }
1963 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
1964 << D
1965 << LockName << LK);
1966 PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
1967 << *PossibleMatch);
1968 if (Verbose && POK == POK_VarAccess) {
1970 S.PDiag(diag::note_guarded_by_declared_here)
1971 << D->getDeclName());
1972 Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote));
1973 } else
1974 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1975 } else {
1976 switch (POK) {
1977 case POK_VarAccess:
1978 DiagID = diag::warn_variable_requires_lock;
1979 break;
1980 case POK_VarDereference:
1981 DiagID = diag::warn_var_deref_requires_lock;
1982 break;
1983 case POK_FunctionCall:
1984 DiagID = diag::warn_fun_requires_lock;
1985 break;
1986 case POK_PassByRef:
1987 DiagID = diag::warn_guarded_pass_by_reference;
1988 break;
1989 case POK_PtPassByRef:
1990 DiagID = diag::warn_pt_guarded_pass_by_reference;
1991 break;
1992 }
1993 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
1994 << D
1995 << LockName << LK);
1996 if (Verbose && POK == POK_VarAccess) {
1998 S.PDiag(diag::note_guarded_by_declared_here));
1999 Warnings.emplace_back(std::move(Warning), getNotes(Note));
2000 } else
2001 Warnings.emplace_back(std::move(Warning), getNotes());
2002 }
2003 }
2004
2005 void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
2006 SourceLocation Loc) override {
2008 S.PDiag(diag::warn_acquire_requires_negative_cap)
2009 << Kind << LockName << Neg);
2010 Warnings.emplace_back(std::move(Warning), getNotes());
2011 }
2012
2013 void handleNegativeNotHeld(const NamedDecl *D, Name LockName,
2014 SourceLocation Loc) override {
2016 Loc, S.PDiag(diag::warn_fun_requires_negative_cap) << D << LockName);
2017 Warnings.emplace_back(std::move(Warning), getNotes());
2018 }
2019
2020 void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
2021 SourceLocation Loc) override {
2022 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
2023 << Kind << FunName << LockName);
2024 Warnings.emplace_back(std::move(Warning), getNotes());
2025 }
2026
2027 void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
2028 SourceLocation Loc) override {
2030 S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
2031 Warnings.emplace_back(std::move(Warning), getNotes());
2032 }
2033
2034 void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override {
2036 S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
2037 Warnings.emplace_back(std::move(Warning), getNotes());
2038 }
2039
2040 void enterFunction(const FunctionDecl* FD) override {
2041 CurrentFunction = FD;
2042 }
2043
2044 void leaveFunction(const FunctionDecl* FD) override {
2045 CurrentFunction = nullptr;
2046 }
2047};
2048} // anonymous namespace
2049} // namespace threadSafety
2050} // namespace clang
2051
2052//===----------------------------------------------------------------------===//
2053// -Wconsumed
2054//===----------------------------------------------------------------------===//
2055
2056namespace clang {
2057namespace consumed {
2058namespace {
2059class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase {
2060
2061 Sema &S;
2062 DiagList Warnings;
2063
2064public:
2065
2066 ConsumedWarningsHandler(Sema &S) : S(S) {}
2067
2068 void emitDiagnostics() override {
2069 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
2070 for (const auto &Diag : Warnings) {
2071 S.Diag(Diag.first.first, Diag.first.second);
2072 for (const auto &Note : Diag.second)
2073 S.Diag(Note.first, Note.second);
2074 }
2075 }
2076
2077 void warnLoopStateMismatch(SourceLocation Loc,
2078 StringRef VariableName) override {
2079 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) <<
2080 VariableName);
2081
2082 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2083 }
2084
2085 void warnParamReturnTypestateMismatch(SourceLocation Loc,
2086 StringRef VariableName,
2087 StringRef ExpectedState,
2088 StringRef ObservedState) override {
2089
2091 diag::warn_param_return_typestate_mismatch) << VariableName <<
2092 ExpectedState << ObservedState);
2093
2094 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2095 }
2096
2097 void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
2098 StringRef ObservedState) override {
2099
2101 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
2102
2103 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2104 }
2105
2106 void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
2107 StringRef TypeName) override {
2109 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
2110
2111 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2112 }
2113
2114 void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
2115 StringRef ObservedState) override {
2116
2118 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
2119
2120 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2121 }
2122
2123 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
2124 SourceLocation Loc) override {
2125
2127 diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
2128
2129 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2130 }
2131
2132 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
2133 StringRef State, SourceLocation Loc) override {
2134
2135 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
2136 MethodName << VariableName << State);
2137
2138 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2139 }
2140};
2141} // anonymous namespace
2142} // namespace consumed
2143} // namespace clang
2144
2145//===----------------------------------------------------------------------===//
2146// Unsafe buffer usage analysis.
2147//===----------------------------------------------------------------------===//
2148
2149namespace {
2150class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler {
2151 Sema &S;
2152
2153public:
2154 UnsafeBufferUsageReporter(Sema &S) : S(S) {}
2155
2156 void handleUnsafeOperation(const Stmt *Operation,
2157 bool IsRelatedToDecl) override {
2158 SourceLocation Loc;
2160 unsigned MsgParam = 0;
2161 if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Operation)) {
2162 Loc = ASE->getBase()->getExprLoc();
2163 Range = ASE->getBase()->getSourceRange();
2164 MsgParam = 2;
2165 } else if (const auto *BO = dyn_cast<BinaryOperator>(Operation)) {
2166 BinaryOperator::Opcode Op = BO->getOpcode();
2167 if (Op == BO_Add || Op == BO_AddAssign || Op == BO_Sub ||
2168 Op == BO_SubAssign) {
2169 if (BO->getRHS()->getType()->isIntegerType()) {
2170 Loc = BO->getLHS()->getExprLoc();
2171 Range = BO->getLHS()->getSourceRange();
2172 } else {
2173 Loc = BO->getRHS()->getExprLoc();
2174 Range = BO->getRHS()->getSourceRange();
2175 }
2176 MsgParam = 1;
2177 }
2178 } else if (const auto *UO = dyn_cast<UnaryOperator>(Operation)) {
2179 UnaryOperator::Opcode Op = UO->getOpcode();
2180 if (Op == UO_PreInc || Op == UO_PreDec || Op == UO_PostInc ||
2181 Op == UO_PostDec) {
2182 Loc = UO->getSubExpr()->getExprLoc();
2183 Range = UO->getSubExpr()->getSourceRange();
2184 MsgParam = 1;
2185 }
2186 } else {
2187 if (isa<CallExpr>(Operation)) {
2188 MsgParam = 3;
2189 }
2190 Loc = Operation->getBeginLoc();
2191 Range = Operation->getSourceRange();
2192 }
2193 if (IsRelatedToDecl)
2194 S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range;
2195 else
2196 S.Diag(Loc, diag::warn_unsafe_buffer_operation) << MsgParam << Range;
2197 }
2198
2199 // FIXME: rename to handleUnsafeVariable
2200 void handleFixableVariable(const VarDecl *Variable,
2201 FixItList &&Fixes) override {
2202 const auto &D =
2203 S.Diag(Variable->getLocation(), diag::warn_unsafe_buffer_variable);
2204 D << Variable;
2205 D << (Variable->getType()->isPointerType() ? 0 : 1);
2206 D << Variable->getSourceRange();
2207 for (const auto &F : Fixes)
2208 D << F;
2209 }
2210};
2211} // namespace
2212
2213//===----------------------------------------------------------------------===//
2214// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
2215// warnings on a function, method, or block.
2216//===----------------------------------------------------------------------===//
2217
2219 enableCheckFallThrough = 1;
2220 enableCheckUnreachable = 0;
2221 enableThreadSafetyAnalysis = 0;
2222 enableConsumedAnalysis = 0;
2223}
2224
2225/// InterProceduralData aims to be a storage of whatever data should be passed
2226/// between analyses of different functions.
2227///
2228/// At the moment, its primary goal is to make the information gathered during
2229/// the analysis of the blocks available during the analysis of the enclosing
2230/// function. This is important due to the fact that blocks are analyzed before
2231/// the enclosed function is even parsed fully, so it is not viable to access
2232/// anything in the outer scope while analyzing the block. On the other hand,
2233/// re-building CFG for blocks and re-analyzing them when we do have all the
2234/// information (i.e. during the analysis of the enclosing function) seems to be
2235/// ill-designed.
2237public:
2238 // It is important to analyze blocks within functions because it's a very
2239 // common pattern to capture completion handler parameters by blocks.
2240 CalledOnceInterProceduralData CalledOnceData;
2241};
2242
2243static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag) {
2244 return (unsigned)!D.isIgnored(diag, SourceLocation());
2245}
2246
2248 : S(s), IPData(std::make_unique<InterProceduralData>()),
2249 NumFunctionsAnalyzed(0), NumFunctionsWithBadCFGs(0), NumCFGBlocks(0),
2250 MaxCFGBlocksPerFunction(0), NumUninitAnalysisFunctions(0),
2251 NumUninitAnalysisVariables(0), MaxUninitAnalysisVariablesPerFunction(0),
2252 NumUninitAnalysisBlockVisits(0),
2253 MaxUninitAnalysisBlockVisitsPerFunction(0) {
2254
2255 using namespace diag;
2257
2258 DefaultPolicy.enableCheckUnreachable =
2259 isEnabled(D, warn_unreachable) || isEnabled(D, warn_unreachable_break) ||
2260 isEnabled(D, warn_unreachable_return) ||
2261 isEnabled(D, warn_unreachable_loop_increment);
2262
2263 DefaultPolicy.enableThreadSafetyAnalysis = isEnabled(D, warn_double_lock);
2264
2265 DefaultPolicy.enableConsumedAnalysis =
2266 isEnabled(D, warn_use_in_invalid_state);
2267}
2268
2269// We need this here for unique_ptr with forward declared class.
2271
2272static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
2273 for (const auto &D : fscope->PossiblyUnreachableDiags)
2274 S.Diag(D.Loc, D.PD);
2275}
2276
2279 const Decl *D, QualType BlockType) {
2280
2281 // We avoid doing analysis-based warnings when there are errors for
2282 // two reasons:
2283 // (1) The CFGs often can't be constructed (if the body is invalid), so
2284 // don't bother trying.
2285 // (2) The code already has problems; running the analysis just takes more
2286 // time.
2287 DiagnosticsEngine &Diags = S.getDiagnostics();
2288
2289 // Do not do any analysis if we are going to just ignore them.
2290 if (Diags.getIgnoreAllWarnings() ||
2291 (Diags.getSuppressSystemWarnings() &&
2293 return;
2294
2295 // For code in dependent contexts, we'll do this at instantiation time.
2296 if (cast<DeclContext>(D)->isDependentContext())
2297 return;
2298
2300 // Flush out any possibly unreachable diagnostics.
2301 flushDiagnostics(S, fscope);
2302 return;
2303 }
2304
2305 const Stmt *Body = D->getBody();
2306 assert(Body);
2307
2308 // Construct the analysis context with the specified CFG build options.
2309 AnalysisDeclContext AC(/* AnalysisDeclContextManager */ nullptr, D);
2310
2311 // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
2312 // explosion for destructors that can result and the compile time hit.
2314 AC.getCFGBuildOptions().AddEHEdges = false;
2320
2321 // Force that certain expressions appear as CFGElements in the CFG. This
2322 // is used to speed up various analyses.
2323 // FIXME: This isn't the right factoring. This is here for initial
2324 // prototyping, but we need a way for analyses to say what expressions they
2325 // expect to always be CFGElements and then fill in the BuildOptions
2326 // appropriately. This is essentially a layering violation.
2327 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
2328 P.enableConsumedAnalysis) {
2329 // Unreachable code analysis and thread safety require a linearized CFG.
2331 }
2332 else {
2334 .setAlwaysAdd(Stmt::BinaryOperatorClass)
2335 .setAlwaysAdd(Stmt::CompoundAssignOperatorClass)
2336 .setAlwaysAdd(Stmt::BlockExprClass)
2337 .setAlwaysAdd(Stmt::CStyleCastExprClass)
2338 .setAlwaysAdd(Stmt::DeclRefExprClass)
2339 .setAlwaysAdd(Stmt::ImplicitCastExprClass)
2340 .setAlwaysAdd(Stmt::UnaryOperatorClass);
2341 }
2342
2343 // Install the logical handler.
2344 std::optional<LogicalErrorHandler> LEH;
2345 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
2346 LEH.emplace(S);
2347 AC.getCFGBuildOptions().Observer = &*LEH;
2348 }
2349
2350 // Emit delayed diagnostics.
2351 if (!fscope->PossiblyUnreachableDiags.empty()) {
2352 bool analyzed = false;
2353
2354 // Register the expressions with the CFGBuilder.
2355 for (const auto &D : fscope->PossiblyUnreachableDiags) {
2356 for (const Stmt *S : D.Stmts)
2358 }
2359
2360 if (AC.getCFG()) {
2361 analyzed = true;
2362 for (const auto &D : fscope->PossiblyUnreachableDiags) {
2363 bool AllReachable = true;
2364 for (const Stmt *S : D.Stmts) {
2365 const CFGBlock *block = AC.getBlockForRegisteredExpression(S);
2368 // FIXME: We should be able to assert that block is non-null, but
2369 // the CFG analysis can skip potentially-evaluated expressions in
2370 // edge cases; see test/Sema/vla-2.c.
2371 if (block && cra) {
2372 // Can this block be reached from the entrance?
2373 if (!cra->isReachable(&AC.getCFG()->getEntry(), block)) {
2374 AllReachable = false;
2375 break;
2376 }
2377 }
2378 // If we cannot map to a basic block, assume the statement is
2379 // reachable.
2380 }
2381
2382 if (AllReachable)
2383 S.Diag(D.Loc, D.PD);
2384 }
2385 }
2386
2387 if (!analyzed)
2388 flushDiagnostics(S, fscope);
2389 }
2390
2391 // Warning: check missing 'return'
2392 if (P.enableCheckFallThrough) {
2393 const CheckFallThroughDiagnostics &CD =
2394 (isa<BlockDecl>(D)
2395 ? CheckFallThroughDiagnostics::MakeForBlock()
2396 : (isa<CXXMethodDecl>(D) &&
2397 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2398 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2399 ? CheckFallThroughDiagnostics::MakeForLambda()
2400 : (fscope->isCoroutine()
2401 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2402 : CheckFallThroughDiagnostics::MakeForFunction(D)));
2403 CheckFallThroughForBody(S, D, Body, BlockType, CD, AC, fscope);
2404 }
2405
2406 // Warning: check for unreachable code
2407 if (P.enableCheckUnreachable) {
2408 // Only check for unreachable code on non-template instantiations.
2409 // Different template instantiations can effectively change the control-flow
2410 // and it is very difficult to prove that a snippet of code in a template
2411 // is unreachable for all instantiations.
2412 bool isTemplateInstantiation = false;
2413 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
2414 isTemplateInstantiation = Function->isTemplateInstantiation();
2416 CheckUnreachable(S, AC);
2417 }
2418
2419 // Check for thread safety violations
2420 if (P.enableThreadSafetyAnalysis) {
2421 SourceLocation FL = AC.getDecl()->getLocation();
2422 SourceLocation FEL = AC.getDecl()->getEndLoc();
2423 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
2424 if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getBeginLoc()))
2425 Reporter.setIssueBetaWarnings(true);
2426 if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getBeginLoc()))
2427 Reporter.setVerbose(true);
2428
2431 Reporter.emitDiagnostics();
2432 }
2433
2434 // Check for violations of consumed properties.
2435 if (P.enableConsumedAnalysis) {
2436 consumed::ConsumedWarningsHandler WarningHandler(S);
2437 consumed::ConsumedAnalyzer Analyzer(WarningHandler);
2438 Analyzer.run(AC);
2439 }
2440
2441 if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||
2442 !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
2443 !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc()) ||
2444 !Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc())) {
2445 if (CFG *cfg = AC.getCFG()) {
2446 UninitValsDiagReporter reporter(S);
2448 std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats));
2449 runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
2450 reporter, stats);
2451
2452 if (S.CollectStats && stats.NumVariablesAnalyzed > 0) {
2453 ++NumUninitAnalysisFunctions;
2454 NumUninitAnalysisVariables += stats.NumVariablesAnalyzed;
2455 NumUninitAnalysisBlockVisits += stats.NumBlockVisits;
2456 MaxUninitAnalysisVariablesPerFunction =
2457 std::max(MaxUninitAnalysisVariablesPerFunction,
2458 stats.NumVariablesAnalyzed);
2459 MaxUninitAnalysisBlockVisitsPerFunction =
2460 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
2461 stats.NumBlockVisits);
2462 }
2463 }
2464 }
2465
2466 // Check for violations of "called once" parameter properties.
2467 if (S.getLangOpts().ObjC && !S.getLangOpts().CPlusPlus &&
2468 shouldAnalyzeCalledOnceParameters(Diags, D->getBeginLoc())) {
2469 if (AC.getCFG()) {
2470 CalledOnceCheckReporter Reporter(S, IPData->CalledOnceData);
2472 AC, Reporter,
2473 shouldAnalyzeCalledOnceConventions(Diags, D->getBeginLoc()));
2474 }
2475 }
2476
2477 bool FallThroughDiagFull =
2478 !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc());
2479 bool FallThroughDiagPerFunction = !Diags.isIgnored(
2480 diag::warn_unannotated_fallthrough_per_function, D->getBeginLoc());
2481 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
2482 fscope->HasFallthroughStmt) {
2483 DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
2484 }
2485
2486 if (S.getLangOpts().ObjCWeak &&
2487 !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getBeginLoc()))
2488 diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
2489
2490
2491 // Check for infinite self-recursion in functions
2492 if (!Diags.isIgnored(diag::warn_infinite_recursive_function,
2493 D->getBeginLoc())) {
2494 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2495 checkRecursiveFunction(S, FD, Body, AC);
2496 }
2497 }
2498
2499 // Check for throw out of non-throwing function.
2500 if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getBeginLoc()))
2501 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2502 if (S.getLangOpts().CPlusPlus && isNoexcept(FD))
2503 checkThrowInNonThrowingFunc(S, FD, AC);
2504
2505 // Emit unsafe buffer usage warnings and fixits.
2506 if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation, D->getBeginLoc()) ||
2507 !Diags.isIgnored(diag::warn_unsafe_buffer_variable, D->getBeginLoc())) {
2508 UnsafeBufferUsageReporter R(S);
2510 }
2511
2512 // If none of the previous checks caused a CFG build, trigger one here
2513 // for the logical error handler.
2514 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
2515 AC.getCFG();
2516 }
2517
2518 // Collect statistics about the CFG if it was built.
2519 if (S.CollectStats && AC.isCFGBuilt()) {
2520 ++NumFunctionsAnalyzed;
2521 if (CFG *cfg = AC.getCFG()) {
2522 // If we successfully built a CFG for this context, record some more
2523 // detail information about it.
2524 NumCFGBlocks += cfg->getNumBlockIDs();
2525 MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,
2526 cfg->getNumBlockIDs());
2527 } else {
2528 ++NumFunctionsWithBadCFGs;
2529 }
2530 }
2531}
2532
2534 llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
2535
2536 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
2537 unsigned AvgCFGBlocksPerFunction =
2538 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
2539 llvm::errs() << NumFunctionsAnalyzed << " functions analyzed ("
2540 << NumFunctionsWithBadCFGs << " w/o CFGs).\n"
2541 << " " << NumCFGBlocks << " CFG blocks built.\n"
2542 << " " << AvgCFGBlocksPerFunction
2543 << " average CFG blocks per function.\n"
2544 << " " << MaxCFGBlocksPerFunction
2545 << " max CFG blocks per function.\n";
2546
2547 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
2548 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
2549 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
2550 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
2551 llvm::errs() << NumUninitAnalysisFunctions
2552 << " functions analyzed for uninitialiazed variables\n"
2553 << " " << NumUninitAnalysisVariables << " variables analyzed.\n"
2554 << " " << AvgUninitVariablesPerFunction
2555 << " average variables per function.\n"
2556 << " " << MaxUninitAnalysisVariablesPerFunction
2557 << " max variables per function.\n"
2558 << " " << NumUninitAnalysisBlockVisits << " block visits.\n"
2559 << " " << AvgUninitBlockVisitsPerFunction
2560 << " average block visits per function.\n"
2561 << " " << MaxUninitAnalysisBlockVisitsPerFunction
2562 << " max block visits per function.\n";
2563}
#define V(N, I)
Definition: ASTContext.h:3216
StringRef P
static void visitReachableThrows(CFG *BodyCFG, llvm::function_ref< void(const CXXThrowExpr *, CFGBlock &)> Visit)
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD)
static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, const Stmt *S)
static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC)
CheckFallThrough - Check that we don't fall off the end of a Statement that should return a value.
static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope)
static void diagnoseRepeatedUseOfWeak(Sema &S, const sema::FunctionScopeInfo *CurFn, const Decl *D, const ParentMap &PM)
static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc, const FunctionDecl *FD)
static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, bool PerFunction)
static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD, AnalysisDeclContext &AC)
static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, const Stmt *Else, bool CondVal, FixItHint &Fixit1, FixItHint &Fixit2)
Create a fixit to remove an if-like statement, on the assumption that its condition is CondVal.
static StringRef getFallthroughAttrSpelling(Preprocessor &PP, SourceLocation Loc)
static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag)
static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool alwaysReportSelfInit=false)
DiagnoseUninitializedUse – Helper function for diagnosing uses of an uninitialized variable.
static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block)
static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock, CFG *Body)
Determine whether an exception thrown by E, unwinding from ThrowBlock, can reach ExitBlock.
static bool isNoexcept(const FunctionDecl *FD)
static bool DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD, const UninitUse &Use)
Diagnose uninitialized const reference usages.
static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool IsCapturedByBlock)
DiagUninitUse – Helper function to produce a diagnostic for an uninitialized use of a variable.
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC)
CheckUnreachable - Check for unreachable code.
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, QualType BlockType, const CheckFallThroughDiagnostics &CD, AnalysisDeclContext &AC, sema::FunctionScopeInfo *FSI)
CheckFallThroughForBody - Check that we don't fall off the end of a function that should return a val...
@ NeverFallThrough
@ UnknownFallThrough
@ NeverFallThroughOrReturn
@ MaybeFallThrough
@ AlwaysFallThrough
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, const Stmt *Body, AnalysisDeclContext &AC)
static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg)
SourceManager & SM
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
#define SM(sm)
Definition: Cuda.cpp:78
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult, const ASTContext &Ctx, Expr::SideEffectsKind AllowSideEffects, EvalInfo &Info)
static std::pair< const Stmt *, const CFGBlock * > getLastStmt(const ExplodedNode *Node)
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR, AnalysisManager &AM, const ObjCAutoreleaseWriteChecker *Checker)
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
const char * Data
Defines the Objective-C statement AST node classes.
@ Open
The standard open() call: int open(const char *path, int oflag, ...);.
std::string Label
TextDiagnosticBuffer::DiagList DiagList
__device__ __2f16 b
__device__ int
__device__ __2f16 float bool s
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
AnalysisDeclContext contains the context data for the function, method or block under analysis.
void registerForcedBlockExpression(const Stmt *stmt)
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
const Decl * getDecl() const
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
CFG::BuildOptions & getCFGBuildOptions()
Represents an attribute applied to a statement.
Definition: Stmt.h:1892
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3814
static bool isLogicalOp(Opcode Opc)
Definition: Expr.h:3946
Expr * getLHS() const
Definition: Expr.h:3863
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.h:3868
SourceLocation getOperatorLoc() const
Definition: Expr.h:3855
SourceLocation getExprLoc() const
Definition: Expr.h:3854
static StringRef getOpcodeStr(Opcode Op)
getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to,...
Definition: Expr.cpp:2123
Opcode getOpcode() const
Definition: Expr.h:3858
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:4332
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:5973
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.h:5994
unsigned IgnoreDefaultsWithCoveredEnums
Definition: CFG.h:983
Represents a single basic block in a source-level CFG.
Definition: CFG.h:576
filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const
Definition: CFG.h:1029
pred_iterator pred_end()
Definition: CFG.h:938
reverse_iterator rbegin()
Definition: CFG.h:880
reverse_iterator rend()
Definition: CFG.h:881
bool hasNoReturnElement() const
Definition: CFG.h:1072
succ_range succs()
Definition: CFG.h:965
bool empty() const
Definition: CFG.h:918
Stmt * getLabel()
Definition: CFG.h:1069
succ_iterator succ_begin()
Definition: CFG.h:955
Stmt * getTerminatorStmt()
Definition: CFG.h:1050
pred_iterator pred_begin()
Definition: CFG.h:937
unsigned getBlockID() const
Definition: CFG.h:1074
bool pred_empty() const
Definition: CFG.h:977
unsigned succ_size() const
Definition: CFG.h:973
CFGCallback defines methods that should be called when a logical operator error is found when buildin...
Definition: CFG.h:1207
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
Definition: CFG.h:1213
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
Definition: CFG.h:1212
virtual void compareBitwiseOr(const BinaryOperator *B)
Definition: CFG.h:1215
Represents a top-level expression in a basic block.
Definition: CFG.h:54
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
Definition: CFG.h:97
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Definition: CFG.h:107
bool isReachable(const CFGBlock *Src, const CFGBlock *Dst)
Returns true if the block 'Dst' can be reached from block 'Src'.
const Stmt * getStmt() const
Definition: CFG.h:136
bool PruneTriviallyFalseEdges
Definition: CFG.h:1239
bool AddCXXDefaultInitExprInCtors
Definition: CFG.h:1249
BuildOptions & setAllAlwaysAdd()
Definition: CFG.h:1267
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
Definition: CFG.h:1262
CFGCallback * Observer
Definition: CFG.h:1238
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition: CFG.h:1225
CFGBlock & getExit()
Definition: CFG.h:1333
CFGBlock & getEntry()
Definition: CFG.h:1331
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition: CFG.h:1411
Represents a call to a member function that may be written either with member call syntax (e....
Definition: ExprCXX.h:176
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Definition: ExprCXX.cpp:670
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition: ExprCXX.cpp:651
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1995
bool isVirtual() const
Definition: DeclCXX.h:2039
A C++ throw-expression (C++ [except.throw]).
Definition: ExprCXX.h:1187
const Expr * getSubExpr() const
Definition: ExprCXX.h:1207
SourceLocation getThrowLoc() const
Definition: ExprCXX.h:1210
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2812
Expr * getCallee()
Definition: Expr.h:2962
Decl * getCalleeDecl()
Definition: Expr.h:2976
virtual void handleBlockThatIsGuaranteedToBeCalledOnce(const BlockDecl *Block)
Called when the block is guaranteed to be called exactly once.
virtual void handleBlockWithNoGuarantees(const BlockDecl *Block)
Called when the block has no guarantees about how many times it can get called.
virtual void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call, const Expr *PrevCall, bool IsCompletionHandler, bool Poised)
Called when parameter is called twice.
virtual void handleNeverCalled(const ParmVarDecl *Parameter, bool IsCompletionHandler)
Called when parameter is not called at all.
virtual void handleCapturedNeverCalled(const ParmVarDecl *Parameter, const Decl *Where, bool IsCompletionHandler)
Called when captured parameter is not called at all.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getBegin() const
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:4152
Expr * getFalseExpr() const
Definition: Expr.h:4184
Expr * getCond() const
Definition: Expr.h:4175
Expr * getTrueExpr() const
Definition: Expr.h:4179
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1389
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1238
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
SourceLocation getEndLoc() const LLVM_READONLY
Definition: DeclBase.h:428
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:1052
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition: DeclBase.cpp:227
SourceLocation getLocation() const
Definition: DeclBase.h:432
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:424
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition: DeclBase.h:883
bool hasAttr() const
Definition: DeclBase.h:560
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:943
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:819
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:796
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
bool getIgnoreAllWarnings() const
Definition: Diagnostic.h:648
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
Definition: Diagnostic.h:911
bool getSuppressSystemWarnings() const
Definition: Diagnostic.h:685
This represents one expression.
Definition: Expr.h:110
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3041
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3036
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:330
QualType getType() const
Definition: Expr.h:142
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:71
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
Definition: Diagnostic.h:75
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Definition: Diagnostic.h:134
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition: Diagnostic.h:123
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Definition: Diagnostic.h:97
Represents a function declaration or definition.
Definition: Decl.h:1919
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition: Decl.cpp:3126
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:3406
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification,...
Definition: Decl.cpp:3680
@ TK_MemberSpecialization
Definition: Decl.h:1931
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition: Decl.cpp:3768
bool isCPUDispatchMultiVersion() const
True if this function is a multiversioned dispatch function as a part of the cpu_specific/cpu_dispatc...
Definition: Decl.cpp:3374
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4034
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: Type.h:3687
IfStmt - This represents an if/then/else.
Definition: Stmt.h:1950
Stmt * getThen()
Definition: Stmt.h:2039
Expr * getCond()
Definition: Stmt.h:2027
Stmt * getElse()
Definition: Stmt.h:2048
LabelStmt - Represents a label, which has a substatement.
Definition: Stmt.h:1843
Stmt * getSubStmt()
Definition: Stmt.h:1865
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Definition: ExprCXX.h:1924
This represents a decl that may have a name.
Definition: Decl.h:247
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:313
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
@ TypeSpec
A type, stored as a Type*.
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:138
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:729
Stmt * getParent(Stmt *) const
Definition: ParentMap.cpp:136
Represents a parameter to a function.
Definition: Decl.h:1724
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:128
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
const LangOptions & getLangOpts() const
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
A (possibly-)qualified type.
Definition: Type.h:736
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:803
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: Type.h:6680
QualType getCanonicalType() const
Definition: Type.h:6692
bool hasObjCLifetime() const
Definition: Type.h:350
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, Expr *Init)
Recursively visit a lambda capture.
bool shouldWalkTypesOfTypeLocs() const
Return whether this visitor should recurse into the types of TypeLocs.
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:358
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: Sema.cpp:1895
Preprocessor & getPreprocessor() const
Definition: Sema.h:1655
ASTContext & Context
Definition: Sema.h:409
DiagnosticsEngine & getDiagnostics() const
Definition: Sema.h:1653
ASTContext & getASTContext() const
Definition: Sema.h:1656
std::string getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const
Get a string to suggest for zero-initialization of a type.
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
Definition: Sema.cpp:57
const LangOptions & getLangOpts() const
Definition: Sema.h:1649
threadSafety::BeforeSet * ThreadSafetyDeclCache
Definition: Sema.h:9805
bool CollectStats
Flag indicating whether or not to collect detailed statistics.
Definition: Sema.h:415
SourceManager & getSourceManager() const
Definition: Sema.h:1654
bool handlerCanCatch(QualType HandlerType, QualType ExceptionType)
bool hasUncompilableErrorOccurred() const
Whether uncompilable error has occurred.
Definition: Sema.cpp:1603
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition: SemaInternal.h:24
SourceManager & SourceMgr
Definition: Sema.h:412
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
bool isValid() const
Stmt - This represents one statement.
Definition: Stmt.h:72
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:349
child_range children()
Definition: Stmt.cpp:286
StmtClass getStmtClass() const
Definition: Stmt.h:1177
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:325
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:337
Stmt * getSubStmt()
Definition: Stmt.h:1810
SwitchStmt - This represents a 'switch' stmt.
Definition: Stmt.h:2195
Stores token information for comparing actual tokens with predefined values.
Definition: Preprocessor.h:89
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:6622
bool isBlockPointerType() const
Definition: Type.h:6909
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:7471
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:629
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7404
A use of a variable, which might be uninitialized.
const Expr * getUser() const
Get the expression containing the uninitialized use.
SmallVectorImpl< Branch >::const_iterator branch_iterator
branch_iterator branch_end() const
branch_iterator branch_begin() const
Branches which inevitably result in the variable being used uninitialized.
@ Always
The use is always uninitialized.
@ AfterDecl
The use is uninitialized the first time it is reached after we reach the variable's declaration.
@ Maybe
The use might be uninitialized.
@ AfterCall
The use is uninitialized the first time it is reached after the function is called.
@ Sometimes
The use is uninitialized whenever a certain branch is taken.
Kind getKind() const
Get the kind of uninitialized use.
virtual void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use)
Called when the uninitialized variable is used at the given expression.
virtual void handleSelfInit(const VarDecl *vd)
Called when the uninitialized variable analysis detects the idiom 'int x = x'.
virtual void handleConstRefUseOfUninitVariable(const VarDecl *vd, const UninitUse &use)
Called when the uninitialized variable is used as const refernce argument.
The interface that lets the caller handle unsafe buffer usage analysis results by overriding this cla...
virtual void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl)=0
Invoked when an unsafe operation over raw pointers is found.
virtual void handleFixableVariable(const VarDecl *Variable, FixItList &&List)=0
Invoked when a fix is suggested against a variable.
QualType getType() const
Definition: Decl.h:714
Represents a variable declaration or definition.
Definition: Decl.h:915
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:2126
const Expr * getInit() const
Definition: Decl.h:1327
A class that handles the analysis of uniqueness violations.
Definition: Consumed.h:239
void run(AnalysisDeclContext &AC)
Check a function's CFG for consumed violations.
Definition: Consumed.cpp:1304
virtual void HandleUnreachable(UnreachableKind UK, SourceLocation L, SourceRange ConditionVal, SourceRange R1, SourceRange R2)=0
void IssueWarnings(Policy P, FunctionScopeInfo *fscope, const Decl *D, QualType BlockType)
Represents a simple identification of a weak object.
Definition: ScopeInfo.h:262
Retains information about a function, method, or block that is currently being parsed.
Definition: ScopeInfo.h:102
llvm::SmallDenseMap< WeakObjectProfileTy, WeakUseVector, 8, WeakObjectProfileTy::DenseMapInfo > WeakObjectUseMap
Used to collect all uses of weak objects in a function body.
Definition: ScopeInfo.h:371
bool HasFallthroughStmt
Whether there is a fallthrough statement in this function.
Definition: ScopeInfo.h:136
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
Definition: ScopeInfo.h:208
SmallVector< PossiblyUnreachableDiag, 4 > PossiblyUnreachableDiags
A list of PartialDiagnostics created but delayed within the current function scope.
Definition: ScopeInfo.h:230
const WeakObjectUseMap & getWeakObjectUses() const
Definition: ScopeInfo.h:421
Handler class for thread safety warnings.
Definition: ThreadSafety.h:93
InterProceduralData aims to be a storage of whatever data should be passed between analyses of differ...
SmallVector< PartialDiagnosticAt, 1 > OptionalNotes
Definition: Consumed.h:52
std::pair< PartialDiagnosticAt, OptionalNotes > DelayedDiag
Definition: Consumed.h:53
uint32_t Variable
Boolean variables are represented as positive integers.
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:628
bool Call(InterpState &S, CodePtr &PC, const Function *Func)
Definition: Interp.h:1458
void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP, Callback &CB)
unsigned ScanReachableFromBlock(const CFGBlock *Start, llvm::BitVector &Reachable)
ScanReachableFromBlock - Mark all blocks reachable from Start.
UnreachableKind
Classifications of unreachable code.
Definition: ReachableCode.h:40
LockKind getLockKindFromAccessKind(AccessKind AK)
Helper function that returns a LockKind required for the given level of access.
LockKind
This enum distinguishes between different kinds of lock actions.
Definition: ThreadSafety.h:56
void runThreadSafetyAnalysis(AnalysisDeclContext &AC, ThreadSafetyHandler &Handler, BeforeSet **Bset)
Check a function's CFG for thread-safety violations.
ProtectedOperationKind
This enum distinguishes between different kinds of operations that may need to be protected by locks.
Definition: ThreadSafety.h:36
@ POK_PtPassByRef
Passing a pt-guarded variable by reference.
Definition: ThreadSafety.h:50
@ POK_VarDereference
Dereferencing a variable (e.g. p in *p = 5;)
Definition: ThreadSafety.h:38
@ POK_PassByRef
Passing a guarded variable by reference.
Definition: ThreadSafety.h:47
@ POK_VarAccess
Reading or writing a variable (e.g. x in x = 5;)
Definition: ThreadSafety.h:41
@ POK_FunctionCall
Making a function call (e.g. fool())
Definition: ThreadSafety.h:44
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
Definition: Specifiers.h:200
BinaryOperatorKind
@ C
Languages that the frontend can parse and compile.
@ Property
The type of a property.
@ Parameter
The parameter type of a method or function.
UnaryOperatorKind
void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, AnalysisDeclContext &ac, UninitVariablesHandler &handler, UninitVariablesAnalysisStats &stats)
void checkCalledOnceParameters(AnalysisDeclContext &AC, CalledOnceCheckHandler &Handler, bool CheckConventionalParameters)
Check given CFG for 'called once' parameter violations.
void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler)
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
Definition: Format.h:4608
#define false
Definition: stdbool.h:22
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:623