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