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