clang 22.0.0git
AnalysisBasedWarnings.cpp
Go to the documentation of this file.
1//=== AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis ------===//
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/Decl.h"
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/DeclObjC.h"
21#include "clang/AST/Expr.h"
22#include "clang/AST/ExprCXX.h"
23#include "clang/AST/ExprObjC.h"
25#include "clang/AST/ParentMap.h"
26#include "clang/AST/StmtCXX.h"
27#include "clang/AST/StmtObjC.h"
28#include "clang/AST/Type.h"
38#include "clang/Analysis/CFG.h"
48#include "llvm/ADT/ArrayRef.h"
49#include "llvm/ADT/BitVector.h"
50#include "llvm/ADT/DenseMap.h"
51#include "llvm/ADT/MapVector.h"
52#include "llvm/ADT/STLFunctionalExtras.h"
53#include "llvm/ADT/SmallVector.h"
54#include "llvm/ADT/StringRef.h"
55#include "llvm/Support/Debug.h"
56#include <algorithm>
57#include <deque>
58#include <iterator>
59#include <optional>
60
61using namespace clang;
62
63//===----------------------------------------------------------------------===//
64// Unreachable code analysis.
65//===----------------------------------------------------------------------===//
66
67namespace {
68 class UnreachableCodeHandler : public reachable_code::Callback {
69 Sema &S;
70 SourceRange PreviousSilenceableCondVal;
71
72 public:
73 UnreachableCodeHandler(Sema &s) : S(s) {}
74
75 void HandleUnreachable(reachable_code::UnreachableKind UK, SourceLocation L,
76 SourceRange SilenceableCondVal, SourceRange R1,
77 SourceRange R2, bool HasFallThroughAttr) override {
78 // If the diagnosed code is `[[fallthrough]];` and
79 // `-Wunreachable-code-fallthrough` is enabled, suppress `code will never
80 // be executed` warning to avoid generating diagnostic twice
81 if (HasFallThroughAttr &&
82 !S.getDiagnostics().isIgnored(diag::warn_unreachable_fallthrough_attr,
83 SourceLocation()))
84 return;
85
86 // Avoid reporting multiple unreachable code diagnostics that are
87 // triggered by the same conditional value.
88 if (PreviousSilenceableCondVal.isValid() &&
89 SilenceableCondVal.isValid() &&
90 PreviousSilenceableCondVal == SilenceableCondVal)
91 return;
92 PreviousSilenceableCondVal = SilenceableCondVal;
93
94 unsigned diag = diag::warn_unreachable;
95 switch (UK) {
97 diag = diag::warn_unreachable_break;
98 break;
100 diag = diag::warn_unreachable_return;
101 break;
103 diag = diag::warn_unreachable_loop_increment;
104 break;
106 break;
107 }
108
109 S.Diag(L, diag) << R1 << R2;
110
111 SourceLocation Open = SilenceableCondVal.getBegin();
112 if (Open.isValid()) {
113 SourceLocation Close = SilenceableCondVal.getEnd();
114 Close = S.getLocForEndOfToken(Close);
115 if (Close.isValid()) {
116 S.Diag(Open, diag::note_unreachable_silence)
117 << FixItHint::CreateInsertion(Open, "/* DISABLES CODE */ (")
118 << FixItHint::CreateInsertion(Close, ")");
119 }
120 }
121 }
122 };
123} // anonymous namespace
124
125/// CheckUnreachable - Check for unreachable code.
127 // As a heuristic prune all diagnostics not in the main file. Currently
128 // the majority of warnings in headers are false positives. These
129 // are largely caused by configuration state, e.g. preprocessor
130 // defined code, etc.
131 //
132 // Note that this is also a performance optimization. Analyzing
133 // headers many times can be expensive.
135 return;
136
137 UnreachableCodeHandler UC(S);
139}
140
141namespace {
142/// Warn on logical operator errors in CFGBuilder
143class LogicalErrorHandler : public CFGCallback {
144 Sema &S;
145
146public:
147 LogicalErrorHandler(Sema &S) : S(S) {}
148
149 static bool HasMacroID(const Expr *E) {
150 if (E->getExprLoc().isMacroID())
151 return true;
152
153 // Recurse to children.
154 for (const Stmt *SubStmt : E->children())
155 if (const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
156 if (HasMacroID(SubExpr))
157 return true;
158
159 return false;
160 }
161
162 void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override {
163 if (HasMacroID(B))
164 return;
165
166 unsigned DiagID = isAlwaysTrue
167 ? diag::warn_tautological_negation_or_compare
168 : diag::warn_tautological_negation_and_compare;
169 SourceRange DiagRange = B->getSourceRange();
170 S.Diag(B->getExprLoc(), DiagID) << DiagRange;
171 }
172
173 void compareAlwaysTrue(const BinaryOperator *B,
174 bool isAlwaysTrueOrFalse) override {
175 if (HasMacroID(B))
176 return;
177
178 SourceRange DiagRange = B->getSourceRange();
179 S.Diag(B->getExprLoc(), diag::warn_tautological_overlap_comparison)
180 << DiagRange << isAlwaysTrueOrFalse;
181 }
182
183 void compareBitwiseEquality(const BinaryOperator *B,
184 bool isAlwaysTrue) override {
185 if (HasMacroID(B))
186 return;
187
188 SourceRange DiagRange = B->getSourceRange();
189 S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_always)
190 << DiagRange << isAlwaysTrue;
191 }
192
193 void compareBitwiseOr(const BinaryOperator *B) override {
194 if (HasMacroID(B))
195 return;
196
197 SourceRange DiagRange = B->getSourceRange();
198 S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_or) << DiagRange;
199 }
200
201 static bool hasActiveDiagnostics(DiagnosticsEngine &Diags,
202 SourceLocation Loc) {
203 return !Diags.isIgnored(diag::warn_tautological_overlap_comparison, Loc) ||
204 !Diags.isIgnored(diag::warn_comparison_bitwise_or, Loc) ||
205 !Diags.isIgnored(diag::warn_tautological_negation_and_compare, Loc);
206 }
207};
208} // anonymous namespace
209
210//===----------------------------------------------------------------------===//
211// Check for infinite self-recursion in functions
212//===----------------------------------------------------------------------===//
213
214// Returns true if the function is called anywhere within the CFGBlock.
215// For member functions, the additional condition of being call from the
216// this pointer is required.
218 // Process all the Stmt's in this block to find any calls to FD.
219 for (const auto &B : Block) {
220 if (B.getKind() != CFGElement::Statement)
221 continue;
222
223 const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
224 if (!CE || !CE->getCalleeDecl() ||
225 CE->getCalleeDecl()->getCanonicalDecl() != FD)
226 continue;
227
228 // Skip function calls which are qualified with a templated class.
229 if (const DeclRefExpr *DRE =
230 dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts()))
231 if (NestedNameSpecifier NNS = DRE->getQualifier();
233 if (isa_and_nonnull<TemplateSpecializationType>(NNS.getAsType()))
234 continue;
235
236 const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE);
237 if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
238 !MCE->getMethodDecl()->isVirtual())
239 return true;
240 }
241 return false;
242}
243
244// Returns true if every path from the entry block passes through a call to FD.
245static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
248 // Keep track of whether we found at least one recursive path.
249 bool foundRecursion = false;
250
251 const unsigned ExitID = cfg->getExit().getBlockID();
252
253 // Seed the work list with the entry block.
254 WorkList.push_back(&cfg->getEntry());
255
256 while (!WorkList.empty()) {
257 CFGBlock *Block = WorkList.pop_back_val();
258
259 for (auto I = Block->succ_begin(), E = Block->succ_end(); I != E; ++I) {
260 if (CFGBlock *SuccBlock = *I) {
261 if (!Visited.insert(SuccBlock).second)
262 continue;
263
264 // Found a path to the exit node without a recursive call.
265 if (ExitID == SuccBlock->getBlockID())
266 return false;
267
268 // If the successor block contains a recursive call, end analysis there.
269 if (hasRecursiveCallInPath(FD, *SuccBlock)) {
270 foundRecursion = true;
271 continue;
272 }
273
274 WorkList.push_back(SuccBlock);
275 }
276 }
277 }
278 return foundRecursion;
279}
280
281static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
282 const Stmt *Body, AnalysisDeclContext &AC) {
283 FD = FD->getCanonicalDecl();
284
285 // Only run on non-templated functions and non-templated members of
286 // templated classes.
289 return;
290
291 CFG *cfg = AC.getCFG();
292 if (!cfg) return;
293
294 // If the exit block is unreachable, skip processing the function.
295 if (cfg->getExit().pred_empty())
296 return;
297
298 // Emit diagnostic if a recursive function call is detected for all paths.
300 S.Diag(Body->getBeginLoc(), diag::warn_infinite_recursive_function);
301}
302
303//===----------------------------------------------------------------------===//
304// Check for throw in a non-throwing function.
305//===----------------------------------------------------------------------===//
306
307/// Determine whether an exception thrown by E, unwinding from ThrowBlock,
308/// can reach ExitBlock.
309static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock,
310 CFG *Body) {
312 llvm::BitVector Queued(Body->getNumBlockIDs());
313
314 Stack.push_back(&ThrowBlock);
315 Queued[ThrowBlock.getBlockID()] = true;
316
317 while (!Stack.empty()) {
318 CFGBlock &UnwindBlock = *Stack.pop_back_val();
319
320 for (auto &Succ : UnwindBlock.succs()) {
321 if (!Succ.isReachable() || Queued[Succ->getBlockID()])
322 continue;
323
324 if (Succ->getBlockID() == Body->getExit().getBlockID())
325 return true;
326
327 if (auto *Catch =
328 dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
329 QualType Caught = Catch->getCaughtType();
330 if (Caught.isNull() || // catch (...) catches everything
331 !E->getSubExpr() || // throw; is considered cuaght by any handler
332 S.handlerCanCatch(Caught, E->getSubExpr()->getType()))
333 // Exception doesn't escape via this path.
334 break;
335 } else {
336 Stack.push_back(Succ);
337 Queued[Succ->getBlockID()] = true;
338 }
339 }
340 }
341
342 return false;
343}
344
346 CFG *BodyCFG,
347 llvm::function_ref<void(const CXXThrowExpr *, CFGBlock &)> Visit) {
348 llvm::BitVector Reachable(BodyCFG->getNumBlockIDs());
350 for (CFGBlock *B : *BodyCFG) {
351 if (!Reachable[B->getBlockID()])
352 continue;
353 for (CFGElement &E : *B) {
354 std::optional<CFGStmt> S = E.getAs<CFGStmt>();
355 if (!S)
356 continue;
357 if (auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
358 Visit(Throw, *B);
359 }
360 }
361}
362
364 const FunctionDecl *FD) {
365 if (!S.getSourceManager().isInSystemHeader(OpLoc) &&
366 FD->getTypeSourceInfo()) {
367 S.Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
368 if (S.getLangOpts().CPlusPlus11 &&
370 FD->getDeclName().getCXXOverloadedOperator() == OO_Delete ||
371 FD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete)) {
372 if (const auto *Ty = FD->getTypeSourceInfo()->getType()->
373 getAs<FunctionProtoType>())
374 S.Diag(FD->getLocation(), diag::note_throw_in_dtor)
375 << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
377 } else
378 S.Diag(FD->getLocation(), diag::note_throw_in_function)
380 }
381}
382
385 CFG *BodyCFG = AC.getCFG();
386 if (!BodyCFG)
387 return;
388 if (BodyCFG->getExit().pred_empty())
389 return;
390 visitReachableThrows(BodyCFG, [&](const CXXThrowExpr *Throw, CFGBlock &Block) {
391 if (throwEscapes(S, Throw, Block, BodyCFG))
393 });
394}
395
396static bool isNoexcept(const FunctionDecl *FD) {
397 const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
398 if (FPT->isNothrow() || FD->hasAttr<NoThrowAttr>())
399 return true;
400 return false;
401}
402
403/// Checks if the given expression is a reference to a function with
404/// 'noreturn' attribute.
405static bool isReferenceToNoReturn(const Expr *E) {
406 if (auto *DRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
407 if (auto *FD = dyn_cast<FunctionDecl>(DRef->getDecl()))
408 return FD->isNoReturn();
409 return false;
410}
411
412/// Checks if the given variable, which is assumed to be a function pointer, is
413/// initialized with a function having 'noreturn' attribute.
414static bool isInitializedWithNoReturn(const VarDecl *VD) {
415 if (const Expr *Init = VD->getInit()) {
416 if (auto *ListInit = dyn_cast<InitListExpr>(Init);
417 ListInit && ListInit->getNumInits() > 0)
418 Init = ListInit->getInit(0);
420 }
421 return false;
422}
423
424namespace {
425
426/// Looks for statements, that can define value of the given variable.
427struct TransferFunctions : public StmtVisitor<TransferFunctions> {
428 const VarDecl *Var;
429 std::optional<bool> AllValuesAreNoReturn;
430
431 TransferFunctions(const VarDecl *VD) : Var(VD) {}
432
433 void reset() { AllValuesAreNoReturn = std::nullopt; }
434
435 void VisitDeclStmt(DeclStmt *DS) {
436 for (auto *DI : DS->decls())
437 if (auto *VD = dyn_cast<VarDecl>(DI))
438 if (VarDecl *Def = VD->getDefinition())
439 if (Def == Var)
440 AllValuesAreNoReturn = isInitializedWithNoReturn(Def);
441 }
442
443 void VisitUnaryOperator(UnaryOperator *UO) {
444 if (UO->getOpcode() == UO_AddrOf) {
445 if (auto *DRef =
446 dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParenCasts()))
447 if (DRef->getDecl() == Var)
448 AllValuesAreNoReturn = false;
449 }
450 }
451
452 void VisitBinaryOperator(BinaryOperator *BO) {
453 if (BO->getOpcode() == BO_Assign)
454 if (auto *DRef = dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParenCasts()))
455 if (DRef->getDecl() == Var)
456 AllValuesAreNoReturn = isReferenceToNoReturn(BO->getRHS());
457 }
458
459 void VisitCallExpr(CallExpr *CE) {
460 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E;
461 ++I) {
462 const Expr *Arg = *I;
463 if (Arg->isGLValue() && !Arg->getType().isConstQualified())
464 if (auto *DRef = dyn_cast<DeclRefExpr>(Arg->IgnoreParenCasts()))
465 if (auto VD = dyn_cast<VarDecl>(DRef->getDecl()))
466 if (VD->getDefinition() == Var)
467 AllValuesAreNoReturn = false;
468 }
469 }
470};
471} // namespace
472
473// Checks if all possible values of the given variable are functions with
474// 'noreturn' attribute.
475static bool areAllValuesNoReturn(const VarDecl *VD, const CFGBlock &VarBlk,
477 // The set of possible values of a constant variable is determined by
478 // its initializer, unless it is a function parameter.
479 if (!isa<ParmVarDecl>(VD) && VD->getType().isConstant(AC.getASTContext())) {
480 if (const VarDecl *Def = VD->getDefinition())
481 return isInitializedWithNoReturn(Def);
482 return false;
483 }
484
485 // In multithreaded environment the value of a global variable may be changed
486 // asynchronously.
488 return false;
489
490 // Check the condition "all values are noreturn". It is satisfied if the
491 // variable is set to "noreturn" value in the current block or all its
492 // predecessors satisfies the condition.
493 using MapTy = llvm::DenseMap<const CFGBlock *, std::optional<bool>>;
494 using ValueTy = MapTy::value_type;
495 MapTy BlocksToCheck;
496 BlocksToCheck[&VarBlk] = std::nullopt;
497 const auto BlockSatisfiesCondition = [](ValueTy Item) {
498 return Item.getSecond().value_or(false);
499 };
500
501 TransferFunctions TF(VD);
502 BackwardDataflowWorklist Worklist(*AC.getCFG(), AC);
503 llvm::DenseSet<const CFGBlock *> Visited;
504 Worklist.enqueueBlock(&VarBlk);
505 while (const CFGBlock *B = Worklist.dequeue()) {
506 if (Visited.contains(B))
507 continue;
508 Visited.insert(B);
509 // First check the current block.
510 for (CFGBlock::const_reverse_iterator ri = B->rbegin(), re = B->rend();
511 ri != re; ++ri) {
512 if (std::optional<CFGStmt> cs = ri->getAs<CFGStmt>()) {
513 const Stmt *S = cs->getStmt();
514 TF.reset();
515 TF.Visit(const_cast<Stmt *>(S));
516 if (TF.AllValuesAreNoReturn) {
517 if (!TF.AllValuesAreNoReturn.value())
518 return false;
519 BlocksToCheck[B] = true;
520 break;
521 }
522 }
523 }
524
525 // If all checked blocks satisfy the condition, the check is finished.
526 if (llvm::all_of(BlocksToCheck, BlockSatisfiesCondition))
527 return true;
528
529 // If this block does not contain the variable definition, check
530 // its predecessors.
531 if (!BlocksToCheck[B]) {
532 Worklist.enqueuePredecessors(B);
533 BlocksToCheck.erase(B);
534 for (const auto &PredBlk : B->preds())
535 if (!BlocksToCheck.contains(PredBlk))
536 BlocksToCheck[PredBlk] = std::nullopt;
537 }
538 }
539
540 return false;
541}
542
543//===----------------------------------------------------------------------===//
544// Check for missing return value.
545//===----------------------------------------------------------------------===//
546
554
555/// CheckFallThrough - Check that we don't fall off the end of a
556/// Statement that should return a value.
557///
558/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
559/// MaybeFallThrough iff we might or might not fall off the end,
560/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
561/// return. We assume NeverFallThrough iff we never fall off the end of the
562/// statement but we may return. We assume that functions not marked noreturn
563/// will return.
565 CFG *cfg = AC.getCFG();
566 if (!cfg) return UnknownFallThrough;
567
568 // The CFG leaves in dead things, and we don't want the dead code paths to
569 // confuse us, so we mark all live things first.
570 llvm::BitVector live(cfg->getNumBlockIDs());
571 unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(),
572 live);
573
574 bool AddEHEdges = AC.getAddEHEdges();
575 if (!AddEHEdges && count != cfg->getNumBlockIDs())
576 // When there are things remaining dead, and we didn't add EH edges
577 // from CallExprs to the catch clauses, we have to go back and
578 // mark them as live.
579 for (const auto *B : *cfg) {
580 if (!live[B->getBlockID()]) {
581 if (B->preds().empty()) {
582 const Stmt *Term = B->getTerminatorStmt();
583 if (isa_and_nonnull<CXXTryStmt>(Term))
584 // When not adding EH edges from calls, catch clauses
585 // can otherwise seem dead. Avoid noting them as dead.
587 continue;
588 }
589 }
590 }
591
592 // Now we know what is live, we check the live precessors of the exit block
593 // and look for fall through paths, being careful to ignore normal returns,
594 // and exceptional paths.
595 bool HasLiveReturn = false;
596 bool HasFakeEdge = false;
597 bool HasPlainEdge = false;
598 bool HasAbnormalEdge = false;
599
600 // Ignore default cases that aren't likely to be reachable because all
601 // enums in a switch(X) have explicit case statements.
604
607 I.hasMore(); ++I) {
608 const CFGBlock &B = **I;
609 if (!live[B.getBlockID()])
610 continue;
611
612 // Skip blocks which contain an element marked as no-return. They don't
613 // represent actually viable edges into the exit block, so mark them as
614 // abnormal.
615 if (B.hasNoReturnElement()) {
616 HasAbnormalEdge = true;
617 continue;
618 }
619
620 // Destructors can appear after the 'return' in the CFG. This is
621 // normal. We need to look pass the destructors for the return
622 // statement (if it exists).
624
625 for ( ; ri != re ; ++ri)
626 if (ri->getAs<CFGStmt>())
627 break;
628
629 // No more CFGElements in the block?
630 if (ri == re) {
631 const Stmt *Term = B.getTerminatorStmt();
632 if (Term && (isa<CXXTryStmt>(Term) || isa<ObjCAtTryStmt>(Term))) {
633 HasAbnormalEdge = true;
634 continue;
635 }
636 // A labeled empty statement, or the entry block...
637 HasPlainEdge = true;
638 continue;
639 }
640
641 CFGStmt CS = ri->castAs<CFGStmt>();
642 const Stmt *S = CS.getStmt();
643 if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
644 HasLiveReturn = true;
645 continue;
646 }
647 if (isa<ObjCAtThrowStmt>(S)) {
648 HasFakeEdge = true;
649 continue;
650 }
651 if (isa<CXXThrowExpr>(S)) {
652 HasFakeEdge = true;
653 continue;
654 }
655 if (isa<MSAsmStmt>(S)) {
656 // TODO: Verify this is correct.
657 HasFakeEdge = true;
658 HasLiveReturn = true;
659 continue;
660 }
661 if (isa<CXXTryStmt>(S)) {
662 HasAbnormalEdge = true;
663 continue;
664 }
665 if (!llvm::is_contained(B.succs(), &cfg->getExit())) {
666 HasAbnormalEdge = true;
667 continue;
668 }
669 if (auto *Call = dyn_cast<CallExpr>(S)) {
670 const Expr *Callee = Call->getCallee();
671 if (Callee->getType()->isPointerType())
672 if (auto *DeclRef =
673 dyn_cast<DeclRefExpr>(Callee->IgnoreParenImpCasts()))
674 if (auto *VD = dyn_cast<VarDecl>(DeclRef->getDecl()))
675 if (areAllValuesNoReturn(VD, B, AC)) {
676 HasAbnormalEdge = true;
677 continue;
678 }
679 }
680
681 HasPlainEdge = true;
682 }
683 if (!HasPlainEdge) {
684 if (HasLiveReturn)
685 return NeverFallThrough;
687 }
688 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
689 return MaybeFallThrough;
690 // This says AlwaysFallThrough for calls to functions that are not marked
691 // noreturn, that don't return. If people would like this warning to be more
692 // accurate, such functions should be marked as noreturn.
693 return AlwaysFallThrough;
694}
695
696namespace {
697
698struct CheckFallThroughDiagnostics {
699 unsigned diag_FallThrough_HasNoReturn = 0;
700 unsigned diag_FallThrough_ReturnsNonVoid = 0;
701 unsigned diag_NeverFallThroughOrReturn = 0;
702 unsigned FunKind; // TODO: use diag::FalloffFunctionKind
703 SourceLocation FuncLoc;
704
705 static CheckFallThroughDiagnostics MakeForFunction(Sema &S,
706 const Decl *Func) {
707 CheckFallThroughDiagnostics D;
708 D.FuncLoc = Func->getLocation();
709 D.diag_FallThrough_HasNoReturn = diag::warn_noreturn_has_return_expr;
710 D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
711
712 // Don't suggest that virtual functions be marked "noreturn", since they
713 // might be overridden by non-noreturn functions.
714 bool isVirtualMethod = false;
715 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
716 isVirtualMethod = Method->isVirtual();
717
718 // Don't suggest that template instantiations be marked "noreturn"
719 bool isTemplateInstantiation = false;
720 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) {
721 isTemplateInstantiation = Function->isTemplateInstantiation();
722 if (!S.getLangOpts().CPlusPlus && !S.getLangOpts().C99 &&
723 Function->isMain()) {
724 D.diag_FallThrough_ReturnsNonVoid = diag::ext_main_no_return;
725 }
726 }
727
728 if (!isVirtualMethod && !isTemplateInstantiation)
729 D.diag_NeverFallThroughOrReturn = diag::warn_suggest_noreturn_function;
730
731 D.FunKind = diag::FalloffFunctionKind::Function;
732 return D;
733 }
734
735 static CheckFallThroughDiagnostics MakeForCoroutine(const Decl *Func) {
736 CheckFallThroughDiagnostics D;
737 D.FuncLoc = Func->getLocation();
738 D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
739 D.FunKind = diag::FalloffFunctionKind::Coroutine;
740 return D;
741 }
742
743 static CheckFallThroughDiagnostics MakeForBlock() {
744 CheckFallThroughDiagnostics D;
745 D.diag_FallThrough_HasNoReturn = diag::err_noreturn_has_return_expr;
746 D.diag_FallThrough_ReturnsNonVoid = diag::err_falloff_nonvoid;
747 D.FunKind = diag::FalloffFunctionKind::Block;
748 return D;
749 }
750
751 static CheckFallThroughDiagnostics MakeForLambda() {
752 CheckFallThroughDiagnostics D;
753 D.diag_FallThrough_HasNoReturn = diag::err_noreturn_has_return_expr;
754 D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
755 D.FunKind = diag::FalloffFunctionKind::Lambda;
756 return D;
757 }
758
759 bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid,
760 bool HasNoReturn) const {
761 if (FunKind == diag::FalloffFunctionKind::Function) {
762 return (ReturnsVoid ||
763 D.isIgnored(diag::warn_falloff_nonvoid, FuncLoc)) &&
764 (!HasNoReturn ||
765 D.isIgnored(diag::warn_noreturn_has_return_expr, FuncLoc)) &&
766 (!ReturnsVoid ||
767 D.isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
768 }
769 if (FunKind == diag::FalloffFunctionKind::Coroutine) {
770 return (ReturnsVoid ||
771 D.isIgnored(diag::warn_falloff_nonvoid, FuncLoc)) &&
772 (!HasNoReturn);
773 }
774 // For blocks / lambdas.
775 return ReturnsVoid && !HasNoReturn;
776 }
777};
778
779} // anonymous namespace
780
781/// CheckFallThroughForBody - Check that we don't fall off the end of a
782/// function that should return a value. Check that we don't fall off the end
783/// of a noreturn function. We assume that functions and blocks not marked
784/// noreturn will return.
785static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
786 QualType BlockType,
787 const CheckFallThroughDiagnostics &CD,
789
790 bool ReturnsVoid = false;
791 bool HasNoReturn = false;
792
793 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
794 if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
795 ReturnsVoid = CBody->getFallthroughHandler() != nullptr;
796 else
797 ReturnsVoid = FD->getReturnType()->isVoidType();
798 HasNoReturn = FD->isNoReturn() || FD->hasAttr<InferredNoReturnAttr>();
799 }
800 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
801 ReturnsVoid = MD->getReturnType()->isVoidType();
802 HasNoReturn = MD->hasAttr<NoReturnAttr>();
803 }
804 else if (isa<BlockDecl>(D)) {
805 if (const FunctionType *FT =
806 BlockType->getPointeeType()->getAs<FunctionType>()) {
807 if (FT->getReturnType()->isVoidType())
808 ReturnsVoid = true;
809 if (FT->getNoReturnAttr())
810 HasNoReturn = true;
811 }
812 }
813
815
816 // Short circuit for compilation speed.
817 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
818 return;
819 SourceLocation LBrace = Body->getBeginLoc(), RBrace = Body->getEndLoc();
820
821 // cpu_dispatch functions permit empty function bodies for ICC compatibility.
823 return;
824
825 // Either in a function body compound statement, or a function-try-block.
826 switch (int FallThroughType = CheckFallThrough(AC)) {
828 break;
829
830 case MaybeFallThrough:
832 if (HasNoReturn) {
833 if (CD.diag_FallThrough_HasNoReturn)
834 S.Diag(RBrace, CD.diag_FallThrough_HasNoReturn) << CD.FunKind;
835 } else if (!ReturnsVoid && CD.diag_FallThrough_ReturnsNonVoid) {
836 // If the final statement is a call to an always-throwing function,
837 // don't warn about the fall-through.
838 if (D->getAsFunction()) {
839 if (const auto *CS = dyn_cast<CompoundStmt>(Body);
840 CS && !CS->body_empty()) {
841 const Stmt *LastStmt = CS->body_back();
842 // Unwrap ExprWithCleanups if necessary.
843 if (const auto *EWC = dyn_cast<ExprWithCleanups>(LastStmt)) {
844 LastStmt = EWC->getSubExpr();
845 }
846 if (const auto *CE = dyn_cast<CallExpr>(LastStmt)) {
847 if (const FunctionDecl *Callee = CE->getDirectCallee();
848 Callee && Callee->hasAttr<InferredNoReturnAttr>()) {
849 return; // Don't warn about fall-through.
850 }
851 }
852 // Direct throw.
853 if (isa<CXXThrowExpr>(LastStmt)) {
854 return; // Don't warn about fall-through.
855 }
856 }
857 }
858 bool NotInAllControlPaths = FallThroughType == MaybeFallThrough;
859 S.Diag(RBrace, CD.diag_FallThrough_ReturnsNonVoid)
860 << CD.FunKind << NotInAllControlPaths;
861 }
862 break;
864 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
865 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
866 S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
867 } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
868 S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
869 } else {
870 S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
871 }
872 }
873 break;
874 case NeverFallThrough:
875 break;
876 }
877}
878
879//===----------------------------------------------------------------------===//
880// -Wuninitialized
881//===----------------------------------------------------------------------===//
882
883namespace {
884/// ContainsReference - A visitor class to search for references to
885/// a particular declaration (the needle) within any evaluated component of an
886/// expression (recursively).
887class ContainsReference : public ConstEvaluatedExprVisitor<ContainsReference> {
888 bool FoundReference;
889 const DeclRefExpr *Needle;
890
891public:
892 typedef ConstEvaluatedExprVisitor<ContainsReference> Inherited;
893
894 ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
895 : Inherited(Context), FoundReference(false), Needle(Needle) {}
896
897 void VisitExpr(const Expr *E) {
898 // Stop evaluating if we already have a reference.
899 if (FoundReference)
900 return;
901
902 Inherited::VisitExpr(E);
903 }
904
905 void VisitDeclRefExpr(const DeclRefExpr *E) {
906 if (E == Needle)
907 FoundReference = true;
908 else
910 }
911
912 bool doesContainReference() const { return FoundReference; }
913};
914} // anonymous namespace
915
916static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
917 QualType VariableTy = VD->getType().getCanonicalType();
918 if (VariableTy->isBlockPointerType() &&
919 !VD->hasAttr<BlocksAttr>()) {
920 S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization)
921 << VD->getDeclName()
922 << FixItHint::CreateInsertion(VD->getLocation(), "__block ");
923 return true;
924 }
925
926 // Don't issue a fixit if there is already an initializer.
927 if (VD->getInit())
928 return false;
929
930 // Don't suggest a fixit inside macros.
931 if (VD->getEndLoc().isMacroID())
932 return false;
933
935
936 // Suggest possible initialization (if any).
937 std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
938 if (Init.empty())
939 return false;
940
941 S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()
943 return true;
944}
945
946/// Create a fixit to remove an if-like statement, on the assumption that its
947/// condition is CondVal.
948static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then,
949 const Stmt *Else, bool CondVal,
950 FixItHint &Fixit1, FixItHint &Fixit2) {
951 if (CondVal) {
952 // If condition is always true, remove all but the 'then'.
954 CharSourceRange::getCharRange(If->getBeginLoc(), Then->getBeginLoc()));
955 if (Else) {
956 SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getEndLoc());
957 Fixit2 =
959 }
960 } else {
961 // If condition is always false, remove all but the 'else'.
962 if (Else)
964 If->getBeginLoc(), Else->getBeginLoc()));
965 else
966 Fixit1 = FixItHint::CreateRemoval(If->getSourceRange());
967 }
968}
969
970/// DiagUninitUse -- Helper function to produce a diagnostic for an
971/// uninitialized use of a variable.
972static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
973 bool IsCapturedByBlock) {
974 bool Diagnosed = false;
975
976 switch (Use.getKind()) {
978 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_var)
979 << VD->getDeclName() << IsCapturedByBlock
980 << Use.getUser()->getSourceRange();
981 return;
982
985 S.Diag(VD->getLocation(), diag::warn_sometimes_uninit_var)
986 << VD->getDeclName() << IsCapturedByBlock
987 << (Use.getKind() == UninitUse::AfterDecl ? 4 : 5)
988 << VD->getLexicalDeclContext() << VD->getSourceRange();
989 S.Diag(Use.getUser()->getBeginLoc(), diag::note_uninit_var_use)
990 << IsCapturedByBlock << Use.getUser()->getSourceRange();
991 return;
992
993 case UninitUse::Maybe:
995 // Carry on to report sometimes-uninitialized branches, if possible,
996 // or a 'may be used uninitialized' diagnostic otherwise.
997 break;
998 }
999
1000 // Diagnose each branch which leads to a sometimes-uninitialized use.
1001 for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end();
1002 I != E; ++I) {
1003 assert(Use.getKind() == UninitUse::Sometimes);
1004
1005 const Expr *User = Use.getUser();
1006 const Stmt *Term = I->Terminator;
1007
1008 // Information used when building the diagnostic.
1009 unsigned DiagKind;
1010 StringRef Str;
1011 SourceRange Range;
1012
1013 // FixIts to suppress the diagnostic by removing the dead condition.
1014 // For all binary terminators, branch 0 is taken if the condition is true,
1015 // and branch 1 is taken if the condition is false.
1016 int RemoveDiagKind = -1;
1017 const char *FixitStr =
1018 S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false")
1019 : (I->Output ? "1" : "0");
1020 FixItHint Fixit1, Fixit2;
1021
1022 switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) {
1023 default:
1024 // Don't know how to report this. Just fall back to 'may be used
1025 // uninitialized'. FIXME: Can this happen?
1026 continue;
1027
1028 // "condition is true / condition is false".
1029 case Stmt::IfStmtClass: {
1030 const IfStmt *IS = cast<IfStmt>(Term);
1031 DiagKind = 0;
1032 Str = "if";
1033 Range = IS->getCond()->getSourceRange();
1034 RemoveDiagKind = 0;
1035 CreateIfFixit(S, IS, IS->getThen(), IS->getElse(),
1036 I->Output, Fixit1, Fixit2);
1037 break;
1038 }
1039 case Stmt::ConditionalOperatorClass: {
1041 DiagKind = 0;
1042 Str = "?:";
1043 Range = CO->getCond()->getSourceRange();
1044 RemoveDiagKind = 0;
1045 CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(),
1046 I->Output, Fixit1, Fixit2);
1047 break;
1048 }
1049 case Stmt::BinaryOperatorClass: {
1050 const BinaryOperator *BO = cast<BinaryOperator>(Term);
1051 if (!BO->isLogicalOp())
1052 continue;
1053 DiagKind = 0;
1054 Str = BO->getOpcodeStr();
1055 Range = BO->getLHS()->getSourceRange();
1056 RemoveDiagKind = 0;
1057 if ((BO->getOpcode() == BO_LAnd && I->Output) ||
1058 (BO->getOpcode() == BO_LOr && !I->Output))
1059 // true && y -> y, false || y -> y.
1060 Fixit1 = FixItHint::CreateRemoval(
1061 SourceRange(BO->getBeginLoc(), BO->getOperatorLoc()));
1062 else
1063 // false && y -> false, true || y -> true.
1064 Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr);
1065 break;
1066 }
1067
1068 // "loop is entered / loop is exited".
1069 case Stmt::WhileStmtClass:
1070 DiagKind = 1;
1071 Str = "while";
1072 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
1073 RemoveDiagKind = 1;
1074 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
1075 break;
1076 case Stmt::ForStmtClass:
1077 DiagKind = 1;
1078 Str = "for";
1079 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
1080 RemoveDiagKind = 1;
1081 if (I->Output)
1082 Fixit1 = FixItHint::CreateRemoval(Range);
1083 else
1084 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
1085 break;
1086 case Stmt::CXXForRangeStmtClass:
1087 if (I->Output == 1) {
1088 // The use occurs if a range-based for loop's body never executes.
1089 // That may be impossible, and there's no syntactic fix for this,
1090 // so treat it as a 'may be uninitialized' case.
1091 continue;
1092 }
1093 DiagKind = 1;
1094 Str = "for";
1095 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
1096 break;
1097
1098 // "condition is true / loop is exited".
1099 case Stmt::DoStmtClass:
1100 DiagKind = 2;
1101 Str = "do";
1102 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
1103 RemoveDiagKind = 1;
1104 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
1105 break;
1106
1107 // "switch case is taken".
1108 case Stmt::CaseStmtClass:
1109 DiagKind = 3;
1110 Str = "case";
1111 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
1112 break;
1113 case Stmt::DefaultStmtClass:
1114 DiagKind = 3;
1115 Str = "default";
1116 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
1117 break;
1118 }
1119
1120 S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var)
1121 << VD->getDeclName() << IsCapturedByBlock << DiagKind
1122 << Str << I->Output << Range;
1123 S.Diag(User->getBeginLoc(), diag::note_uninit_var_use)
1124 << IsCapturedByBlock << User->getSourceRange();
1125 if (RemoveDiagKind != -1)
1126 S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond)
1127 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
1128
1129 Diagnosed = true;
1130 }
1131
1132 if (!Diagnosed)
1133 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_maybe_uninit_var)
1134 << VD->getDeclName() << IsCapturedByBlock
1135 << Use.getUser()->getSourceRange();
1136}
1137
1138/// Diagnose uninitialized const reference usages.
1140 const UninitUse &Use) {
1141 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_reference)
1142 << VD->getDeclName() << Use.getUser()->getSourceRange();
1144}
1145
1146/// Diagnose uninitialized const pointer usages.
1148 const UninitUse &Use) {
1149 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_pointer)
1150 << VD->getDeclName() << Use.getUser()->getSourceRange();
1152}
1153
1154/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
1155/// uninitialized variable. This manages the different forms of diagnostic
1156/// emitted for particular types of uses. Returns true if the use was diagnosed
1157/// as a warning. If a particular use is one we omit warnings for, returns
1158/// false.
1159static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
1160 const UninitUse &Use,
1161 bool alwaysReportSelfInit = false) {
1162 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) {
1163 // Inspect the initializer of the variable declaration which is
1164 // being referenced prior to its initialization. We emit
1165 // specialized diagnostics for self-initialization, and we
1166 // specifically avoid warning about self references which take the
1167 // form of:
1168 //
1169 // int x = x;
1170 //
1171 // This is used to indicate to GCC that 'x' is intentionally left
1172 // uninitialized. Proven code paths which access 'x' in
1173 // an uninitialized state after this will still warn.
1174 if (const Expr *Initializer = VD->getInit()) {
1175 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
1176 return false;
1177
1178 ContainsReference CR(S.Context, DRE);
1179 CR.Visit(Initializer);
1180 if (CR.doesContainReference()) {
1181 S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
1182 << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
1184 }
1185 }
1186
1187 DiagUninitUse(S, VD, Use, false);
1188 } else {
1189 const BlockExpr *BE = cast<BlockExpr>(Use.getUser());
1190 if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>())
1191 S.Diag(BE->getBeginLoc(),
1192 diag::warn_uninit_byref_blockvar_captured_by_block)
1193 << VD->getDeclName()
1195 else
1196 DiagUninitUse(S, VD, Use, true);
1197 }
1198
1199 // Report where the variable was declared when the use wasn't within
1200 // the initializer of that declaration & we didn't already suggest
1201 // an initialization fixit.
1202 if (!SuggestInitializationFixit(S, VD))
1203 S.Diag(VD->getBeginLoc(), diag::note_var_declared_here)
1204 << VD->getDeclName();
1205
1207}
1208
1209namespace {
1210class FallthroughMapper : public DynamicRecursiveASTVisitor {
1211public:
1212 FallthroughMapper(Sema &S) : FoundSwitchStatements(false), S(S) {
1213 ShouldWalkTypesOfTypeLocs = false;
1214 }
1215
1216 bool foundSwitchStatements() const { return FoundSwitchStatements; }
1217
1218 void markFallthroughVisited(const AttributedStmt *Stmt) {
1219 bool Found = FallthroughStmts.erase(Stmt);
1220 assert(Found);
1221 (void)Found;
1222 }
1223
1224 typedef llvm::SmallPtrSet<const AttributedStmt *, 8> AttrStmts;
1225
1226 const AttrStmts &getFallthroughStmts() const { return FallthroughStmts; }
1227
1228 void fillReachableBlocks(CFG *Cfg) {
1229 assert(ReachableBlocks.empty() && "ReachableBlocks already filled");
1230 std::deque<const CFGBlock *> BlockQueue;
1231
1232 ReachableBlocks.insert(&Cfg->getEntry());
1233 BlockQueue.push_back(&Cfg->getEntry());
1234 // Mark all case blocks reachable to avoid problems with switching on
1235 // constants, covered enums, etc.
1236 // These blocks can contain fall-through annotations, and we don't want to
1237 // issue a warn_fallthrough_attr_unreachable for them.
1238 for (const auto *B : *Cfg) {
1239 const Stmt *L = B->getLabel();
1240 if (isa_and_nonnull<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1241 BlockQueue.push_back(B);
1242 }
1243
1244 while (!BlockQueue.empty()) {
1245 const CFGBlock *P = BlockQueue.front();
1246 BlockQueue.pop_front();
1247 for (const CFGBlock *B : P->succs()) {
1248 if (B && ReachableBlocks.insert(B).second)
1249 BlockQueue.push_back(B);
1250 }
1251 }
1252 }
1253
1254 bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt,
1255 bool IsTemplateInstantiation) {
1256 assert(!ReachableBlocks.empty() && "ReachableBlocks empty");
1257
1258 int UnannotatedCnt = 0;
1259 AnnotatedCnt = 0;
1260
1261 std::deque<const CFGBlock *> BlockQueue(B.pred_begin(), B.pred_end());
1262 while (!BlockQueue.empty()) {
1263 const CFGBlock *P = BlockQueue.front();
1264 BlockQueue.pop_front();
1265 if (!P)
1266 continue;
1267
1268 const Stmt *Term = P->getTerminatorStmt();
1269 if (isa_and_nonnull<SwitchStmt>(Term))
1270 continue; // Switch statement, good.
1271
1272 const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel());
1273 if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end())
1274 continue; // Previous case label has no statements, good.
1275
1276 const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel());
1277 if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end())
1278 continue; // Case label is preceded with a normal label, good.
1279
1280 if (!ReachableBlocks.count(P)) {
1281 for (const CFGElement &Elem : llvm::reverse(*P)) {
1282 if (std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>()) {
1283 if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1284 // Don't issue a warning for an unreachable fallthrough
1285 // attribute in template instantiations as it may not be
1286 // unreachable in all instantiations of the template.
1287 if (!IsTemplateInstantiation)
1288 S.Diag(AS->getBeginLoc(),
1289 diag::warn_unreachable_fallthrough_attr);
1290 markFallthroughVisited(AS);
1291 ++AnnotatedCnt;
1292 break;
1293 }
1294 // Don't care about other unreachable statements.
1295 }
1296 }
1297 // If there are no unreachable statements, this may be a special
1298 // case in CFG:
1299 // case X: {
1300 // A a; // A has a destructor.
1301 // break;
1302 // }
1303 // // <<<< This place is represented by a 'hanging' CFG block.
1304 // case Y:
1305 continue;
1306 }
1307
1308 const Stmt *LastStmt = getLastStmt(*P);
1309 if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) {
1310 markFallthroughVisited(AS);
1311 ++AnnotatedCnt;
1312 continue; // Fallthrough annotation, good.
1313 }
1314
1315 if (!LastStmt) { // This block contains no executable statements.
1316 // Traverse its predecessors.
1317 std::copy(P->pred_begin(), P->pred_end(),
1318 std::back_inserter(BlockQueue));
1319 continue;
1320 }
1321
1322 ++UnannotatedCnt;
1323 }
1324 return !!UnannotatedCnt;
1325 }
1326
1327 bool VisitAttributedStmt(AttributedStmt *S) override {
1328 if (asFallThroughAttr(S))
1329 FallthroughStmts.insert(S);
1330 return true;
1331 }
1332
1333 bool VisitSwitchStmt(SwitchStmt *S) override {
1334 FoundSwitchStatements = true;
1335 return true;
1336 }
1337
1338 // We don't want to traverse local type declarations. We analyze their
1339 // methods separately.
1340 bool TraverseDecl(Decl *D) override { return true; }
1341
1342 // We analyze lambda bodies separately. Skip them here.
1343 bool TraverseLambdaExpr(LambdaExpr *LE) override {
1344 // Traverse the captures, but not the body.
1345 for (const auto C : zip(LE->captures(), LE->capture_inits()))
1346 TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
1347 return true;
1348 }
1349
1350 private:
1351
1352 static const AttributedStmt *asFallThroughAttr(const Stmt *S) {
1353 if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1354 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1355 return AS;
1356 }
1357 return nullptr;
1358 }
1359
1360 static const Stmt *getLastStmt(const CFGBlock &B) {
1361 if (const Stmt *Term = B.getTerminatorStmt())
1362 return Term;
1363 for (const CFGElement &Elem : llvm::reverse(B))
1364 if (std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>())
1365 return CS->getStmt();
1366 // Workaround to detect a statement thrown out by CFGBuilder:
1367 // case X: {} case Y:
1368 // case X: ; case Y:
1369 if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel()))
1370 if (!isa<SwitchCase>(SW->getSubStmt()))
1371 return SW->getSubStmt();
1372
1373 return nullptr;
1374 }
1375
1376 bool FoundSwitchStatements;
1377 AttrStmts FallthroughStmts;
1378 Sema &S;
1379 llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
1380};
1381} // anonymous namespace
1382
1384 SourceLocation Loc) {
1385 TokenValue FallthroughTokens[] = {
1386 tok::l_square, tok::l_square,
1387 PP.getIdentifierInfo("fallthrough"),
1388 tok::r_square, tok::r_square
1389 };
1390
1391 TokenValue ClangFallthroughTokens[] = {
1392 tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"),
1393 tok::coloncolon, PP.getIdentifierInfo("fallthrough"),
1394 tok::r_square, tok::r_square
1395 };
1396
1397 bool PreferClangAttr = !PP.getLangOpts().CPlusPlus17 && !PP.getLangOpts().C23;
1398
1399 StringRef MacroName;
1400 if (PreferClangAttr)
1401 MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);
1402 if (MacroName.empty())
1403 MacroName = PP.getLastMacroWithSpelling(Loc, FallthroughTokens);
1404 if (MacroName.empty() && !PreferClangAttr)
1405 MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);
1406 if (MacroName.empty()) {
1407 if (!PreferClangAttr)
1408 MacroName = "[[fallthrough]]";
1409 else if (PP.getLangOpts().CPlusPlus)
1410 MacroName = "[[clang::fallthrough]]";
1411 else
1412 MacroName = "__attribute__((fallthrough))";
1413 }
1414 return MacroName;
1415}
1416
1418 bool PerFunction) {
1419 FallthroughMapper FM(S);
1420 FM.TraverseStmt(AC.getBody());
1421
1422 if (!FM.foundSwitchStatements())
1423 return;
1424
1425 if (PerFunction && FM.getFallthroughStmts().empty())
1426 return;
1427
1428 CFG *Cfg = AC.getCFG();
1429
1430 if (!Cfg)
1431 return;
1432
1433 FM.fillReachableBlocks(Cfg);
1434
1435 for (const CFGBlock *B : llvm::reverse(*Cfg)) {
1436 const Stmt *Label = B->getLabel();
1437
1438 if (!isa_and_nonnull<SwitchCase>(Label))
1439 continue;
1440
1441 int AnnotatedCnt;
1442
1443 bool IsTemplateInstantiation = false;
1444 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(AC.getDecl()))
1445 IsTemplateInstantiation = Function->isTemplateInstantiation();
1446 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1447 IsTemplateInstantiation))
1448 continue;
1449
1450 S.Diag(Label->getBeginLoc(),
1451 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1452 : diag::warn_unannotated_fallthrough);
1453
1454 if (!AnnotatedCnt) {
1455 SourceLocation L = Label->getBeginLoc();
1456 if (L.isMacroID())
1457 continue;
1458
1459 const Stmt *Term = B->getTerminatorStmt();
1460 // Skip empty cases.
1461 while (B->empty() && !Term && B->succ_size() == 1) {
1462 B = *B->succ_begin();
1463 Term = B->getTerminatorStmt();
1464 }
1465 if (!(B->empty() && isa_and_nonnull<BreakStmt>(Term))) {
1466 Preprocessor &PP = S.getPreprocessor();
1467 StringRef AnnotationSpelling = getFallthroughAttrSpelling(PP, L);
1468 SmallString<64> TextToInsert(AnnotationSpelling);
1469 TextToInsert += "; ";
1470 S.Diag(L, diag::note_insert_fallthrough_fixit)
1471 << AnnotationSpelling
1472 << FixItHint::CreateInsertion(L, TextToInsert);
1473 }
1474 S.Diag(L, diag::note_insert_break_fixit)
1475 << FixItHint::CreateInsertion(L, "break; ");
1476 }
1477 }
1478
1479 for (const auto *F : FM.getFallthroughStmts())
1480 S.Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);
1481}
1482
1483static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
1484 const Stmt *S) {
1485 assert(S);
1486
1487 do {
1488 switch (S->getStmtClass()) {
1489 case Stmt::ForStmtClass:
1490 case Stmt::WhileStmtClass:
1491 case Stmt::CXXForRangeStmtClass:
1492 case Stmt::ObjCForCollectionStmtClass:
1493 return true;
1494 case Stmt::DoStmtClass: {
1495 Expr::EvalResult Result;
1496 if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))
1497 return true;
1498 return Result.Val.getInt().getBoolValue();
1499 }
1500 default:
1501 break;
1502 }
1503 } while ((S = PM.getParent(S)));
1504
1505 return false;
1506}
1507
1509 const sema::FunctionScopeInfo *CurFn,
1510 const Decl *D,
1511 const ParentMap &PM) {
1512 typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy;
1513 typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap;
1514 typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector;
1515 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1516 StmtUsesPair;
1517
1518 ASTContext &Ctx = S.getASTContext();
1519
1520 const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses();
1521
1522 // Extract all weak objects that are referenced more than once.
1524 for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
1525 I != E; ++I) {
1526 const WeakUseVector &Uses = I->second;
1527
1528 // Find the first read of the weak object.
1529 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1530 for ( ; UI != UE; ++UI) {
1531 if (UI->isUnsafe())
1532 break;
1533 }
1534
1535 // If there were only writes to this object, don't warn.
1536 if (UI == UE)
1537 continue;
1538
1539 // If there was only one read, followed by any number of writes, and the
1540 // read is not within a loop, don't warn. Additionally, don't warn in a
1541 // loop if the base object is a local variable -- local variables are often
1542 // changed in loops.
1543 if (UI == Uses.begin()) {
1544 WeakUseVector::const_iterator UI2 = UI;
1545 for (++UI2; UI2 != UE; ++UI2)
1546 if (UI2->isUnsafe())
1547 break;
1548
1549 if (UI2 == UE) {
1550 if (!isInLoop(Ctx, PM, UI->getUseExpr()))
1551 continue;
1552
1553 const WeakObjectProfileTy &Profile = I->first;
1554 if (!Profile.isExactProfile())
1555 continue;
1556
1557 const NamedDecl *Base = Profile.getBase();
1558 if (!Base)
1559 Base = Profile.getProperty();
1560 assert(Base && "A profile always has a base or property.");
1561
1562 if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1563 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1564 continue;
1565 }
1566 }
1567
1568 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
1569 }
1570
1571 if (UsesByStmt.empty())
1572 return;
1573
1574 // Sort by first use so that we emit the warnings in a deterministic order.
1576 llvm::sort(UsesByStmt,
1577 [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
1578 return SM.isBeforeInTranslationUnit(LHS.first->getBeginLoc(),
1579 RHS.first->getBeginLoc());
1580 });
1581
1582 // Classify the current code body for better warning text.
1583 // This enum should stay in sync with the cases in
1584 // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
1585 // FIXME: Should we use a common classification enum and the same set of
1586 // possibilities all throughout Sema?
1587 enum {
1588 Function,
1589 Method,
1590 Block,
1591 Lambda
1592 } FunctionKind;
1593
1594 if (isa<sema::BlockScopeInfo>(CurFn))
1595 FunctionKind = Block;
1596 else if (isa<sema::LambdaScopeInfo>(CurFn))
1597 FunctionKind = Lambda;
1598 else if (isa<ObjCMethodDecl>(D))
1599 FunctionKind = Method;
1600 else
1601 FunctionKind = Function;
1602
1603 // Iterate through the sorted problems and emit warnings for each.
1604 for (const auto &P : UsesByStmt) {
1605 const Stmt *FirstRead = P.first;
1606 const WeakObjectProfileTy &Key = P.second->first;
1607 const WeakUseVector &Uses = P.second->second;
1608
1609 // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy
1610 // may not contain enough information to determine that these are different
1611 // properties. We can only be 100% sure of a repeated use in certain cases,
1612 // and we adjust the diagnostic kind accordingly so that the less certain
1613 // case can be turned off if it is too noisy.
1614 unsigned DiagKind;
1615 if (Key.isExactProfile())
1616 DiagKind = diag::warn_arc_repeated_use_of_weak;
1617 else
1618 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1619
1620 // Classify the weak object being accessed for better warning text.
1621 // This enum should stay in sync with the cases in
1622 // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
1623 enum {
1624 Variable,
1625 Property,
1626 ImplicitProperty,
1627 Ivar
1628 } ObjectKind;
1629
1630 const NamedDecl *KeyProp = Key.getProperty();
1631 if (isa<VarDecl>(KeyProp))
1632 ObjectKind = Variable;
1633 else if (isa<ObjCPropertyDecl>(KeyProp))
1634 ObjectKind = Property;
1635 else if (isa<ObjCMethodDecl>(KeyProp))
1636 ObjectKind = ImplicitProperty;
1637 else if (isa<ObjCIvarDecl>(KeyProp))
1638 ObjectKind = Ivar;
1639 else
1640 llvm_unreachable("Unexpected weak object kind!");
1641
1642 // Do not warn about IBOutlet weak property receivers being set to null
1643 // since they are typically only used from the main thread.
1644 if (const ObjCPropertyDecl *Prop = dyn_cast<ObjCPropertyDecl>(KeyProp))
1645 if (Prop->hasAttr<IBOutletAttr>())
1646 continue;
1647
1648 // Show the first time the object was read.
1649 S.Diag(FirstRead->getBeginLoc(), DiagKind)
1650 << int(ObjectKind) << KeyProp << int(FunctionKind)
1651 << FirstRead->getSourceRange();
1652
1653 // Print all the other accesses as notes.
1654 for (const auto &Use : Uses) {
1655 if (Use.getUseExpr() == FirstRead)
1656 continue;
1657 S.Diag(Use.getUseExpr()->getBeginLoc(),
1658 diag::note_arc_weak_also_accessed_here)
1659 << Use.getUseExpr()->getSourceRange();
1660 }
1661 }
1662}
1663
1664namespace clang {
1665namespace {
1667typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
1668typedef std::list<DelayedDiag> DiagList;
1669
1670struct SortDiagBySourceLocation {
1671 SourceManager &SM;
1672 SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}
1673
1674 bool operator()(const DelayedDiag &left, const DelayedDiag &right) {
1675 // Although this call will be slow, this is only called when outputting
1676 // multiple warnings.
1677 return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
1678 }
1679};
1680} // anonymous namespace
1681} // namespace clang
1682
1683namespace {
1684class UninitValsDiagReporter : public UninitVariablesHandler {
1685 Sema &S;
1686 typedef SmallVector<UninitUse, 2> UsesVec;
1687 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1688 // Prefer using MapVector to DenseMap, so that iteration order will be
1689 // the same as insertion order. This is needed to obtain a deterministic
1690 // order of diagnostics when calling flushDiagnostics().
1691 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1692 UsesMap uses;
1693
1694public:
1695 UninitValsDiagReporter(Sema &S) : S(S) {}
1696 ~UninitValsDiagReporter() override { flushDiagnostics(); }
1697
1698 MappedType &getUses(const VarDecl *vd) {
1699 MappedType &V = uses[vd];
1700 if (!V.getPointer())
1701 V.setPointer(new UsesVec());
1702 return V;
1703 }
1704
1705 void handleUseOfUninitVariable(const VarDecl *vd,
1706 const UninitUse &use) override {
1707 getUses(vd).getPointer()->push_back(use);
1708 }
1709
1710 void handleSelfInit(const VarDecl *vd) override { getUses(vd).setInt(true); }
1711
1712 void flushDiagnostics() {
1713 for (const auto &P : uses) {
1714 const VarDecl *vd = P.first;
1715 const MappedType &V = P.second;
1716
1717 UsesVec *vec = V.getPointer();
1718 bool hasSelfInit = V.getInt();
1719
1720 diagnoseUnitializedVar(vd, hasSelfInit, vec);
1721
1722 // Release the uses vector.
1723 delete vec;
1724 }
1725
1726 uses.clear();
1727 }
1728
1729private:
1730 static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
1731 return llvm::any_of(*vec, [](const UninitUse &U) {
1732 return U.getKind() == UninitUse::Always ||
1735 });
1736 }
1737
1738 // Print the diagnostic for the variable. We try to warn only on the first
1739 // point at which a variable is used uninitialized. After the first
1740 // diagnostic is printed, further diagnostics for this variable are skipped.
1741 void diagnoseUnitializedVar(const VarDecl *vd, bool hasSelfInit,
1742 UsesVec *vec) {
1743 // Specially handle the case where we have uses of an uninitialized
1744 // variable, but the root cause is an idiomatic self-init. We want
1745 // to report the diagnostic at the self-init since that is the root cause.
1746 if (hasSelfInit && hasAlwaysUninitializedUse(vec)) {
1747 if (DiagnoseUninitializedUse(S, vd,
1748 UninitUse(vd->getInit()->IgnoreParenCasts(),
1749 /*isAlwaysUninit=*/true),
1750 /*alwaysReportSelfInit=*/true))
1751 return;
1752 }
1753
1754 // Sort the uses by their SourceLocations. While not strictly
1755 // guaranteed to produce them in line/column order, this will provide
1756 // a stable ordering.
1757 llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {
1758 // Prefer the direct use of an uninitialized variable over its use via
1759 // constant reference or pointer.
1760 if (a.isConstRefOrPtrUse() != b.isConstRefOrPtrUse())
1761 return b.isConstRefOrPtrUse();
1762 // Prefer a more confident report over a less confident one.
1763 if (a.getKind() != b.getKind())
1764 return a.getKind() > b.getKind();
1765 return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();
1766 });
1767
1768 for (const auto &U : *vec) {
1769 if (U.isConstRefUse()) {
1771 return;
1772 } else if (U.isConstPtrUse()) {
1774 return;
1775 } else {
1776 // If we have self-init, downgrade all uses to 'may be uninitialized'.
1777 UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
1778 if (DiagnoseUninitializedUse(S, vd, Use))
1779 return;
1780 }
1781 }
1782 }
1783};
1784
1785/// Inter-procedural data for the called-once checker.
1786class CalledOnceInterProceduralData {
1787public:
1788 // Add the delayed warning for the given block.
1789 void addDelayedWarning(const BlockDecl *Block,
1791 DelayedBlockWarnings[Block].emplace_back(std::move(Warning));
1792 }
1793 // Report all of the warnings we've gathered for the given block.
1794 void flushWarnings(const BlockDecl *Block, Sema &S) {
1795 for (const PartialDiagnosticAt &Delayed : DelayedBlockWarnings[Block])
1796 S.Diag(Delayed.first, Delayed.second);
1797
1798 discardWarnings(Block);
1799 }
1800 // Discard all of the warnings we've gathered for the given block.
1801 void discardWarnings(const BlockDecl *Block) {
1802 DelayedBlockWarnings.erase(Block);
1803 }
1804
1805private:
1806 using DelayedDiagnostics = SmallVector<PartialDiagnosticAt, 2>;
1807 llvm::DenseMap<const BlockDecl *, DelayedDiagnostics> DelayedBlockWarnings;
1808};
1809
1810class CalledOnceCheckReporter : public CalledOnceCheckHandler {
1811public:
1812 CalledOnceCheckReporter(Sema &S, CalledOnceInterProceduralData &Data)
1813 : S(S), Data(Data) {}
1814 void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call,
1815 const Expr *PrevCall, bool IsCompletionHandler,
1816 bool Poised) override {
1817 auto DiagToReport = IsCompletionHandler
1818 ? diag::warn_completion_handler_called_twice
1819 : diag::warn_called_once_gets_called_twice;
1820 S.Diag(Call->getBeginLoc(), DiagToReport) << Parameter;
1821 S.Diag(PrevCall->getBeginLoc(), diag::note_called_once_gets_called_twice)
1822 << Poised;
1823 }
1824
1825 void handleNeverCalled(const ParmVarDecl *Parameter,
1826 bool IsCompletionHandler) override {
1827 auto DiagToReport = IsCompletionHandler
1828 ? diag::warn_completion_handler_never_called
1829 : diag::warn_called_once_never_called;
1830 S.Diag(Parameter->getBeginLoc(), DiagToReport)
1831 << Parameter << /* Captured */ false;
1832 }
1833
1834 void handleNeverCalled(const ParmVarDecl *Parameter, const Decl *Function,
1835 const Stmt *Where, NeverCalledReason Reason,
1836 bool IsCalledDirectly,
1837 bool IsCompletionHandler) override {
1838 auto DiagToReport = IsCompletionHandler
1839 ? diag::warn_completion_handler_never_called_when
1840 : diag::warn_called_once_never_called_when;
1841 PartialDiagnosticAt Warning(Where->getBeginLoc(), S.PDiag(DiagToReport)
1842 << Parameter
1843 << IsCalledDirectly
1844 << (unsigned)Reason);
1845
1846 if (const auto *Block = dyn_cast<BlockDecl>(Function)) {
1847 // We shouldn't report these warnings on blocks immediately
1848 Data.addDelayedWarning(Block, std::move(Warning));
1849 } else {
1850 S.Diag(Warning.first, Warning.second);
1851 }
1852 }
1853
1854 void handleCapturedNeverCalled(const ParmVarDecl *Parameter,
1855 const Decl *Where,
1856 bool IsCompletionHandler) override {
1857 auto DiagToReport = IsCompletionHandler
1858 ? diag::warn_completion_handler_never_called
1859 : diag::warn_called_once_never_called;
1860 S.Diag(Where->getBeginLoc(), DiagToReport)
1861 << Parameter << /* Captured */ true;
1862 }
1863
1864 void
1865 handleBlockThatIsGuaranteedToBeCalledOnce(const BlockDecl *Block) override {
1866 Data.flushWarnings(Block, S);
1867 }
1868
1869 void handleBlockWithNoGuarantees(const BlockDecl *Block) override {
1870 Data.discardWarnings(Block);
1871 }
1872
1873private:
1874 Sema &S;
1875 CalledOnceInterProceduralData &Data;
1876};
1877
1878constexpr unsigned CalledOnceWarnings[] = {
1879 diag::warn_called_once_never_called,
1880 diag::warn_called_once_never_called_when,
1881 diag::warn_called_once_gets_called_twice};
1882
1883constexpr unsigned CompletionHandlerWarnings[]{
1884 diag::warn_completion_handler_never_called,
1885 diag::warn_completion_handler_never_called_when,
1886 diag::warn_completion_handler_called_twice};
1887
1888bool shouldAnalyzeCalledOnceImpl(llvm::ArrayRef<unsigned> DiagIDs,
1889 const DiagnosticsEngine &Diags,
1890 SourceLocation At) {
1891 return llvm::any_of(DiagIDs, [&Diags, At](unsigned DiagID) {
1892 return !Diags.isIgnored(DiagID, At);
1893 });
1894}
1895
1896bool shouldAnalyzeCalledOnceConventions(const DiagnosticsEngine &Diags,
1897 SourceLocation At) {
1898 return shouldAnalyzeCalledOnceImpl(CompletionHandlerWarnings, Diags, At);
1899}
1900
1901bool shouldAnalyzeCalledOnceParameters(const DiagnosticsEngine &Diags,
1902 SourceLocation At) {
1903 return shouldAnalyzeCalledOnceImpl(CalledOnceWarnings, Diags, At) ||
1904 shouldAnalyzeCalledOnceConventions(Diags, At);
1905}
1906} // anonymous namespace
1907
1908//===----------------------------------------------------------------------===//
1909// -Wthread-safety
1910//===----------------------------------------------------------------------===//
1911namespace clang {
1912namespace threadSafety {
1913namespace {
1914class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
1915 Sema &S;
1916 DiagList Warnings;
1917 SourceLocation FunLocation, FunEndLocation;
1918
1919 const FunctionDecl *CurrentFunction;
1920 bool Verbose;
1921
1922 OptionalNotes getNotes() const {
1923 if (Verbose && CurrentFunction) {
1924 PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
1925 S.PDiag(diag::note_thread_warning_in_fun)
1926 << CurrentFunction);
1927 return OptionalNotes(1, FNote);
1928 }
1929 return OptionalNotes();
1930 }
1931
1932 OptionalNotes getNotes(const PartialDiagnosticAt &Note) const {
1933 OptionalNotes ONS(1, Note);
1934 if (Verbose && CurrentFunction) {
1935 PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
1936 S.PDiag(diag::note_thread_warning_in_fun)
1937 << CurrentFunction);
1938 ONS.push_back(std::move(FNote));
1939 }
1940 return ONS;
1941 }
1942
1943 OptionalNotes getNotes(const PartialDiagnosticAt &Note1,
1944 const PartialDiagnosticAt &Note2) const {
1945 OptionalNotes ONS;
1946 ONS.push_back(Note1);
1947 ONS.push_back(Note2);
1948 if (Verbose && CurrentFunction) {
1949 PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
1950 S.PDiag(diag::note_thread_warning_in_fun)
1951 << CurrentFunction);
1952 ONS.push_back(std::move(FNote));
1953 }
1954 return ONS;
1955 }
1956
1957 OptionalNotes makeLockedHereNote(SourceLocation LocLocked, StringRef Kind) {
1958 return LocLocked.isValid()
1959 ? getNotes(PartialDiagnosticAt(
1960 LocLocked, S.PDiag(diag::note_locked_here) << Kind))
1961 : getNotes();
1962 }
1963
1964 OptionalNotes makeUnlockedHereNote(SourceLocation LocUnlocked,
1965 StringRef Kind) {
1966 return LocUnlocked.isValid()
1967 ? getNotes(PartialDiagnosticAt(
1968 LocUnlocked, S.PDiag(diag::note_unlocked_here) << Kind))
1969 : getNotes();
1970 }
1971
1972 OptionalNotes makeManagedMismatchNoteForParam(SourceLocation DeclLoc) {
1973 return DeclLoc.isValid()
1974 ? getNotes(PartialDiagnosticAt(
1975 DeclLoc,
1976 S.PDiag(diag::note_managed_mismatch_here_for_param)))
1977 : getNotes();
1978 }
1979
1980 public:
1981 ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL)
1982 : S(S), FunLocation(FL), FunEndLocation(FEL),
1983 CurrentFunction(nullptr), Verbose(false) {}
1984
1985 void setVerbose(bool b) { Verbose = b; }
1986
1987 /// Emit all buffered diagnostics in order of sourcelocation.
1988 /// We need to output diagnostics produced while iterating through
1989 /// the lockset in deterministic order, so this function orders diagnostics
1990 /// and outputs them.
1991 void emitDiagnostics() {
1992 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
1993 for (const auto &Diag : Warnings) {
1994 S.Diag(Diag.first.first, Diag.first.second);
1995 for (const auto &Note : Diag.second)
1996 S.Diag(Note.first, Note.second);
1997 }
1998 }
1999
2000 void handleUnmatchedUnderlyingMutexes(SourceLocation Loc, SourceLocation DLoc,
2001 Name scopeName, StringRef Kind,
2002 Name expected, Name actual) override {
2004 S.PDiag(diag::warn_unmatched_underlying_mutexes)
2005 << Kind << scopeName << expected << actual);
2006 Warnings.emplace_back(std::move(Warning),
2007 makeManagedMismatchNoteForParam(DLoc));
2008 }
2009
2010 void handleExpectMoreUnderlyingMutexes(SourceLocation Loc,
2011 SourceLocation DLoc, Name scopeName,
2012 StringRef Kind,
2013 Name expected) override {
2015 Loc, S.PDiag(diag::warn_expect_more_underlying_mutexes)
2016 << Kind << scopeName << expected);
2017 Warnings.emplace_back(std::move(Warning),
2018 makeManagedMismatchNoteForParam(DLoc));
2019 }
2020
2021 void handleExpectFewerUnderlyingMutexes(SourceLocation Loc,
2022 SourceLocation DLoc, Name scopeName,
2023 StringRef Kind,
2024 Name actual) override {
2026 Loc, S.PDiag(diag::warn_expect_fewer_underlying_mutexes)
2027 << Kind << scopeName << actual);
2028 Warnings.emplace_back(std::move(Warning),
2029 makeManagedMismatchNoteForParam(DLoc));
2030 }
2031
2032 void handleInvalidLockExp(SourceLocation Loc) override {
2033 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock)
2034 << Loc);
2035 Warnings.emplace_back(std::move(Warning), getNotes());
2036 }
2037
2038 void handleUnmatchedUnlock(StringRef Kind, Name LockName, SourceLocation Loc,
2039 SourceLocation LocPreviousUnlock) override {
2040 if (Loc.isInvalid())
2041 Loc = FunLocation;
2042 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_but_no_lock)
2043 << Kind << LockName);
2044 Warnings.emplace_back(std::move(Warning),
2045 makeUnlockedHereNote(LocPreviousUnlock, Kind));
2046 }
2047
2048 void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
2049 LockKind Expected, LockKind Received,
2050 SourceLocation LocLocked,
2051 SourceLocation LocUnlock) override {
2052 if (LocUnlock.isInvalid())
2053 LocUnlock = FunLocation;
2055 LocUnlock, S.PDiag(diag::warn_unlock_kind_mismatch)
2056 << Kind << LockName << Received << Expected);
2057 Warnings.emplace_back(std::move(Warning),
2058 makeLockedHereNote(LocLocked, Kind));
2059 }
2060
2061 void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation LocLocked,
2062 SourceLocation LocDoubleLock) override {
2063 if (LocDoubleLock.isInvalid())
2064 LocDoubleLock = FunLocation;
2065 PartialDiagnosticAt Warning(LocDoubleLock, S.PDiag(diag::warn_double_lock)
2066 << Kind << LockName);
2067 Warnings.emplace_back(std::move(Warning),
2068 makeLockedHereNote(LocLocked, Kind));
2069 }
2070
2071 void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
2072 SourceLocation LocLocked,
2073 SourceLocation LocEndOfScope,
2074 LockErrorKind LEK,
2075 bool ReentrancyMismatch) override {
2076 unsigned DiagID = 0;
2077 switch (LEK) {
2079 DiagID = diag::warn_lock_some_predecessors;
2080 break;
2082 DiagID = diag::warn_expecting_lock_held_on_loop;
2083 break;
2085 DiagID = diag::warn_no_unlock;
2086 break;
2088 DiagID = diag::warn_expecting_locked;
2089 break;
2090 }
2091 if (LocEndOfScope.isInvalid())
2092 LocEndOfScope = FunEndLocation;
2093
2094 PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID)
2095 << Kind << LockName
2096 << ReentrancyMismatch);
2097 Warnings.emplace_back(std::move(Warning),
2098 makeLockedHereNote(LocLocked, Kind));
2099 }
2100
2101 void handleExclusiveAndShared(StringRef Kind, Name LockName,
2102 SourceLocation Loc1,
2103 SourceLocation Loc2) override {
2105 S.PDiag(diag::warn_lock_exclusive_and_shared)
2106 << Kind << LockName);
2107 PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared)
2108 << Kind << LockName);
2109 Warnings.emplace_back(std::move(Warning), getNotes(Note));
2110 }
2111
2112 void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
2113 AccessKind AK, SourceLocation Loc) override {
2114 unsigned DiagID = 0;
2115 switch (POK) {
2116 case POK_VarAccess:
2117 case POK_PassByRef:
2118 case POK_ReturnByRef:
2119 case POK_PassPointer:
2120 case POK_ReturnPointer:
2121 DiagID = diag::warn_variable_requires_any_lock;
2122 break;
2123 case POK_VarDereference:
2124 case POK_PtPassByRef:
2125 case POK_PtReturnByRef:
2126 case POK_PtPassPointer:
2128 DiagID = diag::warn_var_deref_requires_any_lock;
2129 break;
2130 case POK_FunctionCall:
2131 llvm_unreachable("Only works for variables");
2132 break;
2133 }
2134 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
2135 << D << getLockKindFromAccessKind(AK));
2136 Warnings.emplace_back(std::move(Warning), getNotes());
2137 }
2138
2139 void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
2140 ProtectedOperationKind POK, Name LockName,
2141 LockKind LK, SourceLocation Loc,
2142 Name *PossibleMatch) override {
2143 unsigned DiagID = 0;
2144 if (PossibleMatch) {
2145 switch (POK) {
2146 case POK_VarAccess:
2147 DiagID = diag::warn_variable_requires_lock_precise;
2148 break;
2149 case POK_VarDereference:
2150 DiagID = diag::warn_var_deref_requires_lock_precise;
2151 break;
2152 case POK_FunctionCall:
2153 DiagID = diag::warn_fun_requires_lock_precise;
2154 break;
2155 case POK_PassByRef:
2156 DiagID = diag::warn_guarded_pass_by_reference;
2157 break;
2158 case POK_PtPassByRef:
2159 DiagID = diag::warn_pt_guarded_pass_by_reference;
2160 break;
2161 case POK_ReturnByRef:
2162 DiagID = diag::warn_guarded_return_by_reference;
2163 break;
2164 case POK_PtReturnByRef:
2165 DiagID = diag::warn_pt_guarded_return_by_reference;
2166 break;
2167 case POK_PassPointer:
2168 DiagID = diag::warn_guarded_pass_pointer;
2169 break;
2170 case POK_PtPassPointer:
2171 DiagID = diag::warn_pt_guarded_pass_pointer;
2172 break;
2173 case POK_ReturnPointer:
2174 DiagID = diag::warn_guarded_return_pointer;
2175 break;
2177 DiagID = diag::warn_pt_guarded_return_pointer;
2178 break;
2179 }
2180 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
2181 << D
2182 << LockName << LK);
2183 PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
2184 << *PossibleMatch);
2185 if (Verbose && POK == POK_VarAccess) {
2187 S.PDiag(diag::note_guarded_by_declared_here)
2188 << D->getDeclName());
2189 Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote));
2190 } else
2191 Warnings.emplace_back(std::move(Warning), getNotes(Note));
2192 } else {
2193 switch (POK) {
2194 case POK_VarAccess:
2195 DiagID = diag::warn_variable_requires_lock;
2196 break;
2197 case POK_VarDereference:
2198 DiagID = diag::warn_var_deref_requires_lock;
2199 break;
2200 case POK_FunctionCall:
2201 DiagID = diag::warn_fun_requires_lock;
2202 break;
2203 case POK_PassByRef:
2204 DiagID = diag::warn_guarded_pass_by_reference;
2205 break;
2206 case POK_PtPassByRef:
2207 DiagID = diag::warn_pt_guarded_pass_by_reference;
2208 break;
2209 case POK_ReturnByRef:
2210 DiagID = diag::warn_guarded_return_by_reference;
2211 break;
2212 case POK_PtReturnByRef:
2213 DiagID = diag::warn_pt_guarded_return_by_reference;
2214 break;
2215 case POK_PassPointer:
2216 DiagID = diag::warn_guarded_pass_pointer;
2217 break;
2218 case POK_PtPassPointer:
2219 DiagID = diag::warn_pt_guarded_pass_pointer;
2220 break;
2221 case POK_ReturnPointer:
2222 DiagID = diag::warn_guarded_return_pointer;
2223 break;
2225 DiagID = diag::warn_pt_guarded_return_pointer;
2226 break;
2227 }
2228 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
2229 << D
2230 << LockName << LK);
2231 if (Verbose && POK == POK_VarAccess) {
2233 S.PDiag(diag::note_guarded_by_declared_here));
2234 Warnings.emplace_back(std::move(Warning), getNotes(Note));
2235 } else
2236 Warnings.emplace_back(std::move(Warning), getNotes());
2237 }
2238 }
2239
2240 void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
2241 SourceLocation Loc) override {
2243 S.PDiag(diag::warn_acquire_requires_negative_cap)
2244 << Kind << LockName << Neg);
2245 Warnings.emplace_back(std::move(Warning), getNotes());
2246 }
2247
2248 void handleNegativeNotHeld(const NamedDecl *D, Name LockName,
2249 SourceLocation Loc) override {
2251 Loc, S.PDiag(diag::warn_fun_requires_negative_cap) << D << LockName);
2252 Warnings.emplace_back(std::move(Warning), getNotes());
2253 }
2254
2255 void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
2256 SourceLocation Loc) override {
2257 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
2258 << Kind << FunName << LockName);
2259 Warnings.emplace_back(std::move(Warning), getNotes());
2260 }
2261
2262 void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
2263 SourceLocation Loc) override {
2265 S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
2266 Warnings.emplace_back(std::move(Warning), getNotes());
2267 }
2268
2269 void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override {
2271 S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
2272 Warnings.emplace_back(std::move(Warning), getNotes());
2273 }
2274
2275 void enterFunction(const FunctionDecl* FD) override {
2276 CurrentFunction = FD;
2277 }
2278
2279 void leaveFunction(const FunctionDecl* FD) override {
2280 CurrentFunction = nullptr;
2281 }
2282};
2283} // anonymous namespace
2284} // namespace threadSafety
2285} // namespace clang
2286
2287//===----------------------------------------------------------------------===//
2288// -Wconsumed
2289//===----------------------------------------------------------------------===//
2290
2291namespace clang {
2292namespace consumed {
2293namespace {
2294class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase {
2295
2296 Sema &S;
2297 DiagList Warnings;
2298
2299public:
2300
2301 ConsumedWarningsHandler(Sema &S) : S(S) {}
2302
2303 void emitDiagnostics() override {
2304 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
2305 for (const auto &Diag : Warnings) {
2306 S.Diag(Diag.first.first, Diag.first.second);
2307 for (const auto &Note : Diag.second)
2308 S.Diag(Note.first, Note.second);
2309 }
2310 }
2311
2312 void warnLoopStateMismatch(SourceLocation Loc,
2313 StringRef VariableName) override {
2314 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) <<
2315 VariableName);
2316
2317 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2318 }
2319
2320 void warnParamReturnTypestateMismatch(SourceLocation Loc,
2321 StringRef VariableName,
2322 StringRef ExpectedState,
2323 StringRef ObservedState) override {
2324
2325 PartialDiagnosticAt Warning(Loc, S.PDiag(
2326 diag::warn_param_return_typestate_mismatch) << VariableName <<
2327 ExpectedState << ObservedState);
2328
2329 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2330 }
2331
2332 void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
2333 StringRef ObservedState) override {
2334
2335 PartialDiagnosticAt Warning(Loc, S.PDiag(
2336 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
2337
2338 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2339 }
2340
2341 void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
2342 StringRef TypeName) override {
2343 PartialDiagnosticAt Warning(Loc, S.PDiag(
2344 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
2345
2346 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2347 }
2348
2349 void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
2350 StringRef ObservedState) override {
2351
2352 PartialDiagnosticAt Warning(Loc, S.PDiag(
2353 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
2354
2355 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2356 }
2357
2358 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
2359 SourceLocation Loc) override {
2360
2361 PartialDiagnosticAt Warning(Loc, S.PDiag(
2362 diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
2363
2364 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2365 }
2366
2367 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
2368 StringRef State, SourceLocation Loc) override {
2369
2370 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
2371 MethodName << VariableName << State);
2372
2373 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2374 }
2375};
2376} // anonymous namespace
2377} // namespace consumed
2378} // namespace clang
2379
2380//===----------------------------------------------------------------------===//
2381// Unsafe buffer usage analysis.
2382//===----------------------------------------------------------------------===//
2383
2384namespace {
2385class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler {
2386 Sema &S;
2387 bool SuggestSuggestions; // Recommend -fsafe-buffer-usage-suggestions?
2388
2389 // Lists as a string the names of variables in `VarGroupForVD` except for `VD`
2390 // itself:
2391 std::string listVariableGroupAsString(
2392 const VarDecl *VD, const ArrayRef<const VarDecl *> &VarGroupForVD) const {
2393 if (VarGroupForVD.size() <= 1)
2394 return "";
2395
2396 std::vector<StringRef> VarNames;
2397 auto PutInQuotes = [](StringRef S) -> std::string {
2398 return "'" + S.str() + "'";
2399 };
2400
2401 for (auto *V : VarGroupForVD) {
2402 if (V == VD)
2403 continue;
2404 VarNames.push_back(V->getName());
2405 }
2406 if (VarNames.size() == 1) {
2407 return PutInQuotes(VarNames[0]);
2408 }
2409 if (VarNames.size() == 2) {
2410 return PutInQuotes(VarNames[0]) + " and " + PutInQuotes(VarNames[1]);
2411 }
2412 assert(VarGroupForVD.size() > 3);
2413 const unsigned N = VarNames.size() -
2414 2; // need to print the last two names as "..., X, and Y"
2415 std::string AllVars = "";
2416
2417 for (unsigned I = 0; I < N; ++I)
2418 AllVars.append(PutInQuotes(VarNames[I]) + ", ");
2419 AllVars.append(PutInQuotes(VarNames[N]) + ", and " +
2420 PutInQuotes(VarNames[N + 1]));
2421 return AllVars;
2422 }
2423
2424public:
2425 UnsafeBufferUsageReporter(Sema &S, bool SuggestSuggestions)
2426 : S(S), SuggestSuggestions(SuggestSuggestions) {}
2427
2428 void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl,
2429 ASTContext &Ctx) override {
2430 SourceLocation Loc;
2431 SourceRange Range;
2432 unsigned MsgParam = 0;
2433 NamedDecl *D = nullptr;
2434 if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Operation)) {
2435 Loc = ASE->getBase()->getExprLoc();
2436 Range = ASE->getBase()->getSourceRange();
2437 MsgParam = 2;
2438 } else if (const auto *BO = dyn_cast<BinaryOperator>(Operation)) {
2440 if (Op == BO_Add || Op == BO_AddAssign || Op == BO_Sub ||
2441 Op == BO_SubAssign) {
2442 if (BO->getRHS()->getType()->isIntegerType()) {
2443 Loc = BO->getLHS()->getExprLoc();
2444 Range = BO->getLHS()->getSourceRange();
2445 } else {
2446 Loc = BO->getRHS()->getExprLoc();
2447 Range = BO->getRHS()->getSourceRange();
2448 }
2449 MsgParam = 1;
2450 }
2451 } else if (const auto *UO = dyn_cast<UnaryOperator>(Operation)) {
2453 if (Op == UO_PreInc || Op == UO_PreDec || Op == UO_PostInc ||
2454 Op == UO_PostDec) {
2455 Loc = UO->getSubExpr()->getExprLoc();
2456 Range = UO->getSubExpr()->getSourceRange();
2457 MsgParam = 1;
2458 }
2459 } else {
2460 if (isa<CallExpr>(Operation) || isa<CXXConstructExpr>(Operation)) {
2461 // note_unsafe_buffer_operation doesn't have this mode yet.
2462 assert(!IsRelatedToDecl && "Not implemented yet!");
2463 MsgParam = 3;
2464 } else if (isa<MemberExpr>(Operation)) {
2465 // note_unsafe_buffer_operation doesn't have this mode yet.
2466 assert(!IsRelatedToDecl && "Not implemented yet!");
2467 auto *ME = cast<MemberExpr>(Operation);
2468 D = ME->getMemberDecl();
2469 MsgParam = 5;
2470 } else if (const auto *ECE = dyn_cast<ExplicitCastExpr>(Operation)) {
2471 QualType destType = ECE->getType();
2472 bool destTypeComplete = true;
2473
2474 if (!isa<PointerType>(destType))
2475 return;
2476 destType = destType.getTypePtr()->getPointeeType();
2477 if (const auto *D = destType->getAsTagDecl())
2478 destTypeComplete = D->isCompleteDefinition();
2479
2480 // If destination type is incomplete, it is unsafe to cast to anyway, no
2481 // need to check its type:
2482 if (destTypeComplete) {
2483 const uint64_t dSize = Ctx.getTypeSize(destType);
2484 QualType srcType = ECE->getSubExpr()->getType();
2485
2486 assert(srcType->isPointerType());
2487
2488 const uint64_t sSize =
2489 Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType());
2490
2491 if (sSize >= dSize)
2492 return;
2493 }
2494 if (const auto *CE = dyn_cast<CXXMemberCallExpr>(
2495 ECE->getSubExpr()->IgnoreParens())) {
2496 D = CE->getMethodDecl();
2497 }
2498
2499 if (!D)
2500 return;
2501
2502 MsgParam = 4;
2503 }
2504 Loc = Operation->getBeginLoc();
2505 Range = Operation->getSourceRange();
2506 }
2507 if (IsRelatedToDecl) {
2508 assert(!SuggestSuggestions &&
2509 "Variables blamed for unsafe buffer usage without suggestions!");
2510 S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range;
2511 } else {
2512 if (D) {
2513 S.Diag(Loc, diag::warn_unsafe_buffer_operation)
2514 << MsgParam << D << Range;
2515 } else {
2516 S.Diag(Loc, diag::warn_unsafe_buffer_operation) << MsgParam << Range;
2517 }
2518 if (SuggestSuggestions) {
2519 S.Diag(Loc, diag::note_safe_buffer_usage_suggestions_disabled);
2520 }
2521 }
2522 }
2523
2524 void handleUnsafeLibcCall(const CallExpr *Call, unsigned PrintfInfo,
2525 ASTContext &Ctx,
2526 const Expr *UnsafeArg = nullptr) override {
2527 S.Diag(Call->getBeginLoc(), diag::warn_unsafe_buffer_libc_call)
2528 << Call->getDirectCallee() // We've checked there is a direct callee
2529 << Call->getSourceRange();
2530 if (PrintfInfo > 0) {
2531 SourceRange R =
2532 UnsafeArg ? UnsafeArg->getSourceRange() : Call->getSourceRange();
2533 S.Diag(R.getBegin(), diag::note_unsafe_buffer_printf_call)
2534 << PrintfInfo << R;
2535 }
2536 }
2537
2538 void handleUnsafeOperationInContainer(const Stmt *Operation,
2539 bool IsRelatedToDecl,
2540 ASTContext &Ctx) override {
2541 SourceLocation Loc;
2542 SourceRange Range;
2543 unsigned MsgParam = 0;
2544
2545 // This function only handles SpanTwoParamConstructorGadget so far, which
2546 // always gives a CXXConstructExpr.
2547 const auto *CtorExpr = cast<CXXConstructExpr>(Operation);
2548 Loc = CtorExpr->getLocation();
2549
2550 S.Diag(Loc, diag::warn_unsafe_buffer_usage_in_container);
2551 if (IsRelatedToDecl) {
2552 assert(!SuggestSuggestions &&
2553 "Variables blamed for unsafe buffer usage without suggestions!");
2554 S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range;
2555 }
2556 }
2557
2558 void handleUnsafeVariableGroup(const VarDecl *Variable,
2559 const VariableGroupsManager &VarGrpMgr,
2560 FixItList &&Fixes, const Decl *D,
2561 const FixitStrategy &VarTargetTypes) override {
2562 assert(!SuggestSuggestions &&
2563 "Unsafe buffer usage fixits displayed without suggestions!");
2564 S.Diag(Variable->getLocation(), diag::warn_unsafe_buffer_variable)
2565 << Variable << (Variable->getType()->isPointerType() ? 0 : 1)
2566 << Variable->getSourceRange();
2567 if (!Fixes.empty()) {
2568 assert(isa<NamedDecl>(D) &&
2569 "Fix-its are generated only for `NamedDecl`s");
2570 const NamedDecl *ND = cast<NamedDecl>(D);
2571 bool BriefMsg = false;
2572 // If the variable group involves parameters, the diagnostic message will
2573 // NOT explain how the variables are grouped as the reason is non-trivial
2574 // and irrelavant to users' experience:
2575 const auto VarGroupForVD = VarGrpMgr.getGroupOfVar(Variable, &BriefMsg);
2576 unsigned FixItStrategy = 0;
2577 switch (VarTargetTypes.lookup(Variable)) {
2579 FixItStrategy = 0;
2580 break;
2582 FixItStrategy = 1;
2583 break;
2584 default:
2585 assert(false && "We support only std::span and std::array");
2586 };
2587
2588 const auto &FD =
2589 S.Diag(Variable->getLocation(),
2590 BriefMsg ? diag::note_unsafe_buffer_variable_fixit_together
2591 : diag::note_unsafe_buffer_variable_fixit_group);
2592
2593 FD << Variable << FixItStrategy;
2594 FD << listVariableGroupAsString(Variable, VarGroupForVD)
2595 << (VarGroupForVD.size() > 1) << ND;
2596 for (const auto &F : Fixes) {
2597 FD << F;
2598 }
2599 }
2600
2601#ifndef NDEBUG
2602 if (areDebugNotesRequested())
2603 for (const DebugNote &Note: DebugNotesByVar[Variable])
2604 S.Diag(Note.first, diag::note_safe_buffer_debug_mode) << Note.second;
2605#endif
2606 }
2607
2608 void handleUnsafeUniquePtrArrayAccess(const DynTypedNode &Node,
2609 bool IsRelatedToDecl,
2610 ASTContext &Ctx) override {
2611 SourceLocation Loc;
2612 std::string Message;
2613
2614 Loc = Node.get<Stmt>()->getBeginLoc();
2615 S.Diag(Loc, diag::warn_unsafe_buffer_usage_unique_ptr_array_access)
2616 << Node.getSourceRange();
2617 }
2618
2619 bool isSafeBufferOptOut(const SourceLocation &Loc) const override {
2620 return S.PP.isSafeBufferOptOut(S.getSourceManager(), Loc);
2621 }
2622
2623 bool ignoreUnsafeBufferInContainer(const SourceLocation &Loc) const override {
2624 return S.Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container, Loc);
2625 }
2626
2627 bool ignoreUnsafeBufferInLibcCall(const SourceLocation &Loc) const override {
2628 return S.Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, Loc);
2629 }
2630
2631 // Returns the text representation of clang::unsafe_buffer_usage attribute.
2632 // `WSSuffix` holds customized "white-space"s, e.g., newline or whilespace
2633 // characters.
2634 std::string
2635 getUnsafeBufferUsageAttributeTextAt(SourceLocation Loc,
2636 StringRef WSSuffix = "") const override {
2637 Preprocessor &PP = S.getPreprocessor();
2638 TokenValue ClangUnsafeBufferUsageTokens[] = {
2639 tok::l_square,
2640 tok::l_square,
2641 PP.getIdentifierInfo("clang"),
2642 tok::coloncolon,
2643 PP.getIdentifierInfo("unsafe_buffer_usage"),
2644 tok::r_square,
2645 tok::r_square};
2646
2647 StringRef MacroName;
2648
2649 // The returned macro (it returns) is guaranteed not to be function-like:
2650 MacroName = PP.getLastMacroWithSpelling(Loc, ClangUnsafeBufferUsageTokens);
2651 if (MacroName.empty())
2652 MacroName = "[[clang::unsafe_buffer_usage]]";
2653 return MacroName.str() + WSSuffix.str();
2654 }
2655};
2656} // namespace
2657
2658//===----------------------------------------------------------------------===//
2659// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
2660// warnings on a function, method, or block.
2661//===----------------------------------------------------------------------===//
2662
2664 enableCheckFallThrough = 1;
2665 enableCheckUnreachable = 0;
2666 enableThreadSafetyAnalysis = 0;
2667 enableConsumedAnalysis = 0;
2668}
2669
2670/// InterProceduralData aims to be a storage of whatever data should be passed
2671/// between analyses of different functions.
2672///
2673/// At the moment, its primary goal is to make the information gathered during
2674/// the analysis of the blocks available during the analysis of the enclosing
2675/// function. This is important due to the fact that blocks are analyzed before
2676/// the enclosed function is even parsed fully, so it is not viable to access
2677/// anything in the outer scope while analyzing the block. On the other hand,
2678/// re-building CFG for blocks and re-analyzing them when we do have all the
2679/// information (i.e. during the analysis of the enclosing function) seems to be
2680/// ill-designed.
2682public:
2683 // It is important to analyze blocks within functions because it's a very
2684 // common pattern to capture completion handler parameters by blocks.
2685 CalledOnceInterProceduralData CalledOnceData;
2686};
2687
2688template <typename... Ts>
2690 Ts... Diags) {
2691 return (!D.isIgnored(Diags, Loc) || ...);
2692}
2693
2695 : S(s), IPData(std::make_unique<InterProceduralData>()),
2696 NumFunctionsAnalyzed(0), NumFunctionsWithBadCFGs(0), NumCFGBlocks(0),
2697 MaxCFGBlocksPerFunction(0), NumUninitAnalysisFunctions(0),
2698 NumUninitAnalysisVariables(0), MaxUninitAnalysisVariablesPerFunction(0),
2699 NumUninitAnalysisBlockVisits(0),
2700 MaxUninitAnalysisBlockVisitsPerFunction(0) {
2701}
2702
2703// We need this here for unique_ptr with forward declared class.
2705
2708 using namespace diag;
2709 DiagnosticsEngine &D = S.getDiagnostics();
2710 Policy P;
2711
2712 // Note: The enabled checks should be kept in sync with the switch in
2713 // SemaPPCallbacks::PragmaDiagnostic().
2714 P.enableCheckUnreachable =
2715 PolicyOverrides.enableCheckUnreachable ||
2716 areAnyEnabled(D, Loc, warn_unreachable, warn_unreachable_break,
2717 warn_unreachable_return, warn_unreachable_loop_increment);
2718
2719 P.enableThreadSafetyAnalysis = PolicyOverrides.enableThreadSafetyAnalysis ||
2720 areAnyEnabled(D, Loc, warn_double_lock);
2721
2722 P.enableConsumedAnalysis = PolicyOverrides.enableConsumedAnalysis ||
2723 areAnyEnabled(D, Loc, warn_use_in_invalid_state);
2724 return P;
2725}
2726
2727void sema::AnalysisBasedWarnings::clearOverrides() {
2728 PolicyOverrides.enableCheckUnreachable = false;
2729 PolicyOverrides.enableConsumedAnalysis = false;
2730 PolicyOverrides.enableThreadSafetyAnalysis = false;
2731}
2732
2733static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
2734 for (const auto &D : fscope->PossiblyUnreachableDiags)
2735 S.Diag(D.Loc, D.PD);
2736}
2737
2738// An AST Visitor that calls a callback function on each callable DEFINITION
2739// that is NOT in a dependent context:
2741private:
2742 llvm::function_ref<void(const Decl *)> Callback;
2743 const Module *const TUModule;
2744
2745public:
2746 CallableVisitor(llvm::function_ref<void(const Decl *)> Callback,
2747 const Module *const TUModule)
2748 : Callback(Callback), TUModule(TUModule) {
2751 }
2752
2753 bool TraverseDecl(Decl *Node) override {
2754 // For performance reasons, only validate the current translation unit's
2755 // module, and not modules it depends on.
2756 // See https://issues.chromium.org/issues/351909443 for details.
2757 if (Node && Node->getOwningModule() == TUModule)
2759 return true;
2760 }
2761
2762 bool VisitFunctionDecl(FunctionDecl *Node) override {
2763 if (cast<DeclContext>(Node)->isDependentContext())
2764 return true; // Not to analyze dependent decl
2765 // `FunctionDecl->hasBody()` returns true if the function has a body
2766 // somewhere defined. But we want to know if this `Node` has a body
2767 // child. So we use `doesThisDeclarationHaveABody`:
2768 if (Node->doesThisDeclarationHaveABody())
2769 Callback(Node);
2770 return true;
2771 }
2772
2773 bool VisitBlockDecl(BlockDecl *Node) override {
2774 if (cast<DeclContext>(Node)->isDependentContext())
2775 return true; // Not to analyze dependent decl
2776 Callback(Node);
2777 return true;
2778 }
2779
2781 if (cast<DeclContext>(Node)->isDependentContext())
2782 return true; // Not to analyze dependent decl
2783 if (Node->hasBody())
2784 Callback(Node);
2785 return true;
2786 }
2787
2788 bool VisitLambdaExpr(LambdaExpr *Node) override {
2789 return VisitFunctionDecl(Node->getCallOperator());
2790 }
2791};
2792
2793namespace clang::lifetimes {
2794namespace {
2795class LifetimeSafetyReporterImpl : public LifetimeSafetyReporter {
2796
2797public:
2798 LifetimeSafetyReporterImpl(Sema &S) : S(S) {}
2799
2800 void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
2801 SourceLocation FreeLoc, Confidence C) override {
2802 S.Diag(IssueExpr->getExprLoc(),
2803 C == Confidence::Definite
2804 ? diag::warn_lifetime_safety_loan_expires_permissive
2805 : diag::warn_lifetime_safety_loan_expires_strict)
2806 << IssueExpr->getEndLoc();
2807 S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here);
2808 S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
2809 << UseExpr->getEndLoc();
2810 }
2811
2812private:
2813 Sema &S;
2814};
2815} // namespace
2816} // namespace clang::lifetimes
2817
2819 TranslationUnitDecl *TU) {
2820 if (!TU)
2821 return; // This is unexpected, give up quietly.
2822
2823 DiagnosticsEngine &Diags = S.getDiagnostics();
2824
2825 if (S.hasUncompilableErrorOccurred() || Diags.getIgnoreAllWarnings())
2826 // exit if having uncompilable errors or ignoring all warnings:
2827 return;
2828
2829 DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();
2830
2831 // UnsafeBufferUsage analysis settings.
2832 bool UnsafeBufferUsageCanEmitSuggestions = S.getLangOpts().CPlusPlus20;
2833 bool UnsafeBufferUsageShouldEmitSuggestions = // Should != Can.
2834 UnsafeBufferUsageCanEmitSuggestions &&
2835 DiagOpts.ShowSafeBufferUsageSuggestions;
2836 bool UnsafeBufferUsageShouldSuggestSuggestions =
2837 UnsafeBufferUsageCanEmitSuggestions &&
2838 !DiagOpts.ShowSafeBufferUsageSuggestions;
2839 UnsafeBufferUsageReporter R(S, UnsafeBufferUsageShouldSuggestSuggestions);
2840
2841 // The Callback function that performs analyses:
2842 auto CallAnalyzers = [&](const Decl *Node) -> void {
2843 if (Node->hasAttr<UnsafeBufferUsageAttr>())
2844 return;
2845
2846 // Perform unsafe buffer usage analysis:
2847 if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation,
2848 Node->getBeginLoc()) ||
2849 !Diags.isIgnored(diag::warn_unsafe_buffer_variable,
2850 Node->getBeginLoc()) ||
2851 !Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container,
2852 Node->getBeginLoc()) ||
2853 !Diags.isIgnored(diag::warn_unsafe_buffer_libc_call,
2854 Node->getBeginLoc())) {
2856 UnsafeBufferUsageShouldEmitSuggestions);
2857 }
2858
2859 // More analysis ...
2860 };
2861 // Emit per-function analysis-based warnings that require the whole-TU
2862 // reasoning. Check if any of them is enabled at all before scanning the AST:
2863 if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation, SourceLocation()) ||
2864 !Diags.isIgnored(diag::warn_unsafe_buffer_variable, SourceLocation()) ||
2865 !Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container,
2866 SourceLocation()) ||
2867 (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) &&
2868 S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) {
2869 CallableVisitor(CallAnalyzers, TU->getOwningModule())
2870 .TraverseTranslationUnitDecl(TU);
2871 }
2872}
2873
2876 const Decl *D, QualType BlockType) {
2877
2878 // We avoid doing analysis-based warnings when there are errors for
2879 // two reasons:
2880 // (1) The CFGs often can't be constructed (if the body is invalid), so
2881 // don't bother trying.
2882 // (2) The code already has problems; running the analysis just takes more
2883 // time.
2884 DiagnosticsEngine &Diags = S.getDiagnostics();
2885
2886 // Do not do any analysis if we are going to just ignore them.
2887 if (Diags.getIgnoreAllWarnings() ||
2888 (Diags.getSuppressSystemWarnings() &&
2889 S.SourceMgr.isInSystemHeader(D->getLocation())))
2890 return;
2891
2892 // For code in dependent contexts, we'll do this at instantiation time.
2893 if (cast<DeclContext>(D)->isDependentContext())
2894 return;
2895
2896 if (S.hasUncompilableErrorOccurred()) {
2897 // Flush out any possibly unreachable diagnostics.
2898 flushDiagnostics(S, fscope);
2899 return;
2900 }
2901
2902 const Stmt *Body = D->getBody();
2903 assert(Body);
2904
2905 // Construct the analysis context with the specified CFG build options.
2906 AnalysisDeclContext AC(/* AnalysisDeclContextManager */ nullptr, D);
2907
2908 // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
2909 // explosion for destructors that can result and the compile time hit.
2911 AC.getCFGBuildOptions().AddEHEdges = false;
2917
2918 bool EnableLifetimeSafetyAnalysis = S.getLangOpts().EnableLifetimeSafety;
2919
2920 // Force that certain expressions appear as CFGElements in the CFG. This
2921 // is used to speed up various analyses.
2922 // FIXME: This isn't the right factoring. This is here for initial
2923 // prototyping, but we need a way for analyses to say what expressions they
2924 // expect to always be CFGElements and then fill in the BuildOptions
2925 // appropriately. This is essentially a layering violation.
2926 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
2927 P.enableConsumedAnalysis || EnableLifetimeSafetyAnalysis) {
2928 // Unreachable code analysis and thread safety require a linearized CFG.
2930 } else {
2932 .setAlwaysAdd(Stmt::BinaryOperatorClass)
2933 .setAlwaysAdd(Stmt::CompoundAssignOperatorClass)
2934 .setAlwaysAdd(Stmt::BlockExprClass)
2935 .setAlwaysAdd(Stmt::CStyleCastExprClass)
2936 .setAlwaysAdd(Stmt::DeclRefExprClass)
2937 .setAlwaysAdd(Stmt::ImplicitCastExprClass)
2938 .setAlwaysAdd(Stmt::UnaryOperatorClass);
2939 }
2940
2941 // Install the logical handler.
2942 std::optional<LogicalErrorHandler> LEH;
2943 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
2944 LEH.emplace(S);
2945 AC.getCFGBuildOptions().Observer = &*LEH;
2946 }
2947
2948 // Emit delayed diagnostics.
2949 if (!fscope->PossiblyUnreachableDiags.empty()) {
2950 bool analyzed = false;
2951
2952 // Register the expressions with the CFGBuilder.
2953 for (const auto &D : fscope->PossiblyUnreachableDiags) {
2954 for (const Stmt *S : D.Stmts)
2956 }
2957
2958 if (AC.getCFG()) {
2959 analyzed = true;
2960 for (const auto &D : fscope->PossiblyUnreachableDiags) {
2961 bool AllReachable = true;
2962 for (const Stmt *S : D.Stmts) {
2963 const CFGBlock *block = AC.getBlockForRegisteredExpression(S);
2966 // FIXME: We should be able to assert that block is non-null, but
2967 // the CFG analysis can skip potentially-evaluated expressions in
2968 // edge cases; see test/Sema/vla-2.c.
2969 if (block && cra) {
2970 // Can this block be reached from the entrance?
2971 if (!cra->isReachable(&AC.getCFG()->getEntry(), block)) {
2972 AllReachable = false;
2973 break;
2974 }
2975 }
2976 // If we cannot map to a basic block, assume the statement is
2977 // reachable.
2978 }
2979
2980 if (AllReachable)
2981 S.Diag(D.Loc, D.PD);
2982 }
2983 }
2984
2985 if (!analyzed)
2986 flushDiagnostics(S, fscope);
2987 }
2988
2989 // Warning: check missing 'return'
2990 if (P.enableCheckFallThrough) {
2991 const CheckFallThroughDiagnostics &CD =
2992 (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
2993 : (isa<CXXMethodDecl>(D) &&
2994 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2995 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2996 ? CheckFallThroughDiagnostics::MakeForLambda()
2997 : (fscope->isCoroutine()
2998 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2999 : CheckFallThroughDiagnostics::MakeForFunction(S, D)));
3000 CheckFallThroughForBody(S, D, Body, BlockType, CD, AC);
3001 }
3002
3003 // Warning: check for unreachable code
3004 if (P.enableCheckUnreachable) {
3005 // Only check for unreachable code on non-template instantiations.
3006 // Different template instantiations can effectively change the control-flow
3007 // and it is very difficult to prove that a snippet of code in a template
3008 // is unreachable for all instantiations.
3009 bool isTemplateInstantiation = false;
3010 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
3011 isTemplateInstantiation = Function->isTemplateInstantiation();
3013 CheckUnreachable(S, AC);
3014 }
3015
3016 // Check for thread safety violations
3017 if (P.enableThreadSafetyAnalysis) {
3018 SourceLocation FL = AC.getDecl()->getLocation();
3019 SourceLocation FEL = AC.getDecl()->getEndLoc();
3020 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
3021 if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getBeginLoc()))
3022 Reporter.setIssueBetaWarnings(true);
3023 if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getBeginLoc()))
3024 Reporter.setVerbose(true);
3025
3027 &S.ThreadSafetyDeclCache);
3028 Reporter.emitDiagnostics();
3029 }
3030
3031 // Check for violations of consumed properties.
3032 if (P.enableConsumedAnalysis) {
3033 consumed::ConsumedWarningsHandler WarningHandler(S);
3034 consumed::ConsumedAnalyzer Analyzer(WarningHandler);
3035 Analyzer.run(AC);
3036 }
3037
3038 if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||
3039 !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
3040 !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc()) ||
3041 !Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc()) ||
3042 !Diags.isIgnored(diag::warn_uninit_const_pointer, D->getBeginLoc())) {
3043 if (CFG *cfg = AC.getCFG()) {
3044 UninitValsDiagReporter reporter(S);
3046 std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats));
3048 reporter, stats);
3049
3050 if (S.CollectStats && stats.NumVariablesAnalyzed > 0) {
3051 ++NumUninitAnalysisFunctions;
3052 NumUninitAnalysisVariables += stats.NumVariablesAnalyzed;
3053 NumUninitAnalysisBlockVisits += stats.NumBlockVisits;
3054 MaxUninitAnalysisVariablesPerFunction =
3055 std::max(MaxUninitAnalysisVariablesPerFunction,
3056 stats.NumVariablesAnalyzed);
3057 MaxUninitAnalysisBlockVisitsPerFunction =
3058 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
3059 stats.NumBlockVisits);
3060 }
3061 }
3062 }
3063
3064 // TODO: Enable lifetime safety analysis for other languages once it is
3065 // stable.
3066 if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
3067 if (AC.getCFG()) {
3068 lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
3069 lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter);
3070 }
3071 }
3072 // Check for violations of "called once" parameter properties.
3073 if (S.getLangOpts().ObjC && !S.getLangOpts().CPlusPlus &&
3074 shouldAnalyzeCalledOnceParameters(Diags, D->getBeginLoc())) {
3075 if (AC.getCFG()) {
3076 CalledOnceCheckReporter Reporter(S, IPData->CalledOnceData);
3078 AC, Reporter,
3079 shouldAnalyzeCalledOnceConventions(Diags, D->getBeginLoc()));
3080 }
3081 }
3082
3083 bool FallThroughDiagFull =
3084 !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc());
3085 bool FallThroughDiagPerFunction = !Diags.isIgnored(
3086 diag::warn_unannotated_fallthrough_per_function, D->getBeginLoc());
3087 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
3088 fscope->HasFallthroughStmt) {
3089 DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
3090 }
3091
3092 if (S.getLangOpts().ObjCWeak &&
3093 !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getBeginLoc()))
3094 diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
3095
3096
3097 // Check for infinite self-recursion in functions
3098 if (!Diags.isIgnored(diag::warn_infinite_recursive_function,
3099 D->getBeginLoc())) {
3100 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
3101 checkRecursiveFunction(S, FD, Body, AC);
3102 }
3103 }
3104
3105 // Check for throw out of non-throwing function.
3106 if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getBeginLoc()))
3107 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
3108 if (S.getLangOpts().CPlusPlus && !fscope->isCoroutine() && isNoexcept(FD))
3109 checkThrowInNonThrowingFunc(S, FD, AC);
3110
3111 // If none of the previous checks caused a CFG build, trigger one here
3112 // for the logical error handler.
3113 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
3114 AC.getCFG();
3115 }
3116
3117 // Clear any of our policy overrides.
3118 clearOverrides();
3119
3120 // Collect statistics about the CFG if it was built.
3121 if (S.CollectStats && AC.isCFGBuilt()) {
3122 ++NumFunctionsAnalyzed;
3123 if (CFG *cfg = AC.getCFG()) {
3124 // If we successfully built a CFG for this context, record some more
3125 // detail information about it.
3126 NumCFGBlocks += cfg->getNumBlockIDs();
3127 MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,
3128 cfg->getNumBlockIDs());
3129 } else {
3130 ++NumFunctionsWithBadCFGs;
3131 }
3132 }
3133}
3134
3136 llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
3137
3138 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
3139 unsigned AvgCFGBlocksPerFunction =
3140 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
3141 llvm::errs() << NumFunctionsAnalyzed << " functions analyzed ("
3142 << NumFunctionsWithBadCFGs << " w/o CFGs).\n"
3143 << " " << NumCFGBlocks << " CFG blocks built.\n"
3144 << " " << AvgCFGBlocksPerFunction
3145 << " average CFG blocks per function.\n"
3146 << " " << MaxCFGBlocksPerFunction
3147 << " max CFG blocks per function.\n";
3148
3149 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
3150 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
3151 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
3152 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
3153 llvm::errs() << NumUninitAnalysisFunctions
3154 << " functions analyzed for uninitialiazed variables\n"
3155 << " " << NumUninitAnalysisVariables << " variables analyzed.\n"
3156 << " " << AvgUninitVariablesPerFunction
3157 << " average variables per function.\n"
3158 << " " << MaxUninitAnalysisVariablesPerFunction
3159 << " max variables per function.\n"
3160 << " " << NumUninitAnalysisBlockVisits << " block visits.\n"
3161 << " " << AvgUninitBlockVisitsPerFunction
3162 << " average block visits per function.\n"
3163 << " " << MaxUninitAnalysisBlockVisitsPerFunction
3164 << " max block visits per function.\n";
3165}
#define V(N, I)
static void visitReachableThrows(CFG *BodyCFG, llvm::function_ref< void(const CXXThrowExpr *, CFGBlock &)> Visit)
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD)
static bool isReferenceToNoReturn(const Expr *E)
Checks if the given expression is a reference to a function with 'noreturn' attribute.
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 CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, QualType BlockType, const CheckFallThroughDiagnostics &CD, AnalysisDeclContext &AC)
CheckFallThroughForBody - Check that we don't fall off the end of a function that should return a val...
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 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 areAnyEnabled(DiagnosticsEngine &D, SourceLocation Loc, Ts... Diags)
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 areAllValuesNoReturn(const VarDecl *VD, const CFGBlock &VarBlk, AnalysisDeclContext &AC)
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 bool DiagnoseUninitializedConstPtrUse(Sema &S, const VarDecl *VD, const UninitUse &Use)
Diagnose uninitialized const pointer usages.
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC)
CheckUnreachable - Check for unreachable code.
@ NeverFallThroughOrReturn
static bool isInitializedWithNoReturn(const VarDecl *VD)
Checks if the given variable, which is assumed to be a function pointer, is initialized with a functi...
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, const Stmt *Body, AnalysisDeclContext &AC)
static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg)
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Defines the Diagnostic-related interfaces.
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)
#define SM(sm)
llvm::DenseMap< Stmt *, Stmt * > MapTy
Definition ParentMap.cpp:21
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines the Objective-C statement AST node classes.
C Language Family Type Representation.
@ Open
The standard open() call: int open(const char *path, int oflag, ...);.
static bool ignoreUnsafeBufferInContainer(const Stmt &Node, const UnsafeBufferUsageHandler *Handler)
TextDiagnosticBuffer::DiagList DiagList
__device__ __2f16 b
__device__ __2f16 float __ockl_bool s
CallableVisitor(llvm::function_ref< void(const Decl *)> Callback, const Module *const TUModule)
bool VisitObjCMethodDecl(ObjCMethodDecl *Node) override
bool TraverseDecl(Decl *Node) override
bool VisitBlockDecl(BlockDecl *Node) override
bool VisitFunctionDecl(FunctionDecl *Node) override
bool VisitLambdaExpr(LambdaExpr *Node) override
APSInt & getInt()
Definition APValue.h:489
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
AnalysisDeclContext contains the context data for the function, method or block under analysis.
void registerForcedBlockExpression(const Stmt *stmt)
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
ASTContext & getASTContext() const
CFG::BuildOptions & getCFGBuildOptions()
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:3972
static bool isLogicalOp(Opcode Opc)
Definition Expr.h:4105
Expr * getLHS() const
Definition Expr.h:4022
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:4027
SourceLocation getOperatorLoc() const
Definition Expr.h:4014
SourceLocation getExprLoc() const
Definition Expr.h:4013
static StringRef getOpcodeStr(Opcode Op)
getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to,...
Definition Expr.cpp:2128
Expr * getRHS() const
Definition Expr.h:4024
Opcode getOpcode() const
Definition Expr.h:4017
BinaryOperatorKind Opcode
Definition Expr.h:3977
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition Decl.h:4654
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition Expr.h:6558
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:6579
unsigned IgnoreDefaultsWithCoveredEnums
Definition CFG.h:1020
Represents a single basic block in a source-level CFG.
Definition CFG.h:605
filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const
Definition CFG.h:1066
pred_iterator pred_end()
Definition CFG.h:973
reverse_iterator rbegin()
Definition CFG.h:915
reverse_iterator rend()
Definition CFG.h:916
bool hasNoReturnElement() const
Definition CFG.h:1109
ElementList::const_reverse_iterator const_reverse_iterator
Definition CFG.h:903
CFGElement front() const
Definition CFG.h:907
iterator begin()
Definition CFG.h:910
FilteredCFGBlockIterator< const_pred_iterator, true > filtered_pred_iterator
Definition CFG.h:1060
succ_range succs()
Definition CFG.h:1000
bool empty() const
Definition CFG.h:953
Stmt * getLabel()
Definition CFG.h:1106
succ_iterator succ_begin()
Definition CFG.h:990
Stmt * getTerminatorStmt()
Definition CFG.h:1087
pred_iterator pred_begin()
Definition CFG.h:972
iterator end()
Definition CFG.h:911
unsigned getBlockID() const
Definition CFG.h:1111
bool pred_empty() const
Definition CFG.h:1012
unsigned succ_size() const
Definition CFG.h:1008
CFGCallback defines methods that should be called when a logical operator error is found when buildin...
Definition CFG.h:1203
Represents a top-level expression in a basic block.
Definition CFG.h:55
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
Definition CFG.h:99
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:109
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:139
bool PruneTriviallyFalseEdges
Definition CFG.h:1238
bool AddCXXDefaultInitExprInCtors
Definition CFG.h:1248
BuildOptions & setAllAlwaysAdd()
Definition CFG.h:1267
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
Definition CFG.h:1262
CFGCallback * Observer
Definition CFG.h:1237
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1222
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:1410
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:179
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Definition ExprCXX.cpp:741
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition ExprCXX.cpp:722
bool isVirtual() const
Definition DeclCXX.h:2184
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1209
const Expr * getSubExpr() const
Definition ExprCXX.h:1229
SourceLocation getThrowLoc() const
Definition ExprCXX.h:1232
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
ExprIterator arg_iterator
Definition Expr.h:3124
arg_iterator arg_begin()
Definition Expr.h:3134
arg_iterator arg_end()
Definition Expr.h:3137
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3060
Expr * getCallee()
Definition Expr.h:3024
Decl * getCalleeDecl()
Definition Expr.h:3054
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getBegin() const
ConditionalOperator - The ?
Definition Expr.h:4325
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4357
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Definition Expr.h:4348
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4352
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
void enqueueBlock(const CFGBlock *Block)
bool isFunctionOrMethod() const
Definition DeclBase.h:2161
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
decl_range decls()
Definition Stmt.h:1659
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getEndLoc() const LLVM_READONLY
Definition DeclBase.h:435
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:1087
Module * getOwningModule() const
Get the module that owns this declaration (for visibility purposes).
Definition DeclBase.h:842
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:251
SourceLocation getLocation() const
Definition DeclBase.h:439
DeclContext * getDeclContext()
Definition DeclBase.h:448
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:431
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:918
bool hasAttr() const
Definition DeclBase.h:577
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:978
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
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:831
TypeSourceInfo * getTypeSourceInfo() const
Definition Decl.h:809
Options for controlling the compiler diagnostics engine.
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:232
bool isLastDiagnosticIgnored() const
Determine whether the previous diagnostic was ignored.
Definition Diagnostic.h:801
bool getIgnoreAllWarnings() const
Definition Diagnostic.h:686
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
Definition Diagnostic.h:597
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
Definition Diagnostic.h:951
bool getSuppressSystemWarnings() const
Definition Diagnostic.h:723
const T * get() const
Retrieve the stored node as type T.
SourceRange getSourceRange(bool IncludeQualifier=false) const
For nodes which represent textual entities in the source code, return their SourceRange.
virtual bool TraverseDecl(MaybeConst< Decl > *D)
void VisitDeclRefExpr(PTR(DeclRefExpr) E)
This represents one expression.
Definition Expr.h:112
bool isGLValue() const
Definition Expr.h:287
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3090
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3085
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
QualType getType() const
Definition Expr.h:144
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition Diagnostic.h:79
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
Definition Diagnostic.h:83
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:140
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition Diagnostic.h:129
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:103
Kind lookup(const VarDecl *VD) const
Represents a function declaration or definition.
Definition Decl.h:2000
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:3735
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
Definition Decl.h:2326
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification,...
Definition Decl.cpp:4044
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition Decl.cpp:4132
bool isCPUDispatchMultiVersion() const
True if this function is a multiversioned dispatch function as a part of the cpu_specific/cpu_dispatc...
Definition Decl.cpp:3690
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5266
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4462
IfStmt - This represents an if/then/else.
Definition Stmt.h:2259
Stmt * getThen()
Definition Stmt.h:2348
Expr * getCond()
Definition Stmt.h:2336
Stmt * getElse()
Definition Stmt.h:2357
Stmt * getSubStmt()
Definition Stmt.h:2168
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Definition ExprCXX.h:1970
CXXMethodDecl * getCallOperator() const
Retrieve the function call operator associated with this lambda expression.
Definition ExprCXX.cpp:1404
Describes a module or submodule.
Definition Module.h:144
This represents a decl that may have a name.
Definition Decl.h:274
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
ObjCMethodDecl - Represents an instance or class method declaration.
Definition DeclObjC.h:140
bool hasBody() const override
Determine whether this method has a body.
Definition DeclObjC.h:523
Represents one property declaration in an Objective-C interface.
Definition DeclObjC.h:731
Stmt * getParent(Stmt *) const
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
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 TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8290
bool isConstant(const ASTContext &Ctx) const
Definition TypeBase.h:1097
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8330
QualType getCanonicalType() const
Definition TypeBase.h:8342
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8363
bool hasObjCLifetime() const
Definition TypeBase.h:544
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition SemaBase.cpp:61
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
Preprocessor & getPreprocessor() const
Definition Sema.h:924
ASTContext & Context
Definition Sema.h:1283
DiagnosticsEngine & getDiagnostics() const
Definition Sema.h:922
ASTContext & getASTContext() const
Definition Sema.h:925
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:83
const LangOptions & getLangOpts() const
Definition Sema.h:918
SourceManager & getSourceManager() const
Definition Sema.h:923
bool handlerCanCatch(QualType HandlerType, QualType ExceptionType)
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.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Definition Stmt.h:85
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:358
child_range children()
Definition Stmt.cpp:295
StmtClass getStmtClass() const
Definition Stmt.h:1472
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:346
Stmt * getSubStmt()
Definition Stmt.h:2113
Stores token information for comparing actual tokens with predefined values.
The top declaration context.
Definition Decl.h:105
QualType getType() const
Return the type wrapped by this type source info.
Definition TypeBase.h:8272
bool isBlockPointerType() const
Definition TypeBase.h:8547
bool isPointerType() const
Definition TypeBase.h:8527
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8927
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9170
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
TagDecl * getAsTagDecl() const
Retrieves the TagDecl that this type refers to, either because the type is a TagType or because it is...
Definition Type.h:65
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9103
Expr * getSubExpr() const
Definition Expr.h:2285
Opcode getOpcode() const
Definition Expr.h:2280
UnaryOperatorKind Opcode
Definition Expr.h:2258
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
bool isConstPtrUse() const
bool isConstRefOrPtrUse() const
bool isConstRefUse() 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.
The interface that lets the caller handle unsafe buffer usage analysis results by overriding this cla...
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2190
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2366
const Expr * getInit() const
Definition Decl.h:1368
virtual VarGrpRef getGroupOfVar(const VarDecl *Var, bool *HasParm=nullptr) const =0
Returns the set of variables (including Var) that need to be fixed together in one step.
A class that handles the analysis of uniqueness violations.
Definition Consumed.h:243
void IssueWarnings(Policy P, FunctionScopeInfo *fscope, const Decl *D, QualType BlockType)
Policy getPolicyInEffectAt(SourceLocation Loc)
Represents a simple identification of a weak object.
Definition ScopeInfo.h:271
Retains information about a function, method, or block that is currently being parsed.
Definition ScopeInfo.h:104
bool HasFallthroughStmt
Whether there is a fallthrough statement in this function.
Definition ScopeInfo.h:138
SmallVector< WeakUseTy, 4 > WeakUseVector
Used to collect uses of a particular weak object in a function body.
Definition ScopeInfo.h:373
SmallVector< PossiblyUnreachableDiag, 4 > PossiblyUnreachableDiags
A list of PartialDiagnostics created but delayed within the current function scope.
Definition ScopeInfo.h:239
llvm::SmallDenseMap< WeakObjectProfileTy, WeakUseVector, 8, WeakObjectProfileTy::DenseMapInfo > WeakObjectUseMap
Used to collect all uses of weak objects in a function body.
Definition ScopeInfo.h:378
const WeakObjectUseMap & getWeakObjectUses() const
Definition ScopeInfo.h:431
InterProceduralData aims to be a storage of whatever data should be passed between analyses of differ...
std::list< DelayedDiag > DiagList
Definition Consumed.h:54
std::pair< PartialDiagnosticAt, OptionalNotes > DelayedDiag
Definition Consumed.h:53
SmallVector< PartialDiagnosticAt, 1 > OptionalNotes
Definition Consumed.h:52
uint32_t Variable
Boolean variables are represented as positive integers.
Definition CNFFormula.h:25
bool LE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1274
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC, LifetimeSafetyReporter *Reporter)
The main entry point for the analysis.
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.
LockKind getLockKindFromAccessKind(AccessKind AK)
Helper function that returns a LockKind required for the given level of access.
LockErrorKind
This enum distinguishes between different situations where we warn due to inconsistent locking.
@ LEK_NotLockedAtEndOfFunction
Expecting a capability to be held at the end of function.
@ LEK_LockedSomePredecessors
A capability is locked in some but not all predecessors of a CFGBlock.
@ LEK_LockedAtEndOfFunction
A capability is still locked at the end of a function.
@ LEK_LockedSomeLoopIterations
A capability is locked for some but not all loop iterations.
AccessKind
This enum distinguishes between different ways to access (read or write) a variable.
LockKind
This enum distinguishes between different kinds of lock actions.
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.
@ POK_PtPassByRef
Passing a pt-guarded variable by reference.
@ POK_PassPointer
Passing pointer to a guarded variable.
@ POK_VarDereference
Dereferencing a variable (e.g. p in *p = 5;)
@ POK_PassByRef
Passing a guarded variable by reference.
@ POK_ReturnByRef
Returning a guarded variable by reference.
@ POK_PtPassPointer
Passing a pt-guarded pointer.
@ POK_PtReturnPointer
Returning a pt-guarded pointer.
@ POK_VarAccess
Reading or writing a variable (e.g. x in x = 5;)
@ POK_FunctionCall
Making a function call (e.g. fool())
@ POK_ReturnPointer
Returning pointer to a guarded variable.
@ POK_PtReturnByRef
Returning a pt-guarded variable by reference.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
Definition Specifiers.h:212
void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler, bool EmitSuggestions)
bool hasSpecificAttr(const Container &container)
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Parameter
The parameter type of a method or function.
Definition TypeBase.h:908
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.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
Definition Address.h:327
unsigned long uint64_t
#define false
Definition stdbool.h:26
A worklist implementation for backward dataflow analysis.
void enqueuePredecessors(const CFGBlock *Block)
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:647