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
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,
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.
134 if (!S.getSourceManager().isInMainFile(AC.getDecl()->getBeginLoc()))
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
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,
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();
232 NNS.getKind() == NestedNameSpecifier::Kind::Type)
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 &&
369 (isa<CXXDestructorDecl>(FD) ||
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:
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 << const_cast<DeclContext*>(VD->getLexicalDeclContext())
989 << VD->getSourceRange();
990 S.Diag(Use.getUser()->getBeginLoc(), diag::note_uninit_var_use)
991 << IsCapturedByBlock << Use.getUser()->getSourceRange();
992 return;
993
994 case UninitUse::Maybe:
996 // Carry on to report sometimes-uninitialized branches, if possible,
997 // or a 'may be used uninitialized' diagnostic otherwise.
998 break;
999 }
1000
1001 // Diagnose each branch which leads to a sometimes-uninitialized use.
1002 for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end();
1003 I != E; ++I) {
1004 assert(Use.getKind() == UninitUse::Sometimes);
1005
1006 const Expr *User = Use.getUser();
1007 const Stmt *Term = I->Terminator;
1008
1009 // Information used when building the diagnostic.
1010 unsigned DiagKind;
1011 StringRef Str;
1013
1014 // FixIts to suppress the diagnostic by removing the dead condition.
1015 // For all binary terminators, branch 0 is taken if the condition is true,
1016 // and branch 1 is taken if the condition is false.
1017 int RemoveDiagKind = -1;
1018 const char *FixitStr =
1019 S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false")
1020 : (I->Output ? "1" : "0");
1021 FixItHint Fixit1, Fixit2;
1022
1023 switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) {
1024 default:
1025 // Don't know how to report this. Just fall back to 'may be used
1026 // uninitialized'. FIXME: Can this happen?
1027 continue;
1028
1029 // "condition is true / condition is false".
1030 case Stmt::IfStmtClass: {
1031 const IfStmt *IS = cast<IfStmt>(Term);
1032 DiagKind = 0;
1033 Str = "if";
1034 Range = IS->getCond()->getSourceRange();
1035 RemoveDiagKind = 0;
1036 CreateIfFixit(S, IS, IS->getThen(), IS->getElse(),
1037 I->Output, Fixit1, Fixit2);
1038 break;
1039 }
1040 case Stmt::ConditionalOperatorClass: {
1041 const ConditionalOperator *CO = cast<ConditionalOperator>(Term);
1042 DiagKind = 0;
1043 Str = "?:";
1044 Range = CO->getCond()->getSourceRange();
1045 RemoveDiagKind = 0;
1046 CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(),
1047 I->Output, Fixit1, Fixit2);
1048 break;
1049 }
1050 case Stmt::BinaryOperatorClass: {
1051 const BinaryOperator *BO = cast<BinaryOperator>(Term);
1052 if (!BO->isLogicalOp())
1053 continue;
1054 DiagKind = 0;
1055 Str = BO->getOpcodeStr();
1056 Range = BO->getLHS()->getSourceRange();
1057 RemoveDiagKind = 0;
1058 if ((BO->getOpcode() == BO_LAnd && I->Output) ||
1059 (BO->getOpcode() == BO_LOr && !I->Output))
1060 // true && y -> y, false || y -> y.
1061 Fixit1 = FixItHint::CreateRemoval(
1062 SourceRange(BO->getBeginLoc(), BO->getOperatorLoc()));
1063 else
1064 // false && y -> false, true || y -> true.
1065 Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr);
1066 break;
1067 }
1068
1069 // "loop is entered / loop is exited".
1070 case Stmt::WhileStmtClass:
1071 DiagKind = 1;
1072 Str = "while";
1073 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
1074 RemoveDiagKind = 1;
1075 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
1076 break;
1077 case Stmt::ForStmtClass:
1078 DiagKind = 1;
1079 Str = "for";
1080 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
1081 RemoveDiagKind = 1;
1082 if (I->Output)
1084 else
1085 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
1086 break;
1087 case Stmt::CXXForRangeStmtClass:
1088 if (I->Output == 1) {
1089 // The use occurs if a range-based for loop's body never executes.
1090 // That may be impossible, and there's no syntactic fix for this,
1091 // so treat it as a 'may be uninitialized' case.
1092 continue;
1093 }
1094 DiagKind = 1;
1095 Str = "for";
1096 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
1097 break;
1098
1099 // "condition is true / loop is exited".
1100 case Stmt::DoStmtClass:
1101 DiagKind = 2;
1102 Str = "do";
1103 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
1104 RemoveDiagKind = 1;
1105 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
1106 break;
1107
1108 // "switch case is taken".
1109 case Stmt::CaseStmtClass:
1110 DiagKind = 3;
1111 Str = "case";
1112 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
1113 break;
1114 case Stmt::DefaultStmtClass:
1115 DiagKind = 3;
1116 Str = "default";
1117 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
1118 break;
1119 }
1120
1121 S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var)
1122 << VD->getDeclName() << IsCapturedByBlock << DiagKind
1123 << Str << I->Output << Range;
1124 S.Diag(User->getBeginLoc(), diag::note_uninit_var_use)
1125 << IsCapturedByBlock << User->getSourceRange();
1126 if (RemoveDiagKind != -1)
1127 S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond)
1128 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
1129
1130 Diagnosed = true;
1131 }
1132
1133 if (!Diagnosed)
1134 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_maybe_uninit_var)
1135 << VD->getDeclName() << IsCapturedByBlock
1136 << Use.getUser()->getSourceRange();
1137}
1138
1139/// Diagnose uninitialized const reference usages.
1141 const UninitUse &Use) {
1142 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_reference)
1143 << VD->getDeclName() << Use.getUser()->getSourceRange();
1145}
1146
1147/// Diagnose uninitialized const pointer usages.
1149 const UninitUse &Use) {
1150 S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_pointer)
1151 << VD->getDeclName() << Use.getUser()->getSourceRange();
1153}
1154
1155/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
1156/// uninitialized variable. This manages the different forms of diagnostic
1157/// emitted for particular types of uses. Returns true if the use was diagnosed
1158/// as a warning. If a particular use is one we omit warnings for, returns
1159/// false.
1160static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
1161 const UninitUse &Use,
1162 bool alwaysReportSelfInit = false) {
1163 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) {
1164 // Inspect the initializer of the variable declaration which is
1165 // being referenced prior to its initialization. We emit
1166 // specialized diagnostics for self-initialization, and we
1167 // specifically avoid warning about self references which take the
1168 // form of:
1169 //
1170 // int x = x;
1171 //
1172 // This is used to indicate to GCC that 'x' is intentionally left
1173 // uninitialized. Proven code paths which access 'x' in
1174 // an uninitialized state after this will still warn.
1175 if (const Expr *Initializer = VD->getInit()) {
1176 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
1177 return false;
1178
1179 ContainsReference CR(S.Context, DRE);
1180 CR.Visit(Initializer);
1181 if (CR.doesContainReference()) {
1182 S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
1183 << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
1185 }
1186 }
1187
1188 DiagUninitUse(S, VD, Use, false);
1189 } else {
1190 const BlockExpr *BE = cast<BlockExpr>(Use.getUser());
1191 if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>())
1192 S.Diag(BE->getBeginLoc(),
1193 diag::warn_uninit_byref_blockvar_captured_by_block)
1194 << VD->getDeclName()
1196 else
1197 DiagUninitUse(S, VD, Use, true);
1198 }
1199
1200 // Report where the variable was declared when the use wasn't within
1201 // the initializer of that declaration & we didn't already suggest
1202 // an initialization fixit.
1203 if (!SuggestInitializationFixit(S, VD))
1204 S.Diag(VD->getBeginLoc(), diag::note_var_declared_here)
1205 << VD->getDeclName();
1206
1208}
1209
1210namespace {
1211class FallthroughMapper : public DynamicRecursiveASTVisitor {
1212public:
1213 FallthroughMapper(Sema &S) : FoundSwitchStatements(false), S(S) {
1214 ShouldWalkTypesOfTypeLocs = false;
1215 }
1216
1217 bool foundSwitchStatements() const { return FoundSwitchStatements; }
1218
1219 void markFallthroughVisited(const AttributedStmt *Stmt) {
1220 bool Found = FallthroughStmts.erase(Stmt);
1221 assert(Found);
1222 (void)Found;
1223 }
1224
1226
1227 const AttrStmts &getFallthroughStmts() const { return FallthroughStmts; }
1228
1229 void fillReachableBlocks(CFG *Cfg) {
1230 assert(ReachableBlocks.empty() && "ReachableBlocks already filled");
1231 std::deque<const CFGBlock *> BlockQueue;
1232
1233 ReachableBlocks.insert(&Cfg->getEntry());
1234 BlockQueue.push_back(&Cfg->getEntry());
1235 // Mark all case blocks reachable to avoid problems with switching on
1236 // constants, covered enums, etc.
1237 // These blocks can contain fall-through annotations, and we don't want to
1238 // issue a warn_fallthrough_attr_unreachable for them.
1239 for (const auto *B : *Cfg) {
1240 const Stmt *L = B->getLabel();
1241 if (isa_and_nonnull<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1242 BlockQueue.push_back(B);
1243 }
1244
1245 while (!BlockQueue.empty()) {
1246 const CFGBlock *P = BlockQueue.front();
1247 BlockQueue.pop_front();
1248 for (const CFGBlock *B : P->succs()) {
1249 if (B && ReachableBlocks.insert(B).second)
1250 BlockQueue.push_back(B);
1251 }
1252 }
1253 }
1254
1255 bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt,
1256 bool IsTemplateInstantiation) {
1257 assert(!ReachableBlocks.empty() && "ReachableBlocks empty");
1258
1259 int UnannotatedCnt = 0;
1260 AnnotatedCnt = 0;
1261
1262 std::deque<const CFGBlock *> BlockQueue(B.pred_begin(), B.pred_end());
1263 while (!BlockQueue.empty()) {
1264 const CFGBlock *P = BlockQueue.front();
1265 BlockQueue.pop_front();
1266 if (!P)
1267 continue;
1268
1269 const Stmt *Term = P->getTerminatorStmt();
1270 if (isa_and_nonnull<SwitchStmt>(Term))
1271 continue; // Switch statement, good.
1272
1273 const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel());
1274 if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end())
1275 continue; // Previous case label has no statements, good.
1276
1277 const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel());
1278 if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end())
1279 continue; // Case label is preceded with a normal label, good.
1280
1281 if (!ReachableBlocks.count(P)) {
1282 for (const CFGElement &Elem : llvm::reverse(*P)) {
1283 if (std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>()) {
1284 if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1285 // Don't issue a warning for an unreachable fallthrough
1286 // attribute in template instantiations as it may not be
1287 // unreachable in all instantiations of the template.
1288 if (!IsTemplateInstantiation)
1289 S.Diag(AS->getBeginLoc(),
1290 diag::warn_unreachable_fallthrough_attr);
1291 markFallthroughVisited(AS);
1292 ++AnnotatedCnt;
1293 break;
1294 }
1295 // Don't care about other unreachable statements.
1296 }
1297 }
1298 // If there are no unreachable statements, this may be a special
1299 // case in CFG:
1300 // case X: {
1301 // A a; // A has a destructor.
1302 // break;
1303 // }
1304 // // <<<< This place is represented by a 'hanging' CFG block.
1305 // case Y:
1306 continue;
1307 }
1308
1309 const Stmt *LastStmt = getLastStmt(*P);
1310 if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) {
1311 markFallthroughVisited(AS);
1312 ++AnnotatedCnt;
1313 continue; // Fallthrough annotation, good.
1314 }
1315
1316 if (!LastStmt) { // This block contains no executable statements.
1317 // Traverse its predecessors.
1318 std::copy(P->pred_begin(), P->pred_end(),
1319 std::back_inserter(BlockQueue));
1320 continue;
1321 }
1322
1323 ++UnannotatedCnt;
1324 }
1325 return !!UnannotatedCnt;
1326 }
1327
1328 bool VisitAttributedStmt(AttributedStmt *S) override {
1329 if (asFallThroughAttr(S))
1330 FallthroughStmts.insert(S);
1331 return true;
1332 }
1333
1334 bool VisitSwitchStmt(SwitchStmt *S) override {
1335 FoundSwitchStatements = true;
1336 return true;
1337 }
1338
1339 // We don't want to traverse local type declarations. We analyze their
1340 // methods separately.
1341 bool TraverseDecl(Decl *D) override { return true; }
1342
1343 // We analyze lambda bodies separately. Skip them here.
1344 bool TraverseLambdaExpr(LambdaExpr *LE) override {
1345 // Traverse the captures, but not the body.
1346 for (const auto C : zip(LE->captures(), LE->capture_inits()))
1347 TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
1348 return true;
1349 }
1350
1351 private:
1352
1353 static const AttributedStmt *asFallThroughAttr(const Stmt *S) {
1354 if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1355 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1356 return AS;
1357 }
1358 return nullptr;
1359 }
1360
1361 static const Stmt *getLastStmt(const CFGBlock &B) {
1362 if (const Stmt *Term = B.getTerminatorStmt())
1363 return Term;
1364 for (const CFGElement &Elem : llvm::reverse(B))
1365 if (std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>())
1366 return CS->getStmt();
1367 // Workaround to detect a statement thrown out by CFGBuilder:
1368 // case X: {} case Y:
1369 // case X: ; case Y:
1370 if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel()))
1371 if (!isa<SwitchCase>(SW->getSubStmt()))
1372 return SW->getSubStmt();
1373
1374 return nullptr;
1375 }
1376
1377 bool FoundSwitchStatements;
1378 AttrStmts FallthroughStmts;
1379 Sema &S;
1381};
1382} // anonymous namespace
1383
1386 TokenValue FallthroughTokens[] = {
1387 tok::l_square, tok::l_square,
1388 PP.getIdentifierInfo("fallthrough"),
1389 tok::r_square, tok::r_square
1390 };
1391
1392 TokenValue ClangFallthroughTokens[] = {
1393 tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"),
1394 tok::coloncolon, PP.getIdentifierInfo("fallthrough"),
1395 tok::r_square, tok::r_square
1396 };
1397
1398 bool PreferClangAttr = !PP.getLangOpts().CPlusPlus17 && !PP.getLangOpts().C23;
1399
1400 StringRef MacroName;
1401 if (PreferClangAttr)
1402 MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);
1403 if (MacroName.empty())
1404 MacroName = PP.getLastMacroWithSpelling(Loc, FallthroughTokens);
1405 if (MacroName.empty() && !PreferClangAttr)
1406 MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);
1407 if (MacroName.empty()) {
1408 if (!PreferClangAttr)
1409 MacroName = "[[fallthrough]]";
1410 else if (PP.getLangOpts().CPlusPlus)
1411 MacroName = "[[clang::fallthrough]]";
1412 else
1413 MacroName = "__attribute__((fallthrough))";
1414 }
1415 return MacroName;
1416}
1417
1419 bool PerFunction) {
1420 FallthroughMapper FM(S);
1421 FM.TraverseStmt(AC.getBody());
1422
1423 if (!FM.foundSwitchStatements())
1424 return;
1425
1426 if (PerFunction && FM.getFallthroughStmts().empty())
1427 return;
1428
1429 CFG *Cfg = AC.getCFG();
1430
1431 if (!Cfg)
1432 return;
1433
1434 FM.fillReachableBlocks(Cfg);
1435
1436 for (const CFGBlock *B : llvm::reverse(*Cfg)) {
1437 const Stmt *Label = B->getLabel();
1438
1439 if (!isa_and_nonnull<SwitchCase>(Label))
1440 continue;
1441
1442 int AnnotatedCnt;
1443
1444 bool IsTemplateInstantiation = false;
1445 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(AC.getDecl()))
1446 IsTemplateInstantiation = Function->isTemplateInstantiation();
1447 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1448 IsTemplateInstantiation))
1449 continue;
1450
1451 S.Diag(Label->getBeginLoc(),
1452 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1453 : diag::warn_unannotated_fallthrough);
1454
1455 if (!AnnotatedCnt) {
1456 SourceLocation L = Label->getBeginLoc();
1457 if (L.isMacroID())
1458 continue;
1459
1460 const Stmt *Term = B->getTerminatorStmt();
1461 // Skip empty cases.
1462 while (B->empty() && !Term && B->succ_size() == 1) {
1463 B = *B->succ_begin();
1464 Term = B->getTerminatorStmt();
1465 }
1466 if (!(B->empty() && isa_and_nonnull<BreakStmt>(Term))) {
1467 Preprocessor &PP = S.getPreprocessor();
1468 StringRef AnnotationSpelling = getFallthroughAttrSpelling(PP, L);
1469 SmallString<64> TextToInsert(AnnotationSpelling);
1470 TextToInsert += "; ";
1471 S.Diag(L, diag::note_insert_fallthrough_fixit)
1472 << AnnotationSpelling
1473 << FixItHint::CreateInsertion(L, TextToInsert);
1474 }
1475 S.Diag(L, diag::note_insert_break_fixit)
1476 << FixItHint::CreateInsertion(L, "break; ");
1477 }
1478 }
1479
1480 for (const auto *F : FM.getFallthroughStmts())
1481 S.Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);
1482}
1483
1484static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
1485 const Stmt *S) {
1486 assert(S);
1487
1488 do {
1489 switch (S->getStmtClass()) {
1490 case Stmt::ForStmtClass:
1491 case Stmt::WhileStmtClass:
1492 case Stmt::CXXForRangeStmtClass:
1493 case Stmt::ObjCForCollectionStmtClass:
1494 return true;
1495 case Stmt::DoStmtClass: {
1496 Expr::EvalResult Result;
1497 if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))
1498 return true;
1499 return Result.Val.getInt().getBoolValue();
1500 }
1501 default:
1502 break;
1503 }
1504 } while ((S = PM.getParent(S)));
1505
1506 return false;
1507}
1508
1510 const sema::FunctionScopeInfo *CurFn,
1511 const Decl *D,
1512 const ParentMap &PM) {
1513 typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy;
1514 typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap;
1515 typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector;
1516 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1517 StmtUsesPair;
1518
1519 ASTContext &Ctx = S.getASTContext();
1520
1521 const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses();
1522
1523 // Extract all weak objects that are referenced more than once.
1525 for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
1526 I != E; ++I) {
1527 const WeakUseVector &Uses = I->second;
1528
1529 // Find the first read of the weak object.
1530 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1531 for ( ; UI != UE; ++UI) {
1532 if (UI->isUnsafe())
1533 break;
1534 }
1535
1536 // If there were only writes to this object, don't warn.
1537 if (UI == UE)
1538 continue;
1539
1540 // If there was only one read, followed by any number of writes, and the
1541 // read is not within a loop, don't warn. Additionally, don't warn in a
1542 // loop if the base object is a local variable -- local variables are often
1543 // changed in loops.
1544 if (UI == Uses.begin()) {
1545 WeakUseVector::const_iterator UI2 = UI;
1546 for (++UI2; UI2 != UE; ++UI2)
1547 if (UI2->isUnsafe())
1548 break;
1549
1550 if (UI2 == UE) {
1551 if (!isInLoop(Ctx, PM, UI->getUseExpr()))
1552 continue;
1553
1554 const WeakObjectProfileTy &Profile = I->first;
1555 if (!Profile.isExactProfile())
1556 continue;
1557
1558 const NamedDecl *Base = Profile.getBase();
1559 if (!Base)
1560 Base = Profile.getProperty();
1561 assert(Base && "A profile always has a base or property.");
1562
1563 if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1564 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1565 continue;
1566 }
1567 }
1568
1569 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
1570 }
1571
1572 if (UsesByStmt.empty())
1573 return;
1574
1575 // Sort by first use so that we emit the warnings in a deterministic order.
1577 llvm::sort(UsesByStmt,
1578 [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
1579 return SM.isBeforeInTranslationUnit(LHS.first->getBeginLoc(),
1580 RHS.first->getBeginLoc());
1581 });
1582
1583 // Classify the current code body for better warning text.
1584 // This enum should stay in sync with the cases in
1585 // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
1586 // FIXME: Should we use a common classification enum and the same set of
1587 // possibilities all throughout Sema?
1588 enum {
1589 Function,
1590 Method,
1591 Block,
1592 Lambda
1593 } FunctionKind;
1594
1595 if (isa<sema::BlockScopeInfo>(CurFn))
1596 FunctionKind = Block;
1597 else if (isa<sema::LambdaScopeInfo>(CurFn))
1598 FunctionKind = Lambda;
1599 else if (isa<ObjCMethodDecl>(D))
1600 FunctionKind = Method;
1601 else
1602 FunctionKind = Function;
1603
1604 // Iterate through the sorted problems and emit warnings for each.
1605 for (const auto &P : UsesByStmt) {
1606 const Stmt *FirstRead = P.first;
1607 const WeakObjectProfileTy &Key = P.second->first;
1608 const WeakUseVector &Uses = P.second->second;
1609
1610 // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy
1611 // may not contain enough information to determine that these are different
1612 // properties. We can only be 100% sure of a repeated use in certain cases,
1613 // and we adjust the diagnostic kind accordingly so that the less certain
1614 // case can be turned off if it is too noisy.
1615 unsigned DiagKind;
1616 if (Key.isExactProfile())
1617 DiagKind = diag::warn_arc_repeated_use_of_weak;
1618 else
1619 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1620
1621 // Classify the weak object being accessed for better warning text.
1622 // This enum should stay in sync with the cases in
1623 // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
1624 enum {
1625 Variable,
1626 Property,
1627 ImplicitProperty,
1628 Ivar
1629 } ObjectKind;
1630
1631 const NamedDecl *KeyProp = Key.getProperty();
1632 if (isa<VarDecl>(KeyProp))
1633 ObjectKind = Variable;
1634 else if (isa<ObjCPropertyDecl>(KeyProp))
1635 ObjectKind = Property;
1636 else if (isa<ObjCMethodDecl>(KeyProp))
1637 ObjectKind = ImplicitProperty;
1638 else if (isa<ObjCIvarDecl>(KeyProp))
1639 ObjectKind = Ivar;
1640 else
1641 llvm_unreachable("Unexpected weak object kind!");
1642
1643 // Do not warn about IBOutlet weak property receivers being set to null
1644 // since they are typically only used from the main thread.
1645 if (const ObjCPropertyDecl *Prop = dyn_cast<ObjCPropertyDecl>(KeyProp))
1646 if (Prop->hasAttr<IBOutletAttr>())
1647 continue;
1648
1649 // Show the first time the object was read.
1650 S.Diag(FirstRead->getBeginLoc(), DiagKind)
1651 << int(ObjectKind) << KeyProp << int(FunctionKind)
1652 << FirstRead->getSourceRange();
1653
1654 // Print all the other accesses as notes.
1655 for (const auto &Use : Uses) {
1656 if (Use.getUseExpr() == FirstRead)
1657 continue;
1658 S.Diag(Use.getUseExpr()->getBeginLoc(),
1659 diag::note_arc_weak_also_accessed_here)
1660 << Use.getUseExpr()->getSourceRange();
1661 }
1662 }
1663}
1664
1665namespace clang {
1666namespace {
1668typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
1669typedef std::list<DelayedDiag> DiagList;
1670
1671struct SortDiagBySourceLocation {
1673 SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}
1674
1675 bool operator()(const DelayedDiag &left, const DelayedDiag &right) {
1676 // Although this call will be slow, this is only called when outputting
1677 // multiple warnings.
1678 return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
1679 }
1680};
1681} // anonymous namespace
1682} // namespace clang
1683
1684namespace {
1685class UninitValsDiagReporter : public UninitVariablesHandler {
1686 Sema &S;
1687 typedef SmallVector<UninitUse, 2> UsesVec;
1688 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1689 // Prefer using MapVector to DenseMap, so that iteration order will be
1690 // the same as insertion order. This is needed to obtain a deterministic
1691 // order of diagnostics when calling flushDiagnostics().
1692 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1693 UsesMap uses;
1694
1695public:
1696 UninitValsDiagReporter(Sema &S) : S(S) {}
1697 ~UninitValsDiagReporter() override { flushDiagnostics(); }
1698
1699 MappedType &getUses(const VarDecl *vd) {
1700 MappedType &V = uses[vd];
1701 if (!V.getPointer())
1702 V.setPointer(new UsesVec());
1703 return V;
1704 }
1705
1706 void handleUseOfUninitVariable(const VarDecl *vd,
1707 const UninitUse &use) override {
1708 getUses(vd).getPointer()->push_back(use);
1709 }
1710
1711 void handleSelfInit(const VarDecl *vd) override { getUses(vd).setInt(true); }
1712
1713 void flushDiagnostics() {
1714 for (const auto &P : uses) {
1715 const VarDecl *vd = P.first;
1716 const MappedType &V = P.second;
1717
1718 UsesVec *vec = V.getPointer();
1719 bool hasSelfInit = V.getInt();
1720
1721 diagnoseUnitializedVar(vd, hasSelfInit, vec);
1722
1723 // Release the uses vector.
1724 delete vec;
1725 }
1726
1727 uses.clear();
1728 }
1729
1730private:
1731 static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
1732 return llvm::any_of(*vec, [](const UninitUse &U) {
1733 return U.getKind() == UninitUse::Always ||
1734 U.getKind() == UninitUse::AfterCall ||
1735 U.getKind() == UninitUse::AfterDecl;
1736 });
1737 }
1738
1739 // Print the diagnostic for the variable. We try to warn only on the first
1740 // point at which a variable is used uninitialized. After the first
1741 // diagnostic is printed, further diagnostics for this variable are skipped.
1742 void diagnoseUnitializedVar(const VarDecl *vd, bool hasSelfInit,
1743 UsesVec *vec) {
1744 // Specially handle the case where we have uses of an uninitialized
1745 // variable, but the root cause is an idiomatic self-init. We want
1746 // to report the diagnostic at the self-init since that is the root cause.
1747 if (hasSelfInit && hasAlwaysUninitializedUse(vec)) {
1748 if (DiagnoseUninitializedUse(S, vd,
1750 /*isAlwaysUninit=*/true),
1751 /*alwaysReportSelfInit=*/true))
1752 return;
1753 }
1754
1755 // Sort the uses by their SourceLocations. While not strictly
1756 // guaranteed to produce them in line/column order, this will provide
1757 // a stable ordering.
1758 llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {
1759 // Prefer the direct use of an uninitialized variable over its use via
1760 // constant reference or pointer.
1761 if (a.isConstRefOrPtrUse() != b.isConstRefOrPtrUse())
1762 return b.isConstRefOrPtrUse();
1763 // Prefer a more confident report over a less confident one.
1764 if (a.getKind() != b.getKind())
1765 return a.getKind() > b.getKind();
1766 return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();
1767 });
1768
1769 for (const auto &U : *vec) {
1770 if (U.isConstRefUse()) {
1772 return;
1773 } else if (U.isConstPtrUse()) {
1775 return;
1776 } else {
1777 // If we have self-init, downgrade all uses to 'may be uninitialized'.
1778 UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
1779 if (DiagnoseUninitializedUse(S, vd, Use))
1780 return;
1781 }
1782 }
1783 }
1784};
1785
1786/// Inter-procedural data for the called-once checker.
1787class CalledOnceInterProceduralData {
1788public:
1789 // Add the delayed warning for the given block.
1790 void addDelayedWarning(const BlockDecl *Block,
1792 DelayedBlockWarnings[Block].emplace_back(std::move(Warning));
1793 }
1794 // Report all of the warnings we've gathered for the given block.
1795 void flushWarnings(const BlockDecl *Block, Sema &S) {
1796 for (const PartialDiagnosticAt &Delayed : DelayedBlockWarnings[Block])
1797 S.Diag(Delayed.first, Delayed.second);
1798
1799 discardWarnings(Block);
1800 }
1801 // Discard all of the warnings we've gathered for the given block.
1802 void discardWarnings(const BlockDecl *Block) {
1803 DelayedBlockWarnings.erase(Block);
1804 }
1805
1806private:
1807 using DelayedDiagnostics = SmallVector<PartialDiagnosticAt, 2>;
1808 llvm::DenseMap<const BlockDecl *, DelayedDiagnostics> DelayedBlockWarnings;
1809};
1810
1811class CalledOnceCheckReporter : public CalledOnceCheckHandler {
1812public:
1813 CalledOnceCheckReporter(Sema &S, CalledOnceInterProceduralData &Data)
1814 : S(S), Data(Data) {}
1815 void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call,
1816 const Expr *PrevCall, bool IsCompletionHandler,
1817 bool Poised) override {
1818 auto DiagToReport = IsCompletionHandler
1819 ? diag::warn_completion_handler_called_twice
1820 : diag::warn_called_once_gets_called_twice;
1821 S.Diag(Call->getBeginLoc(), DiagToReport) << Parameter;
1822 S.Diag(PrevCall->getBeginLoc(), diag::note_called_once_gets_called_twice)
1823 << Poised;
1824 }
1825
1827 bool IsCompletionHandler) override {
1828 auto DiagToReport = IsCompletionHandler
1829 ? diag::warn_completion_handler_never_called
1830 : diag::warn_called_once_never_called;
1831 S.Diag(Parameter->getBeginLoc(), DiagToReport)
1832 << Parameter << /* Captured */ false;
1833 }
1834
1835 void handleNeverCalled(const ParmVarDecl *Parameter, const Decl *Function,
1836 const Stmt *Where, NeverCalledReason Reason,
1837 bool IsCalledDirectly,
1838 bool IsCompletionHandler) override {
1839 auto DiagToReport = IsCompletionHandler
1840 ? diag::warn_completion_handler_never_called_when
1841 : diag::warn_called_once_never_called_when;
1842 PartialDiagnosticAt Warning(Where->getBeginLoc(), S.PDiag(DiagToReport)
1843 << Parameter
1844 << IsCalledDirectly
1845 << (unsigned)Reason);
1846
1847 if (const auto *Block = dyn_cast<BlockDecl>(Function)) {
1848 // We shouldn't report these warnings on blocks immediately
1849 Data.addDelayedWarning(Block, std::move(Warning));
1850 } else {
1851 S.Diag(Warning.first, Warning.second);
1852 }
1853 }
1854
1856 const Decl *Where,
1857 bool IsCompletionHandler) override {
1858 auto DiagToReport = IsCompletionHandler
1859 ? diag::warn_completion_handler_never_called
1860 : diag::warn_called_once_never_called;
1861 S.Diag(Where->getBeginLoc(), DiagToReport)
1862 << Parameter << /* Captured */ true;
1863 }
1864
1865 void
1867 Data.flushWarnings(Block, S);
1868 }
1869
1870 void handleBlockWithNoGuarantees(const BlockDecl *Block) override {
1871 Data.discardWarnings(Block);
1872 }
1873
1874private:
1875 Sema &S;
1876 CalledOnceInterProceduralData &Data;
1877};
1878
1879constexpr unsigned CalledOnceWarnings[] = {
1880 diag::warn_called_once_never_called,
1881 diag::warn_called_once_never_called_when,
1882 diag::warn_called_once_gets_called_twice};
1883
1884constexpr unsigned CompletionHandlerWarnings[]{
1885 diag::warn_completion_handler_never_called,
1886 diag::warn_completion_handler_never_called_when,
1887 diag::warn_completion_handler_called_twice};
1888
1889bool shouldAnalyzeCalledOnceImpl(llvm::ArrayRef<unsigned> DiagIDs,
1890 const DiagnosticsEngine &Diags,
1891 SourceLocation At) {
1892 return llvm::any_of(DiagIDs, [&Diags, At](unsigned DiagID) {
1893 return !Diags.isIgnored(DiagID, At);
1894 });
1895}
1896
1897bool shouldAnalyzeCalledOnceConventions(const DiagnosticsEngine &Diags,
1898 SourceLocation At) {
1899 return shouldAnalyzeCalledOnceImpl(CompletionHandlerWarnings, Diags, At);
1900}
1901
1902bool shouldAnalyzeCalledOnceParameters(const DiagnosticsEngine &Diags,
1903 SourceLocation At) {
1904 return shouldAnalyzeCalledOnceImpl(CalledOnceWarnings, Diags, At) ||
1905 shouldAnalyzeCalledOnceConventions(Diags, At);
1906}
1907} // anonymous namespace
1908
1909//===----------------------------------------------------------------------===//
1910// -Wthread-safety
1911//===----------------------------------------------------------------------===//
1912namespace clang {
1913namespace threadSafety {
1914namespace {
1915class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
1916 Sema &S;
1917 DiagList Warnings;
1918 SourceLocation FunLocation, FunEndLocation;
1919
1920 const FunctionDecl *CurrentFunction;
1921 bool Verbose;
1922
1923 OptionalNotes getNotes() const {
1924 if (Verbose && CurrentFunction) {
1925 PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
1926 S.PDiag(diag::note_thread_warning_in_fun)
1927 << CurrentFunction);
1928 return OptionalNotes(1, FNote);
1929 }
1930 return OptionalNotes();
1931 }
1932
1933 OptionalNotes getNotes(const PartialDiagnosticAt &Note) const {
1934 OptionalNotes ONS(1, Note);
1935 if (Verbose && CurrentFunction) {
1936 PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
1937 S.PDiag(diag::note_thread_warning_in_fun)
1938 << CurrentFunction);
1939 ONS.push_back(std::move(FNote));
1940 }
1941 return ONS;
1942 }
1943
1944 OptionalNotes getNotes(const PartialDiagnosticAt &Note1,
1945 const PartialDiagnosticAt &Note2) const {
1946 OptionalNotes ONS;
1947 ONS.push_back(Note1);
1948 ONS.push_back(Note2);
1949 if (Verbose && CurrentFunction) {
1950 PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
1951 S.PDiag(diag::note_thread_warning_in_fun)
1952 << CurrentFunction);
1953 ONS.push_back(std::move(FNote));
1954 }
1955 return ONS;
1956 }
1957
1958 OptionalNotes makeLockedHereNote(SourceLocation LocLocked, StringRef Kind) {
1959 return LocLocked.isValid()
1960 ? getNotes(PartialDiagnosticAt(
1961 LocLocked, S.PDiag(diag::note_locked_here) << Kind))
1962 : getNotes();
1963 }
1964
1965 OptionalNotes makeUnlockedHereNote(SourceLocation LocUnlocked,
1966 StringRef Kind) {
1967 return LocUnlocked.isValid()
1968 ? getNotes(PartialDiagnosticAt(
1969 LocUnlocked, S.PDiag(diag::note_unlocked_here) << Kind))
1970 : getNotes();
1971 }
1972
1973 OptionalNotes makeManagedMismatchNoteForParam(SourceLocation DeclLoc) {
1974 return DeclLoc.isValid()
1975 ? getNotes(PartialDiagnosticAt(
1976 DeclLoc,
1977 S.PDiag(diag::note_managed_mismatch_here_for_param)))
1978 : getNotes();
1979 }
1980
1981 public:
1982 ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL)
1983 : S(S), FunLocation(FL), FunEndLocation(FEL),
1984 CurrentFunction(nullptr), Verbose(false) {}
1985
1986 void setVerbose(bool b) { Verbose = b; }
1987
1988 /// Emit all buffered diagnostics in order of sourcelocation.
1989 /// We need to output diagnostics produced while iterating through
1990 /// the lockset in deterministic order, so this function orders diagnostics
1991 /// and outputs them.
1992 void emitDiagnostics() {
1993 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
1994 for (const auto &Diag : Warnings) {
1995 S.Diag(Diag.first.first, Diag.first.second);
1996 for (const auto &Note : Diag.second)
1997 S.Diag(Note.first, Note.second);
1998 }
1999 }
2000
2001 void handleUnmatchedUnderlyingMutexes(SourceLocation Loc, SourceLocation DLoc,
2002 Name scopeName, StringRef Kind,
2003 Name expected, Name actual) override {
2005 S.PDiag(diag::warn_unmatched_underlying_mutexes)
2006 << Kind << scopeName << expected << actual);
2007 Warnings.emplace_back(std::move(Warning),
2008 makeManagedMismatchNoteForParam(DLoc));
2009 }
2010
2011 void handleExpectMoreUnderlyingMutexes(SourceLocation Loc,
2012 SourceLocation DLoc, Name scopeName,
2013 StringRef Kind,
2014 Name expected) override {
2016 Loc, S.PDiag(diag::warn_expect_more_underlying_mutexes)
2017 << Kind << scopeName << expected);
2018 Warnings.emplace_back(std::move(Warning),
2019 makeManagedMismatchNoteForParam(DLoc));
2020 }
2021
2022 void handleExpectFewerUnderlyingMutexes(SourceLocation Loc,
2023 SourceLocation DLoc, Name scopeName,
2024 StringRef Kind,
2025 Name actual) override {
2027 Loc, S.PDiag(diag::warn_expect_fewer_underlying_mutexes)
2028 << Kind << scopeName << actual);
2029 Warnings.emplace_back(std::move(Warning),
2030 makeManagedMismatchNoteForParam(DLoc));
2031 }
2032
2033 void handleInvalidLockExp(SourceLocation Loc) override {
2034 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock)
2035 << Loc);
2036 Warnings.emplace_back(std::move(Warning), getNotes());
2037 }
2038
2039 void handleUnmatchedUnlock(StringRef Kind, Name LockName, SourceLocation Loc,
2040 SourceLocation LocPreviousUnlock) override {
2041 if (Loc.isInvalid())
2042 Loc = FunLocation;
2043 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_but_no_lock)
2044 << Kind << LockName);
2045 Warnings.emplace_back(std::move(Warning),
2046 makeUnlockedHereNote(LocPreviousUnlock, Kind));
2047 }
2048
2049 void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
2050 LockKind Expected, LockKind Received,
2051 SourceLocation LocLocked,
2052 SourceLocation LocUnlock) override {
2053 if (LocUnlock.isInvalid())
2054 LocUnlock = FunLocation;
2056 LocUnlock, S.PDiag(diag::warn_unlock_kind_mismatch)
2057 << Kind << LockName << Received << Expected);
2058 Warnings.emplace_back(std::move(Warning),
2059 makeLockedHereNote(LocLocked, Kind));
2060 }
2061
2062 void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation LocLocked,
2063 SourceLocation LocDoubleLock) override {
2064 if (LocDoubleLock.isInvalid())
2065 LocDoubleLock = FunLocation;
2066 PartialDiagnosticAt Warning(LocDoubleLock, S.PDiag(diag::warn_double_lock)
2067 << Kind << LockName);
2068 Warnings.emplace_back(std::move(Warning),
2069 makeLockedHereNote(LocLocked, Kind));
2070 }
2071
2072 void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
2073 SourceLocation LocLocked,
2074 SourceLocation LocEndOfScope,
2075 LockErrorKind LEK,
2076 bool ReentrancyMismatch) override {
2077 unsigned DiagID = 0;
2078 switch (LEK) {
2080 DiagID = diag::warn_lock_some_predecessors;
2081 break;
2083 DiagID = diag::warn_expecting_lock_held_on_loop;
2084 break;
2086 DiagID = diag::warn_no_unlock;
2087 break;
2089 DiagID = diag::warn_expecting_locked;
2090 break;
2091 }
2092 if (LocEndOfScope.isInvalid())
2093 LocEndOfScope = FunEndLocation;
2094
2095 PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID)
2096 << Kind << LockName
2097 << ReentrancyMismatch);
2098 Warnings.emplace_back(std::move(Warning),
2099 makeLockedHereNote(LocLocked, Kind));
2100 }
2101
2102 void handleExclusiveAndShared(StringRef Kind, Name LockName,
2103 SourceLocation Loc1,
2104 SourceLocation Loc2) override {
2106 S.PDiag(diag::warn_lock_exclusive_and_shared)
2107 << Kind << LockName);
2108 PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared)
2109 << Kind << LockName);
2110 Warnings.emplace_back(std::move(Warning), getNotes(Note));
2111 }
2112
2113 void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
2114 AccessKind AK, SourceLocation Loc) override {
2115 unsigned DiagID = 0;
2116 switch (POK) {
2117 case POK_VarAccess:
2118 case POK_PassByRef:
2119 case POK_ReturnByRef:
2120 case POK_PassPointer:
2121 case POK_ReturnPointer:
2122 DiagID = diag::warn_variable_requires_any_lock;
2123 break;
2124 case POK_VarDereference:
2125 case POK_PtPassByRef:
2126 case POK_PtReturnByRef:
2127 case POK_PtPassPointer:
2129 DiagID = diag::warn_var_deref_requires_any_lock;
2130 break;
2131 case POK_FunctionCall:
2132 llvm_unreachable("Only works for variables");
2133 break;
2134 }
2136 << D << getLockKindFromAccessKind(AK));
2137 Warnings.emplace_back(std::move(Warning), getNotes());
2138 }
2139
2140 void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
2141 ProtectedOperationKind POK, Name LockName,
2143 Name *PossibleMatch) override {
2144 unsigned DiagID = 0;
2145 if (PossibleMatch) {
2146 switch (POK) {
2147 case POK_VarAccess:
2148 DiagID = diag::warn_variable_requires_lock_precise;
2149 break;
2150 case POK_VarDereference:
2151 DiagID = diag::warn_var_deref_requires_lock_precise;
2152 break;
2153 case POK_FunctionCall:
2154 DiagID = diag::warn_fun_requires_lock_precise;
2155 break;
2156 case POK_PassByRef:
2157 DiagID = diag::warn_guarded_pass_by_reference;
2158 break;
2159 case POK_PtPassByRef:
2160 DiagID = diag::warn_pt_guarded_pass_by_reference;
2161 break;
2162 case POK_ReturnByRef:
2163 DiagID = diag::warn_guarded_return_by_reference;
2164 break;
2165 case POK_PtReturnByRef:
2166 DiagID = diag::warn_pt_guarded_return_by_reference;
2167 break;
2168 case POK_PassPointer:
2169 DiagID = diag::warn_guarded_pass_pointer;
2170 break;
2171 case POK_PtPassPointer:
2172 DiagID = diag::warn_pt_guarded_pass_pointer;
2173 break;
2174 case POK_ReturnPointer:
2175 DiagID = diag::warn_guarded_return_pointer;
2176 break;
2178 DiagID = diag::warn_pt_guarded_return_pointer;
2179 break;
2180 }
2181 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
2182 << D
2183 << LockName << LK);
2184 PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
2185 << *PossibleMatch);
2186 if (Verbose && POK == POK_VarAccess) {
2188 S.PDiag(diag::note_guarded_by_declared_here)
2189 << D->getDeclName());
2190 Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote));
2191 } else
2192 Warnings.emplace_back(std::move(Warning), getNotes(Note));
2193 } else {
2194 switch (POK) {
2195 case POK_VarAccess:
2196 DiagID = diag::warn_variable_requires_lock;
2197 break;
2198 case POK_VarDereference:
2199 DiagID = diag::warn_var_deref_requires_lock;
2200 break;
2201 case POK_FunctionCall:
2202 DiagID = diag::warn_fun_requires_lock;
2203 break;
2204 case POK_PassByRef:
2205 DiagID = diag::warn_guarded_pass_by_reference;
2206 break;
2207 case POK_PtPassByRef:
2208 DiagID = diag::warn_pt_guarded_pass_by_reference;
2209 break;
2210 case POK_ReturnByRef:
2211 DiagID = diag::warn_guarded_return_by_reference;
2212 break;
2213 case POK_PtReturnByRef:
2214 DiagID = diag::warn_pt_guarded_return_by_reference;
2215 break;
2216 case POK_PassPointer:
2217 DiagID = diag::warn_guarded_pass_pointer;
2218 break;
2219 case POK_PtPassPointer:
2220 DiagID = diag::warn_pt_guarded_pass_pointer;
2221 break;
2222 case POK_ReturnPointer:
2223 DiagID = diag::warn_guarded_return_pointer;
2224 break;
2226 DiagID = diag::warn_pt_guarded_return_pointer;
2227 break;
2228 }
2229 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
2230 << D
2231 << LockName << LK);
2232 if (Verbose && POK == POK_VarAccess) {
2234 S.PDiag(diag::note_guarded_by_declared_here));
2235 Warnings.emplace_back(std::move(Warning), getNotes(Note));
2236 } else
2237 Warnings.emplace_back(std::move(Warning), getNotes());
2238 }
2239 }
2240
2241 void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
2242 SourceLocation Loc) override {
2244 S.PDiag(diag::warn_acquire_requires_negative_cap)
2245 << Kind << LockName << Neg);
2246 Warnings.emplace_back(std::move(Warning), getNotes());
2247 }
2248
2249 void handleNegativeNotHeld(const NamedDecl *D, Name LockName,
2250 SourceLocation Loc) override {
2252 Loc, S.PDiag(diag::warn_fun_requires_negative_cap) << D << LockName);
2253 Warnings.emplace_back(std::move(Warning), getNotes());
2254 }
2255
2256 void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
2257 SourceLocation Loc) override {
2258 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
2259 << Kind << FunName << LockName);
2260 Warnings.emplace_back(std::move(Warning), getNotes());
2261 }
2262
2263 void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
2264 SourceLocation Loc) override {
2266 S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
2267 Warnings.emplace_back(std::move(Warning), getNotes());
2268 }
2269
2270 void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override {
2272 S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
2273 Warnings.emplace_back(std::move(Warning), getNotes());
2274 }
2275
2276 void enterFunction(const FunctionDecl* FD) override {
2277 CurrentFunction = FD;
2278 }
2279
2280 void leaveFunction(const FunctionDecl* FD) override {
2281 CurrentFunction = nullptr;
2282 }
2283};
2284} // anonymous namespace
2285} // namespace threadSafety
2286} // namespace clang
2287
2288//===----------------------------------------------------------------------===//
2289// -Wconsumed
2290//===----------------------------------------------------------------------===//
2291
2292namespace clang {
2293namespace consumed {
2294namespace {
2295class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase {
2296
2297 Sema &S;
2298 DiagList Warnings;
2299
2300public:
2301
2302 ConsumedWarningsHandler(Sema &S) : S(S) {}
2303
2304 void emitDiagnostics() override {
2305 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
2306 for (const auto &Diag : Warnings) {
2307 S.Diag(Diag.first.first, Diag.first.second);
2308 for (const auto &Note : Diag.second)
2309 S.Diag(Note.first, Note.second);
2310 }
2311 }
2312
2313 void warnLoopStateMismatch(SourceLocation Loc,
2314 StringRef VariableName) override {
2315 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) <<
2316 VariableName);
2317
2318 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2319 }
2320
2321 void warnParamReturnTypestateMismatch(SourceLocation Loc,
2322 StringRef VariableName,
2323 StringRef ExpectedState,
2324 StringRef ObservedState) override {
2325
2327 diag::warn_param_return_typestate_mismatch) << VariableName <<
2328 ExpectedState << ObservedState);
2329
2330 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2331 }
2332
2333 void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
2334 StringRef ObservedState) override {
2335
2337 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
2338
2339 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2340 }
2341
2342 void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
2343 StringRef TypeName) override {
2345 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
2346
2347 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2348 }
2349
2350 void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
2351 StringRef ObservedState) override {
2352
2354 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
2355
2356 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2357 }
2358
2359 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
2360 SourceLocation Loc) override {
2361
2363 diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
2364
2365 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2366 }
2367
2368 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
2369 StringRef State, SourceLocation Loc) override {
2370
2371 PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
2372 MethodName << VariableName << State);
2373
2374 Warnings.emplace_back(std::move(Warning), OptionalNotes());
2375 }
2376};
2377} // anonymous namespace
2378} // namespace consumed
2379} // namespace clang
2380
2381//===----------------------------------------------------------------------===//
2382// Unsafe buffer usage analysis.
2383//===----------------------------------------------------------------------===//
2384
2385namespace {
2386class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler {
2387 Sema &S;
2388 bool SuggestSuggestions; // Recommend -fsafe-buffer-usage-suggestions?
2389
2390 // Lists as a string the names of variables in `VarGroupForVD` except for `VD`
2391 // itself:
2392 std::string listVariableGroupAsString(
2393 const VarDecl *VD, const ArrayRef<const VarDecl *> &VarGroupForVD) const {
2394 if (VarGroupForVD.size() <= 1)
2395 return "";
2396
2397 std::vector<StringRef> VarNames;
2398 auto PutInQuotes = [](StringRef S) -> std::string {
2399 return "'" + S.str() + "'";
2400 };
2401
2402 for (auto *V : VarGroupForVD) {
2403 if (V == VD)
2404 continue;
2405 VarNames.push_back(V->getName());
2406 }
2407 if (VarNames.size() == 1) {
2408 return PutInQuotes(VarNames[0]);
2409 }
2410 if (VarNames.size() == 2) {
2411 return PutInQuotes(VarNames[0]) + " and " + PutInQuotes(VarNames[1]);
2412 }
2413 assert(VarGroupForVD.size() > 3);
2414 const unsigned N = VarNames.size() -
2415 2; // need to print the last two names as "..., X, and Y"
2416 std::string AllVars = "";
2417
2418 for (unsigned I = 0; I < N; ++I)
2419 AllVars.append(PutInQuotes(VarNames[I]) + ", ");
2420 AllVars.append(PutInQuotes(VarNames[N]) + ", and " +
2421 PutInQuotes(VarNames[N + 1]));
2422 return AllVars;
2423 }
2424
2425public:
2426 UnsafeBufferUsageReporter(Sema &S, bool SuggestSuggestions)
2427 : S(S), SuggestSuggestions(SuggestSuggestions) {}
2428
2429 void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl,
2430 ASTContext &Ctx) override {
2433 unsigned MsgParam = 0;
2434 NamedDecl *D = nullptr;
2435 if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Operation)) {
2436 Loc = ASE->getBase()->getExprLoc();
2437 Range = ASE->getBase()->getSourceRange();
2438 MsgParam = 2;
2439 } else if (const auto *BO = dyn_cast<BinaryOperator>(Operation)) {
2441 if (Op == BO_Add || Op == BO_AddAssign || Op == BO_Sub ||
2442 Op == BO_SubAssign) {
2443 if (BO->getRHS()->getType()->isIntegerType()) {
2444 Loc = BO->getLHS()->getExprLoc();
2445 Range = BO->getLHS()->getSourceRange();
2446 } else {
2447 Loc = BO->getRHS()->getExprLoc();
2448 Range = BO->getRHS()->getSourceRange();
2449 }
2450 MsgParam = 1;
2451 }
2452 } else if (const auto *UO = dyn_cast<UnaryOperator>(Operation)) {
2454 if (Op == UO_PreInc || Op == UO_PreDec || Op == UO_PostInc ||
2455 Op == UO_PostDec) {
2456 Loc = UO->getSubExpr()->getExprLoc();
2457 Range = UO->getSubExpr()->getSourceRange();
2458 MsgParam = 1;
2459 }
2460 } else {
2461 if (isa<CallExpr>(Operation) || isa<CXXConstructExpr>(Operation)) {
2462 // note_unsafe_buffer_operation doesn't have this mode yet.
2463 assert(!IsRelatedToDecl && "Not implemented yet!");
2464 MsgParam = 3;
2465 } else if (isa<MemberExpr>(Operation)) {
2466 // note_unsafe_buffer_operation doesn't have this mode yet.
2467 assert(!IsRelatedToDecl && "Not implemented yet!");
2468 auto *ME = cast<MemberExpr>(Operation);
2469 D = ME->getMemberDecl();
2470 MsgParam = 5;
2471 } else if (const auto *ECE = dyn_cast<ExplicitCastExpr>(Operation)) {
2472 QualType destType = ECE->getType();
2473 bool destTypeComplete = true;
2474
2475 if (!isa<PointerType>(destType))
2476 return;
2477 destType = destType.getTypePtr()->getPointeeType();
2478 if (const auto *D = destType->getAsTagDecl())
2479 destTypeComplete = D->isCompleteDefinition();
2480
2481 // If destination type is incomplete, it is unsafe to cast to anyway, no
2482 // need to check its type:
2483 if (destTypeComplete) {
2484 const uint64_t dSize = Ctx.getTypeSize(destType);
2485 QualType srcType = ECE->getSubExpr()->getType();
2486
2487 assert(srcType->isPointerType());
2488
2489 const uint64_t sSize =
2490 Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType());
2491
2492 if (sSize >= dSize)
2493 return;
2494 }
2495 if (const auto *CE = dyn_cast<CXXMemberCallExpr>(
2496 ECE->getSubExpr()->IgnoreParens())) {
2497 D = CE->getMethodDecl();
2498 }
2499
2500 if (!D)
2501 return;
2502
2503 MsgParam = 4;
2504 }
2505 Loc = Operation->getBeginLoc();
2506 Range = Operation->getSourceRange();
2507 }
2508 if (IsRelatedToDecl) {
2509 assert(!SuggestSuggestions &&
2510 "Variables blamed for unsafe buffer usage without suggestions!");
2511 S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range;
2512 } else {
2513 if (D) {
2514 S.Diag(Loc, diag::warn_unsafe_buffer_operation)
2515 << MsgParam << D << Range;
2516 } else {
2517 S.Diag(Loc, diag::warn_unsafe_buffer_operation) << MsgParam << Range;
2518 }
2519 if (SuggestSuggestions) {
2520 S.Diag(Loc, diag::note_safe_buffer_usage_suggestions_disabled);
2521 }
2522 }
2523 }
2524
2525 void handleUnsafeLibcCall(const CallExpr *Call, unsigned PrintfInfo,
2526 ASTContext &Ctx,
2527 const Expr *UnsafeArg = nullptr) override {
2528 S.Diag(Call->getBeginLoc(), diag::warn_unsafe_buffer_libc_call)
2529 << Call->getDirectCallee() // We've checked there is a direct callee
2530 << Call->getSourceRange();
2531 if (PrintfInfo > 0) {
2532 SourceRange R =
2533 UnsafeArg ? UnsafeArg->getSourceRange() : Call->getSourceRange();
2534 S.Diag(R.getBegin(), diag::note_unsafe_buffer_printf_call)
2535 << PrintfInfo << R;
2536 }
2537 }
2538
2539 void handleUnsafeOperationInContainer(const Stmt *Operation,
2540 bool IsRelatedToDecl,
2541 ASTContext &Ctx) override {
2544 unsigned MsgParam = 0;
2545
2546 // This function only handles SpanTwoParamConstructorGadget so far, which
2547 // always gives a CXXConstructExpr.
2548 const auto *CtorExpr = cast<CXXConstructExpr>(Operation);
2549 Loc = CtorExpr->getLocation();
2550
2551 S.Diag(Loc, diag::warn_unsafe_buffer_usage_in_container);
2552 if (IsRelatedToDecl) {
2553 assert(!SuggestSuggestions &&
2554 "Variables blamed for unsafe buffer usage without suggestions!");
2555 S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range;
2556 }
2557 }
2558
2560 const VariableGroupsManager &VarGrpMgr,
2561 FixItList &&Fixes, const Decl *D,
2562 const FixitStrategy &VarTargetTypes) override {
2563 assert(!SuggestSuggestions &&
2564 "Unsafe buffer usage fixits displayed without suggestions!");
2565 S.Diag(Variable->getLocation(), diag::warn_unsafe_buffer_variable)
2566 << Variable << (Variable->getType()->isPointerType() ? 0 : 1)
2568 if (!Fixes.empty()) {
2569 assert(isa<NamedDecl>(D) &&
2570 "Fix-its are generated only for `NamedDecl`s");
2571 const NamedDecl *ND = cast<NamedDecl>(D);
2572 bool BriefMsg = false;
2573 // If the variable group involves parameters, the diagnostic message will
2574 // NOT explain how the variables are grouped as the reason is non-trivial
2575 // and irrelavant to users' experience:
2576 const auto VarGroupForVD = VarGrpMgr.getGroupOfVar(Variable, &BriefMsg);
2577 unsigned FixItStrategy = 0;
2578 switch (VarTargetTypes.lookup(Variable)) {
2580 FixItStrategy = 0;
2581 break;
2583 FixItStrategy = 1;
2584 break;
2585 default:
2586 assert(false && "We support only std::span and std::array");
2587 };
2588
2589 const auto &FD =
2591 BriefMsg ? diag::note_unsafe_buffer_variable_fixit_together
2592 : diag::note_unsafe_buffer_variable_fixit_group);
2593
2594 FD << Variable << FixItStrategy;
2595 FD << listVariableGroupAsString(Variable, VarGroupForVD)
2596 << (VarGroupForVD.size() > 1) << ND;
2597 for (const auto &F : Fixes) {
2598 FD << F;
2599 }
2600 }
2601
2602#ifndef NDEBUG
2604 for (const DebugNote &Note: DebugNotesByVar[Variable])
2605 S.Diag(Note.first, diag::note_safe_buffer_debug_mode) << Note.second;
2606#endif
2607 }
2608
2609 bool isSafeBufferOptOut(const SourceLocation &Loc) const override {
2611 }
2612
2613 bool ignoreUnsafeBufferInContainer(const SourceLocation &Loc) const override {
2614 return S.Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container, Loc);
2615 }
2616
2617 bool ignoreUnsafeBufferInLibcCall(const SourceLocation &Loc) const override {
2618 return S.Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, Loc);
2619 }
2620
2621 // Returns the text representation of clang::unsafe_buffer_usage attribute.
2622 // `WSSuffix` holds customized "white-space"s, e.g., newline or whilespace
2623 // characters.
2624 std::string
2626 StringRef WSSuffix = "") const override {
2627 Preprocessor &PP = S.getPreprocessor();
2628 TokenValue ClangUnsafeBufferUsageTokens[] = {
2629 tok::l_square,
2630 tok::l_square,
2631 PP.getIdentifierInfo("clang"),
2632 tok::coloncolon,
2633 PP.getIdentifierInfo("unsafe_buffer_usage"),
2634 tok::r_square,
2635 tok::r_square};
2636
2637 StringRef MacroName;
2638
2639 // The returned macro (it returns) is guaranteed not to be function-like:
2640 MacroName = PP.getLastMacroWithSpelling(Loc, ClangUnsafeBufferUsageTokens);
2641 if (MacroName.empty())
2642 MacroName = "[[clang::unsafe_buffer_usage]]";
2643 return MacroName.str() + WSSuffix.str();
2644 }
2645};
2646} // namespace
2647
2648//===----------------------------------------------------------------------===//
2649// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
2650// warnings on a function, method, or block.
2651//===----------------------------------------------------------------------===//
2652
2654 enableCheckFallThrough = 1;
2655 enableCheckUnreachable = 0;
2656 enableThreadSafetyAnalysis = 0;
2657 enableConsumedAnalysis = 0;
2658}
2659
2660/// InterProceduralData aims to be a storage of whatever data should be passed
2661/// between analyses of different functions.
2662///
2663/// At the moment, its primary goal is to make the information gathered during
2664/// the analysis of the blocks available during the analysis of the enclosing
2665/// function. This is important due to the fact that blocks are analyzed before
2666/// the enclosed function is even parsed fully, so it is not viable to access
2667/// anything in the outer scope while analyzing the block. On the other hand,
2668/// re-building CFG for blocks and re-analyzing them when we do have all the
2669/// information (i.e. during the analysis of the enclosing function) seems to be
2670/// ill-designed.
2672public:
2673 // It is important to analyze blocks within functions because it's a very
2674 // common pattern to capture completion handler parameters by blocks.
2675 CalledOnceInterProceduralData CalledOnceData;
2676};
2677
2678template <typename... Ts>
2680 Ts... Diags) {
2681 return (!D.isIgnored(Diags, Loc) || ...);
2682}
2683
2685 : S(s), IPData(std::make_unique<InterProceduralData>()),
2686 NumFunctionsAnalyzed(0), NumFunctionsWithBadCFGs(0), NumCFGBlocks(0),
2687 MaxCFGBlocksPerFunction(0), NumUninitAnalysisFunctions(0),
2688 NumUninitAnalysisVariables(0), MaxUninitAnalysisVariablesPerFunction(0),
2689 NumUninitAnalysisBlockVisits(0),
2690 MaxUninitAnalysisBlockVisitsPerFunction(0) {
2691}
2692
2693// We need this here for unique_ptr with forward declared class.
2695
2698 using namespace diag;
2700 Policy P;
2701
2702 // Note: The enabled checks should be kept in sync with the switch in
2703 // SemaPPCallbacks::PragmaDiagnostic().
2704 P.enableCheckUnreachable =
2705 PolicyOverrides.enableCheckUnreachable ||
2706 areAnyEnabled(D, Loc, warn_unreachable, warn_unreachable_break,
2707 warn_unreachable_return, warn_unreachable_loop_increment);
2708
2709 P.enableThreadSafetyAnalysis = PolicyOverrides.enableThreadSafetyAnalysis ||
2710 areAnyEnabled(D, Loc, warn_double_lock);
2711
2712 P.enableConsumedAnalysis = PolicyOverrides.enableConsumedAnalysis ||
2713 areAnyEnabled(D, Loc, warn_use_in_invalid_state);
2714 return P;
2715}
2716
2717void sema::AnalysisBasedWarnings::clearOverrides() {
2718 PolicyOverrides.enableCheckUnreachable = false;
2719 PolicyOverrides.enableConsumedAnalysis = false;
2720 PolicyOverrides.enableThreadSafetyAnalysis = false;
2721}
2722
2723static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
2724 for (const auto &D : fscope->PossiblyUnreachableDiags)
2725 S.Diag(D.Loc, D.PD);
2726}
2727
2728// An AST Visitor that calls a callback function on each callable DEFINITION
2729// that is NOT in a dependent context:
2731private:
2732 llvm::function_ref<void(const Decl *)> Callback;
2733 const Module *const TUModule;
2734
2735public:
2736 CallableVisitor(llvm::function_ref<void(const Decl *)> Callback,
2737 const Module *const TUModule)
2738 : Callback(Callback), TUModule(TUModule) {
2739 ShouldVisitTemplateInstantiations = true;
2740 ShouldVisitImplicitCode = false;
2741 }
2742
2743 bool TraverseDecl(Decl *Node) override {
2744 // For performance reasons, only validate the current translation unit's
2745 // module, and not modules it depends on.
2746 // See https://issues.chromium.org/issues/351909443 for details.
2747 if (Node && Node->getOwningModule() == TUModule)
2749 return true;
2750 }
2751
2753 if (cast<DeclContext>(Node)->isDependentContext())
2754 return true; // Not to analyze dependent decl
2755 // `FunctionDecl->hasBody()` returns true if the function has a body
2756 // somewhere defined. But we want to know if this `Node` has a body
2757 // child. So we use `doesThisDeclarationHaveABody`:
2758 if (Node->doesThisDeclarationHaveABody())
2759 Callback(Node);
2760 return true;
2761 }
2762
2764 if (cast<DeclContext>(Node)->isDependentContext())
2765 return true; // Not to analyze dependent decl
2766 Callback(Node);
2767 return true;
2768 }
2769
2771 if (cast<DeclContext>(Node)->isDependentContext())
2772 return true; // Not to analyze dependent decl
2773 if (Node->hasBody())
2774 Callback(Node);
2775 return true;
2776 }
2777
2779 return VisitFunctionDecl(Node->getCallOperator());
2780 }
2781};
2782
2783namespace clang::lifetimes {
2784namespace {
2785class LifetimeSafetyReporterImpl : public LifetimeSafetyReporter {
2786
2787public:
2788 LifetimeSafetyReporterImpl(Sema &S) : S(S) {}
2789
2790 void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
2791 SourceLocation FreeLoc, Confidence C) override {
2792 S.Diag(IssueExpr->getExprLoc(),
2793 C == Confidence::Definite
2794 ? diag::warn_lifetime_safety_loan_expires_permissive
2795 : diag::warn_lifetime_safety_loan_expires_strict)
2796 << IssueExpr->getEndLoc();
2797 S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here);
2798 S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
2799 << UseExpr->getEndLoc();
2800 }
2801
2802private:
2803 Sema &S;
2804};
2805} // namespace
2806} // namespace clang::lifetimes
2807
2809 TranslationUnitDecl *TU) {
2810 if (!TU)
2811 return; // This is unexpected, give up quietly.
2812
2813 DiagnosticsEngine &Diags = S.getDiagnostics();
2814
2816 // exit if having uncompilable errors or ignoring all warnings:
2817 return;
2818
2819 DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();
2820
2821 // UnsafeBufferUsage analysis settings.
2822 bool UnsafeBufferUsageCanEmitSuggestions = S.getLangOpts().CPlusPlus20;
2823 bool UnsafeBufferUsageShouldEmitSuggestions = // Should != Can.
2824 UnsafeBufferUsageCanEmitSuggestions &&
2825 DiagOpts.ShowSafeBufferUsageSuggestions;
2826 bool UnsafeBufferUsageShouldSuggestSuggestions =
2827 UnsafeBufferUsageCanEmitSuggestions &&
2828 !DiagOpts.ShowSafeBufferUsageSuggestions;
2829 UnsafeBufferUsageReporter R(S, UnsafeBufferUsageShouldSuggestSuggestions);
2830
2831 // The Callback function that performs analyses:
2832 auto CallAnalyzers = [&](const Decl *Node) -> void {
2833 if (Node->hasAttr<UnsafeBufferUsageAttr>())
2834 return;
2835
2836 // Perform unsafe buffer usage analysis:
2837 if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation,
2838 Node->getBeginLoc()) ||
2839 !Diags.isIgnored(diag::warn_unsafe_buffer_variable,
2840 Node->getBeginLoc()) ||
2841 !Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container,
2842 Node->getBeginLoc()) ||
2843 !Diags.isIgnored(diag::warn_unsafe_buffer_libc_call,
2844 Node->getBeginLoc())) {
2846 UnsafeBufferUsageShouldEmitSuggestions);
2847 }
2848
2849 // More analysis ...
2850 };
2851 // Emit per-function analysis-based warnings that require the whole-TU
2852 // reasoning. Check if any of them is enabled at all before scanning the AST:
2853 if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation, SourceLocation()) ||
2854 !Diags.isIgnored(diag::warn_unsafe_buffer_variable, SourceLocation()) ||
2855 !Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container,
2856 SourceLocation()) ||
2857 (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) &&
2858 S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) {
2859 CallableVisitor(CallAnalyzers, TU->getOwningModule())
2860 .TraverseTranslationUnitDecl(TU);
2861 }
2862}
2863
2866 const Decl *D, QualType BlockType) {
2867
2868 // We avoid doing analysis-based warnings when there are errors for
2869 // two reasons:
2870 // (1) The CFGs often can't be constructed (if the body is invalid), so
2871 // don't bother trying.
2872 // (2) The code already has problems; running the analysis just takes more
2873 // time.
2874 DiagnosticsEngine &Diags = S.getDiagnostics();
2875
2876 // Do not do any analysis if we are going to just ignore them.
2877 if (Diags.getIgnoreAllWarnings() ||
2878 (Diags.getSuppressSystemWarnings() &&
2880 return;
2881
2882 // For code in dependent contexts, we'll do this at instantiation time.
2883 if (cast<DeclContext>(D)->isDependentContext())
2884 return;
2885
2887 // Flush out any possibly unreachable diagnostics.
2888 flushDiagnostics(S, fscope);
2889 return;
2890 }
2891
2892 const Stmt *Body = D->getBody();
2893 assert(Body);
2894
2895 // Construct the analysis context with the specified CFG build options.
2896 AnalysisDeclContext AC(/* AnalysisDeclContextManager */ nullptr, D);
2897
2898 // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
2899 // explosion for destructors that can result and the compile time hit.
2900 AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true;
2901 AC.getCFGBuildOptions().AddEHEdges = false;
2902 AC.getCFGBuildOptions().AddInitializers = true;
2903 AC.getCFGBuildOptions().AddImplicitDtors = true;
2904 AC.getCFGBuildOptions().AddTemporaryDtors = true;
2905 AC.getCFGBuildOptions().AddCXXNewAllocator = false;
2906 AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true;
2907
2908 // Force that certain expressions appear as CFGElements in the CFG. This
2909 // is used to speed up various analyses.
2910 // FIXME: This isn't the right factoring. This is here for initial
2911 // prototyping, but we need a way for analyses to say what expressions they
2912 // expect to always be CFGElements and then fill in the BuildOptions
2913 // appropriately. This is essentially a layering violation.
2914 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
2915 P.enableConsumedAnalysis) {
2916 // Unreachable code analysis and thread safety require a linearized CFG.
2917 AC.getCFGBuildOptions().setAllAlwaysAdd();
2918 }
2919 else {
2920 AC.getCFGBuildOptions()
2921 .setAlwaysAdd(Stmt::BinaryOperatorClass)
2922 .setAlwaysAdd(Stmt::CompoundAssignOperatorClass)
2923 .setAlwaysAdd(Stmt::BlockExprClass)
2924 .setAlwaysAdd(Stmt::CStyleCastExprClass)
2925 .setAlwaysAdd(Stmt::DeclRefExprClass)
2926 .setAlwaysAdd(Stmt::ImplicitCastExprClass)
2927 .setAlwaysAdd(Stmt::UnaryOperatorClass);
2928 }
2929
2930 bool EnableLifetimeSafetyAnalysis = S.getLangOpts().EnableLifetimeSafety;
2931 // Install the logical handler.
2932 std::optional<LogicalErrorHandler> LEH;
2933 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
2934 LEH.emplace(S);
2935 AC.getCFGBuildOptions().Observer = &*LEH;
2936 }
2937
2938 // Emit delayed diagnostics.
2939 if (!fscope->PossiblyUnreachableDiags.empty()) {
2940 bool analyzed = false;
2941
2942 // Register the expressions with the CFGBuilder.
2943 for (const auto &D : fscope->PossiblyUnreachableDiags) {
2944 for (const Stmt *S : D.Stmts)
2945 AC.registerForcedBlockExpression(S);
2946 }
2947
2948 if (AC.getCFG()) {
2949 analyzed = true;
2950 for (const auto &D : fscope->PossiblyUnreachableDiags) {
2951 bool AllReachable = true;
2952 for (const Stmt *S : D.Stmts) {
2953 const CFGBlock *block = AC.getBlockForRegisteredExpression(S);
2955 AC.getCFGReachablityAnalysis();
2956 // FIXME: We should be able to assert that block is non-null, but
2957 // the CFG analysis can skip potentially-evaluated expressions in
2958 // edge cases; see test/Sema/vla-2.c.
2959 if (block && cra) {
2960 // Can this block be reached from the entrance?
2961 if (!cra->isReachable(&AC.getCFG()->getEntry(), block)) {
2962 AllReachable = false;
2963 break;
2964 }
2965 }
2966 // If we cannot map to a basic block, assume the statement is
2967 // reachable.
2968 }
2969
2970 if (AllReachable)
2971 S.Diag(D.Loc, D.PD);
2972 }
2973 }
2974
2975 if (!analyzed)
2976 flushDiagnostics(S, fscope);
2977 }
2978
2979 // Warning: check missing 'return'
2980 if (P.enableCheckFallThrough) {
2981 const CheckFallThroughDiagnostics &CD =
2982 (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
2983 : (isa<CXXMethodDecl>(D) &&
2984 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2985 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2986 ? CheckFallThroughDiagnostics::MakeForLambda()
2987 : (fscope->isCoroutine()
2988 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2989 : CheckFallThroughDiagnostics::MakeForFunction(S, D)));
2990 CheckFallThroughForBody(S, D, Body, BlockType, CD, AC);
2991 }
2992
2993 // Warning: check for unreachable code
2994 if (P.enableCheckUnreachable) {
2995 // Only check for unreachable code on non-template instantiations.
2996 // Different template instantiations can effectively change the control-flow
2997 // and it is very difficult to prove that a snippet of code in a template
2998 // is unreachable for all instantiations.
2999 bool isTemplateInstantiation = false;
3000 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
3001 isTemplateInstantiation = Function->isTemplateInstantiation();
3003 CheckUnreachable(S, AC);
3004 }
3005
3006 // Check for thread safety violations
3007 if (P.enableThreadSafetyAnalysis) {
3008 SourceLocation FL = AC.getDecl()->getLocation();
3009 SourceLocation FEL = AC.getDecl()->getEndLoc();
3010 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
3011 if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getBeginLoc()))
3012 Reporter.setIssueBetaWarnings(true);
3013 if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getBeginLoc()))
3014 Reporter.setVerbose(true);
3015
3018 Reporter.emitDiagnostics();
3019 }
3020
3021 // Check for violations of consumed properties.
3022 if (P.enableConsumedAnalysis) {
3023 consumed::ConsumedWarningsHandler WarningHandler(S);
3024 consumed::ConsumedAnalyzer Analyzer(WarningHandler);
3025 Analyzer.run(AC);
3026 }
3027
3028 if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||
3029 !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
3030 !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc()) ||
3031 !Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc()) ||
3032 !Diags.isIgnored(diag::warn_uninit_const_pointer, D->getBeginLoc())) {
3033 if (CFG *cfg = AC.getCFG()) {
3034 UninitValsDiagReporter reporter(S);
3036 std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats));
3037 runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
3038 reporter, stats);
3039
3040 if (S.CollectStats && stats.NumVariablesAnalyzed > 0) {
3041 ++NumUninitAnalysisFunctions;
3042 NumUninitAnalysisVariables += stats.NumVariablesAnalyzed;
3043 NumUninitAnalysisBlockVisits += stats.NumBlockVisits;
3044 MaxUninitAnalysisVariablesPerFunction =
3045 std::max(MaxUninitAnalysisVariablesPerFunction,
3046 stats.NumVariablesAnalyzed);
3047 MaxUninitAnalysisBlockVisitsPerFunction =
3048 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
3049 stats.NumBlockVisits);
3050 }
3051 }
3052 }
3053
3054 // TODO: Enable lifetime safety analysis for other languages once it is
3055 // stable.
3056 if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
3057 if (AC.getCFG()) {
3058 lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
3059 lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter);
3060 }
3061 }
3062 // Check for violations of "called once" parameter properties.
3063 if (S.getLangOpts().ObjC && !S.getLangOpts().CPlusPlus &&
3064 shouldAnalyzeCalledOnceParameters(Diags, D->getBeginLoc())) {
3065 if (AC.getCFG()) {
3066 CalledOnceCheckReporter Reporter(S, IPData->CalledOnceData);
3068 AC, Reporter,
3069 shouldAnalyzeCalledOnceConventions(Diags, D->getBeginLoc()));
3070 }
3071 }
3072
3073 bool FallThroughDiagFull =
3074 !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc());
3075 bool FallThroughDiagPerFunction = !Diags.isIgnored(
3076 diag::warn_unannotated_fallthrough_per_function, D->getBeginLoc());
3077 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
3078 fscope->HasFallthroughStmt) {
3079 DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
3080 }
3081
3082 if (S.getLangOpts().ObjCWeak &&
3083 !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getBeginLoc()))
3084 diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
3085
3086
3087 // Check for infinite self-recursion in functions
3088 if (!Diags.isIgnored(diag::warn_infinite_recursive_function,
3089 D->getBeginLoc())) {
3090 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
3091 checkRecursiveFunction(S, FD, Body, AC);
3092 }
3093 }
3094
3095 // Check for throw out of non-throwing function.
3096 if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getBeginLoc()))
3097 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
3098 if (S.getLangOpts().CPlusPlus && !fscope->isCoroutine() && isNoexcept(FD))
3099 checkThrowInNonThrowingFunc(S, FD, AC);
3100
3101 // If none of the previous checks caused a CFG build, trigger one here
3102 // for the logical error handler.
3103 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
3104 AC.getCFG();
3105 }
3106
3107 // Clear any of our policy overrides.
3108 clearOverrides();
3109
3110 // Collect statistics about the CFG if it was built.
3111 if (S.CollectStats && AC.isCFGBuilt()) {
3112 ++NumFunctionsAnalyzed;
3113 if (CFG *cfg = AC.getCFG()) {
3114 // If we successfully built a CFG for this context, record some more
3115 // detail information about it.
3116 NumCFGBlocks += cfg->getNumBlockIDs();
3117 MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,
3118 cfg->getNumBlockIDs());
3119 } else {
3120 ++NumFunctionsWithBadCFGs;
3121 }
3122 }
3123}
3124
3126 llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
3127
3128 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
3129 unsigned AvgCFGBlocksPerFunction =
3130 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
3131 llvm::errs() << NumFunctionsAnalyzed << " functions analyzed ("
3132 << NumFunctionsWithBadCFGs << " w/o CFGs).\n"
3133 << " " << NumCFGBlocks << " CFG blocks built.\n"
3134 << " " << AvgCFGBlocksPerFunction
3135 << " average CFG blocks per function.\n"
3136 << " " << MaxCFGBlocksPerFunction
3137 << " max CFG blocks per function.\n";
3138
3139 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
3140 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
3141 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
3142 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
3143 llvm::errs() << NumUninitAnalysisFunctions
3144 << " functions analyzed for uninitialiazed variables\n"
3145 << " " << NumUninitAnalysisVariables << " variables analyzed.\n"
3146 << " " << AvgUninitVariablesPerFunction
3147 << " average variables per function.\n"
3148 << " " << MaxUninitAnalysisVariablesPerFunction
3149 << " max variables per function.\n"
3150 << " " << NumUninitAnalysisBlockVisits << " block visits.\n"
3151 << " " << AvgUninitBlockVisitsPerFunction
3152 << " average block visits per function.\n"
3153 << " " << MaxUninitAnalysisBlockVisitsPerFunction
3154 << " max block visits per function.\n";
3155}
#define V(N, I)
Definition: ASTContext.h:3597
DynTypedNode Node
StringRef P
static void visitReachableThrows(CFG *BodyCFG, llvm::function_ref< void(const CXXThrowExpr *, CFGBlock &)> Visit)
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD)
static bool 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.
@ NeverFallThrough
@ UnknownFallThrough
@ NeverFallThroughOrReturn
@ MaybeFallThrough
@ AlwaysFallThrough
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)
SourceManager & SM
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Defines the Diagnostic-related interfaces.
const Decl * D
Expr * E
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)
const CFGBlock * Block
Definition: HTMLLogger.cpp:152
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:145
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)
Definition: OffloadArch.cpp:16
llvm::DenseMap< Stmt *, Stmt * > MapTy
Definition: ParentMap.cpp:21
Defines the clang::Preprocessor interface.
SourceRange Range
Definition: SemaObjC.cpp:753
VarDecl * Variable
Definition: SemaObjC.cpp:752
SourceLocation Loc
Definition: SemaObjC.cpp:754
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
const char * Data
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, ...);.
std::string Label
TextDiagnosticBuffer::DiagList DiagList
__device__ __2f16 b
__device__ int
__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
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents an attribute applied to a statement.
Definition: Stmt.h:2203
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3974
static bool isLogicalOp(Opcode Opc)
Definition: Expr.h:4107
Expr * getLHS() const
Definition: Expr.h:4024
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.h:4029
SourceLocation getOperatorLoc() const
Definition: Expr.h:4016
SourceLocation getExprLoc() const
Definition: Expr.h:4015
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:4026
Opcode getOpcode() const
Definition: Expr.h:4019
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:4634
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:6560
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.h:6581
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
succ_iterator succ_end()
Definition: CFG.h:991
reverse_iterator rbegin()
Definition: CFG.h:915
reverse_iterator rend()
Definition: CFG.h:916
bool hasNoReturnElement() const
Definition: CFG.h:1109
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
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
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
Definition: CFG.h:1210
virtual void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
Definition: CFG.h:1208
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
Definition: CFG.h:1209
virtual void compareBitwiseOr(const BinaryOperator *B)
Definition: CFG.h:1212
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
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition: CFG.h:1222
CFGBlock & getExit()
Definition: CFG.h:1332
CFGBlock & getEntry()
Definition: CFG.h:1330
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition: CFG.h:1409
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
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2129
bool isVirtual() const
Definition: DeclCXX.h:2184
A C++ throw-expression (C++ [except.throw]).
Definition: ExprCXX.h:1209
SourceLocation getThrowLoc() const
Definition: ExprCXX.h:1232
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2879
arg_iterator arg_begin()
Definition: Expr.h:3136
arg_iterator arg_end()
Definition: Expr.h:3139
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3062
Expr * getCallee()
Definition: Expr.h:3026
Decl * getCalleeDecl()
Definition: Expr.h:3056
virtual void handleBlockThatIsGuaranteedToBeCalledOnce(const BlockDecl *Block)
Called when the block is guaranteed to be called exactly once.
virtual void handleBlockWithNoGuarantees(const BlockDecl *Block)
Called when the block has no guarantees about how many times it can get called.
virtual void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call, const Expr *PrevCall, bool IsCompletionHandler, bool Poised)
Called when parameter is called twice.
virtual void handleNeverCalled(const ParmVarDecl *Parameter, bool IsCompletionHandler)
Called when parameter is not called at all.
virtual void handleCapturedNeverCalled(const ParmVarDecl *Parameter, const Decl *Where, bool IsCompletionHandler)
Called when captured parameter is not called at all.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getBegin() const
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:4327
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition: Expr.h:4359
Expr * getCond() const
getCond - Return the expression representing the condition for the ?: operator.
Definition: Expr.h:4350
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition: Expr.h:4354
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
void enqueueBlock(const CFGBlock *Block)
const CFGBlock * dequeue()
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1449
bool isFunctionOrMethod() const
Definition: DeclBase.h:2161
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1272
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1611
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
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:830
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:808
Options for controlling the compiler diagnostics engine.
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:231
bool isLastDiagnosticIgnored() const
Determine whether the previous diagnostic was ignored.
Definition: Diagnostic.h:800
bool getIgnoreAllWarnings() const
Definition: Diagnostic.h:685
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
Definition: Diagnostic.h:596
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
Definition: Diagnostic.h:950
bool getSuppressSystemWarnings() const
Definition: Diagnostic.h:722
Recursive AST visitor that supports extension via dynamic dispatch.
virtual bool TraverseDecl(MaybeConst< Decl > *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
virtual bool TraverseLambdaCapture(MaybeConst< LambdaExpr > *LE, const LambdaCapture *C, MaybeConst< Expr > *Init)
Recursively visit a lambda capture.
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:3078
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3073
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:78
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
Definition: Diagnostic.h:82
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:139
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition: Diagnostic.h:128
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:102
Kind lookup(const VarDecl *VD) const
Represents a function declaration or definition.
Definition: Decl.h:1999
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition: Decl.cpp:3271
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:3688
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification,...
Definition: Decl.cpp:3997
@ TK_MemberSpecialization
Definition: Decl.h:2011
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition: Decl.cpp:4085
bool isCPUDispatchMultiVersion() const
True if this function is a multiversioned dispatch function as a part of the cpu_specific/cpu_dispatc...
Definition: Decl.cpp:3643
Represents a prototype with parameter type info, e.g.
Definition: TypeBase.h:5282
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: TypeBase.h:4478
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
LabelStmt - Represents a label, which has a substatement.
Definition: Stmt.h:2146
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
Describes a module or submodule.
Definition: Module.h:144
This represents a decl that may have a name.
Definition: Decl.h:273
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:339
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:140
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:731
Stmt * getParent(Stmt *) const
Definition: ParentMap.cpp:142
Represents a parameter to a function.
Definition: Decl.h:1789
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:145
bool isSafeBufferOptOut(const SourceManager &SourceMgr, const SourceLocation &Loc) const
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:8343
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:8383
QualType getCanonicalType() const
Definition: TypeBase.h:8395
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: TypeBase.h:8416
bool hasObjCLifetime() const
Definition: TypeBase.h:544
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:61
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition: SemaBase.cpp:33
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
Preprocessor & getPreprocessor() const
Definition: Sema.h:917
ASTContext & Context
Definition: Sema.h:1276
DiagnosticsEngine & getDiagnostics() const
Definition: Sema.h:915
ASTContext & getASTContext() const
Definition: Sema.h:918
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:911
Preprocessor & PP
Definition: Sema.h:1275
threadSafety::BeforeSet * ThreadSafetyDeclCache
Definition: Sema.h:1313
bool CollectStats
Flag indicating whether or not to collect detailed statistics.
Definition: Sema.h:1210
SourceManager & getSourceManager() const
Definition: Sema.h:916
bool handlerCanCatch(QualType HandlerType, QualType ExceptionType)
bool hasUncompilableErrorOccurred() const
Whether uncompilable error has occurred.
Definition: Sema.cpp:1772
SourceManager & SourceMgr
Definition: Sema.h:1279
DiagnosticsEngine & Diags
Definition: Sema.h:1278
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
bool isValid() const
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:186
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
SwitchStmt - This represents a 'switch' stmt.
Definition: Stmt.h:2509
Stores token information for comparing actual tokens with predefined values.
Definition: Preprocessor.h:93
The top declaration context.
Definition: Decl.h:104
QualType getType() const
Return the type wrapped by this type source info.
Definition: TypeBase.h:8325
bool isBlockPointerType() const
Definition: TypeBase.h:8600
bool isPointerType() const
Definition: TypeBase.h:8580
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: TypeBase.h:8980
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
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:9159
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2246
Expr * getSubExpr() const
Definition: Expr.h:2287
Opcode getOpcode() const
Definition: Expr.h:2282
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 isConstRefOrPtrUse() const
branch_iterator branch_begin() const
Branches which inevitably result in the variable being used uninitialized.
@ Always
The use is always uninitialized.
@ AfterDecl
The use is uninitialized the first time it is reached after we reach the variable's declaration.
@ Maybe
The use might be uninitialized.
@ AfterCall
The use is uninitialized the first time it is reached after the function is called.
@ Sometimes
The use is uninitialized whenever a certain branch is taken.
Kind getKind() const
Get the kind of uninitialized use.
virtual void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use)
Called when the uninitialized variable is used at the given expression.
virtual void handleSelfInit(const VarDecl *vd)
Called when the uninitialized variable analysis detects the idiom 'int x = x'.
The interface that lets the caller handle unsafe buffer usage analysis results by overriding this cla...
virtual std::string getUnsafeBufferUsageAttributeTextAt(SourceLocation Loc, StringRef WSSuffix="") const =0
virtual bool isSafeBufferOptOut(const SourceLocation &Loc) const =0
virtual bool ignoreUnsafeBufferInContainer(const SourceLocation &Loc) const =0
virtual void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl, ASTContext &Ctx)=0
Invoked when an unsafe operation over raw pointers is found.
virtual void handleUnsafeVariableGroup(const VarDecl *Variable, const VariableGroupsManager &VarGrpMgr, FixItList &&Fixes, const Decl *D, const FixitStrategy &VarTargetTypes)=0
Invoked when a fix is suggested against a variable.
virtual void handleUnsafeOperationInContainer(const Stmt *Operation, bool IsRelatedToDecl, ASTContext &Ctx)=0
Invoked when an unsafe operation with a std container is found.
virtual bool ignoreUnsafeBufferInLibcCall(const SourceLocation &Loc) const =0
virtual void handleUnsafeLibcCall(const CallExpr *Call, unsigned PrintfInfo, ASTContext &Ctx, const Expr *UnsafeArg=nullptr)=0
Invoked when a call to an unsafe libc function is found.
QualType getType() const
Definition: Decl.h:722
Represents a variable declaration or definition.
Definition: Decl.h:925
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:1367
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 run(AnalysisDeclContext &AC)
Check a function's CFG for consumed violations.
Definition: Consumed.cpp:1300
virtual void HandleUnreachable(UnreachableKind UK, SourceLocation L, SourceRange ConditionVal, SourceRange R1, SourceRange R2, bool HasFallThroughAttr)=0
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
llvm::SmallDenseMap< WeakObjectProfileTy, WeakUseVector, 8, WeakObjectProfileTy::DenseMapInfo > WeakObjectUseMap
Used to collect all uses of weak objects in a function body.
Definition: ScopeInfo.h:380
bool HasFallthroughStmt
Whether there is a fallthrough statement in this function.
Definition: ScopeInfo.h:138
SmallVector< PossiblyUnreachableDiag, 4 > PossiblyUnreachableDiags
A list of PartialDiagnostics created but delayed within the current function scope.
Definition: ScopeInfo.h:239
const WeakObjectUseMap & getWeakObjectUses() const
Definition: ScopeInfo.h:431
Handler class for thread safety warnings.
Definition: ThreadSafety.h:109
InterProceduralData aims to be a storage of whatever data should be passed between analyses of differ...
SmallVector< PartialDiagnosticAt, 1 > OptionalNotes
Definition: Consumed.h:52
std::pair< PartialDiagnosticAt, OptionalNotes > DelayedDiag
Definition: Consumed.h:53
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.
Definition: ReachableCode.h:40
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.
Definition: ThreadSafety.h:97
@ LEK_NotLockedAtEndOfFunction
Expecting a capability to be held at the end of function.
Definition: ThreadSafety.h:105
@ LEK_LockedSomePredecessors
A capability is locked in some but not all predecessors of a CFGBlock.
Definition: ThreadSafety.h:101
@ LEK_LockedAtEndOfFunction
A capability is still locked at the end of a function.
Definition: ThreadSafety.h:103
@ LEK_LockedSomeLoopIterations
A capability is locked for some but not all loop iterations.
Definition: ThreadSafety.h:99
LockKind
This enum distinguishes between different kinds of lock actions.
Definition: ThreadSafety.h:74
void runThreadSafetyAnalysis(AnalysisDeclContext &AC, ThreadSafetyHandler &Handler, BeforeSet **Bset)
Check a function's CFG for thread-safety violations.
ProtectedOperationKind
This enum distinguishes between different kinds of operations that may need to be protected by locks.
Definition: ThreadSafety.h:36
@ POK_PtPassByRef
Passing a pt-guarded variable by reference.
Definition: ThreadSafety.h:50
@ POK_PassPointer
Passing pointer to a guarded variable.
Definition: ThreadSafety.h:59
@ POK_VarDereference
Dereferencing a variable (e.g. p in *p = 5;)
Definition: ThreadSafety.h:38
@ POK_PassByRef
Passing a guarded variable by reference.
Definition: ThreadSafety.h:47
@ POK_ReturnByRef
Returning a guarded variable by reference.
Definition: ThreadSafety.h:53
@ POK_PtPassPointer
Passing a pt-guarded pointer.
Definition: ThreadSafety.h:62
@ POK_PtReturnPointer
Returning a pt-guarded pointer.
Definition: ThreadSafety.h:68
@ POK_VarAccess
Reading or writing a variable (e.g. x in x = 5;)
Definition: ThreadSafety.h:41
@ POK_FunctionCall
Making a function call (e.g. fool())
Definition: ThreadSafety.h:44
@ POK_ReturnPointer
Returning pointer to a guarded variable.
Definition: ThreadSafety.h:65
@ POK_PtReturnByRef
Returning a pt-guarded variable by reference.
Definition: ThreadSafety.h:56
The JSON file list parser is used to communicate input to InstallAPI.
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
Definition: Specifiers.h:212
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler, bool EmitSuggestions)
BinaryOperatorKind
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Property
The type of a property.
@ Parameter
The parameter type of a method or function.
UnaryOperatorKind
void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, AnalysisDeclContext &ac, UninitVariablesHandler &handler, UninitVariablesAnalysisStats &stats)
void checkCalledOnceParameters(AnalysisDeclContext &AC, CalledOnceCheckHandler &Handler, bool CheckConventionalParameters)
Check given CFG for 'called once' parameter violations.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
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
Iterator for iterating over Stmt * arrays that contain only T *.
Definition: Stmt.h:1430