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