xref: /freebsd/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
10b57cec5SDimitry Andric //=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines analysis_warnings::[Policy,Executor].
100b57cec5SDimitry Andric // Together they are used by Sema to issue warnings based on inexpensive
110b57cec5SDimitry Andric // static analysis algorithms in libAnalysis.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "clang/Sema/AnalysisBasedWarnings.h"
160b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
170b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
180b57cec5SDimitry Andric #include "clang/AST/EvaluatedExprVisitor.h"
190b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
200b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h"
210b57cec5SDimitry Andric #include "clang/AST/ParentMap.h"
220b57cec5SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
230b57cec5SDimitry Andric #include "clang/AST/StmtCXX.h"
240b57cec5SDimitry Andric #include "clang/AST/StmtObjC.h"
250b57cec5SDimitry Andric #include "clang/AST/StmtVisitor.h"
260b57cec5SDimitry Andric #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
270b57cec5SDimitry Andric #include "clang/Analysis/Analyses/Consumed.h"
280b57cec5SDimitry Andric #include "clang/Analysis/Analyses/ReachableCode.h"
290b57cec5SDimitry Andric #include "clang/Analysis/Analyses/ThreadSafety.h"
300b57cec5SDimitry Andric #include "clang/Analysis/Analyses/UninitializedValues.h"
310b57cec5SDimitry Andric #include "clang/Analysis/AnalysisDeclContext.h"
320b57cec5SDimitry Andric #include "clang/Analysis/CFG.h"
330b57cec5SDimitry Andric #include "clang/Analysis/CFGStmtMap.h"
340b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
350b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
360b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
370b57cec5SDimitry Andric #include "clang/Sema/ScopeInfo.h"
380b57cec5SDimitry Andric #include "clang/Sema/SemaInternal.h"
390b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
400b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h"
410b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
420b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
430b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
440b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
450b57cec5SDimitry Andric #include <algorithm>
460b57cec5SDimitry Andric #include <deque>
470b57cec5SDimitry Andric #include <iterator>
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric using namespace clang;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
520b57cec5SDimitry Andric // Unreachable code analysis.
530b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric namespace {
560b57cec5SDimitry Andric   class UnreachableCodeHandler : public reachable_code::Callback {
570b57cec5SDimitry Andric     Sema &S;
580b57cec5SDimitry Andric     SourceRange PreviousSilenceableCondVal;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   public:
610b57cec5SDimitry Andric     UnreachableCodeHandler(Sema &s) : S(s) {}
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric     void HandleUnreachable(reachable_code::UnreachableKind UK,
640b57cec5SDimitry Andric                            SourceLocation L,
650b57cec5SDimitry Andric                            SourceRange SilenceableCondVal,
660b57cec5SDimitry Andric                            SourceRange R1,
670b57cec5SDimitry Andric                            SourceRange R2) override {
680b57cec5SDimitry Andric       // Avoid reporting multiple unreachable code diagnostics that are
690b57cec5SDimitry Andric       // triggered by the same conditional value.
700b57cec5SDimitry Andric       if (PreviousSilenceableCondVal.isValid() &&
710b57cec5SDimitry Andric           SilenceableCondVal.isValid() &&
720b57cec5SDimitry Andric           PreviousSilenceableCondVal == SilenceableCondVal)
730b57cec5SDimitry Andric         return;
740b57cec5SDimitry Andric       PreviousSilenceableCondVal = SilenceableCondVal;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric       unsigned diag = diag::warn_unreachable;
770b57cec5SDimitry Andric       switch (UK) {
780b57cec5SDimitry Andric         case reachable_code::UK_Break:
790b57cec5SDimitry Andric           diag = diag::warn_unreachable_break;
800b57cec5SDimitry Andric           break;
810b57cec5SDimitry Andric         case reachable_code::UK_Return:
820b57cec5SDimitry Andric           diag = diag::warn_unreachable_return;
830b57cec5SDimitry Andric           break;
840b57cec5SDimitry Andric         case reachable_code::UK_Loop_Increment:
850b57cec5SDimitry Andric           diag = diag::warn_unreachable_loop_increment;
860b57cec5SDimitry Andric           break;
870b57cec5SDimitry Andric         case reachable_code::UK_Other:
880b57cec5SDimitry Andric           break;
890b57cec5SDimitry Andric       }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric       S.Diag(L, diag) << R1 << R2;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric       SourceLocation Open = SilenceableCondVal.getBegin();
940b57cec5SDimitry Andric       if (Open.isValid()) {
950b57cec5SDimitry Andric         SourceLocation Close = SilenceableCondVal.getEnd();
960b57cec5SDimitry Andric         Close = S.getLocForEndOfToken(Close);
970b57cec5SDimitry Andric         if (Close.isValid()) {
980b57cec5SDimitry Andric           S.Diag(Open, diag::note_unreachable_silence)
990b57cec5SDimitry Andric             << FixItHint::CreateInsertion(Open, "/* DISABLES CODE */ (")
1000b57cec5SDimitry Andric             << FixItHint::CreateInsertion(Close, ")");
1010b57cec5SDimitry Andric         }
1020b57cec5SDimitry Andric       }
1030b57cec5SDimitry Andric     }
1040b57cec5SDimitry Andric   };
1050b57cec5SDimitry Andric } // anonymous namespace
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric /// CheckUnreachable - Check for unreachable code.
1080b57cec5SDimitry Andric static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
1090b57cec5SDimitry Andric   // As a heuristic prune all diagnostics not in the main file.  Currently
1100b57cec5SDimitry Andric   // the majority of warnings in headers are false positives.  These
1110b57cec5SDimitry Andric   // are largely caused by configuration state, e.g. preprocessor
1120b57cec5SDimitry Andric   // defined code, etc.
1130b57cec5SDimitry Andric   //
1140b57cec5SDimitry Andric   // Note that this is also a performance optimization.  Analyzing
1150b57cec5SDimitry Andric   // headers many times can be expensive.
1160b57cec5SDimitry Andric   if (!S.getSourceManager().isInMainFile(AC.getDecl()->getBeginLoc()))
1170b57cec5SDimitry Andric     return;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   UnreachableCodeHandler UC(S);
1200b57cec5SDimitry Andric   reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC);
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric namespace {
1240b57cec5SDimitry Andric /// Warn on logical operator errors in CFGBuilder
1250b57cec5SDimitry Andric class LogicalErrorHandler : public CFGCallback {
1260b57cec5SDimitry Andric   Sema &S;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric public:
1290b57cec5SDimitry Andric   LogicalErrorHandler(Sema &S) : CFGCallback(), S(S) {}
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   static bool HasMacroID(const Expr *E) {
1320b57cec5SDimitry Andric     if (E->getExprLoc().isMacroID())
1330b57cec5SDimitry Andric       return true;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric     // Recurse to children.
1360b57cec5SDimitry Andric     for (const Stmt *SubStmt : E->children())
1370b57cec5SDimitry Andric       if (const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
1380b57cec5SDimitry Andric         if (HasMacroID(SubExpr))
1390b57cec5SDimitry Andric           return true;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric     return false;
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override {
1450b57cec5SDimitry Andric     if (HasMacroID(B))
1460b57cec5SDimitry Andric       return;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric     SourceRange DiagRange = B->getSourceRange();
1490b57cec5SDimitry Andric     S.Diag(B->getExprLoc(), diag::warn_tautological_overlap_comparison)
1500b57cec5SDimitry Andric         << DiagRange << isAlwaysTrue;
1510b57cec5SDimitry Andric   }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   void compareBitwiseEquality(const BinaryOperator *B,
1540b57cec5SDimitry Andric                               bool isAlwaysTrue) override {
1550b57cec5SDimitry Andric     if (HasMacroID(B))
1560b57cec5SDimitry Andric       return;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric     SourceRange DiagRange = B->getSourceRange();
1590b57cec5SDimitry Andric     S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_always)
1600b57cec5SDimitry Andric         << DiagRange << isAlwaysTrue;
1610b57cec5SDimitry Andric   }
162*a7dea167SDimitry Andric 
163*a7dea167SDimitry Andric   void compareBitwiseOr(const BinaryOperator *B) override {
164*a7dea167SDimitry Andric     if (HasMacroID(B))
165*a7dea167SDimitry Andric       return;
166*a7dea167SDimitry Andric 
167*a7dea167SDimitry Andric     SourceRange DiagRange = B->getSourceRange();
168*a7dea167SDimitry Andric     S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_or) << DiagRange;
169*a7dea167SDimitry Andric   }
170*a7dea167SDimitry Andric 
171*a7dea167SDimitry Andric   static bool hasActiveDiagnostics(DiagnosticsEngine &Diags,
172*a7dea167SDimitry Andric                                    SourceLocation Loc) {
173*a7dea167SDimitry Andric     return !Diags.isIgnored(diag::warn_tautological_overlap_comparison, Loc) ||
174*a7dea167SDimitry Andric            !Diags.isIgnored(diag::warn_comparison_bitwise_or, Loc);
175*a7dea167SDimitry Andric   }
1760b57cec5SDimitry Andric };
1770b57cec5SDimitry Andric } // anonymous namespace
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1800b57cec5SDimitry Andric // Check for infinite self-recursion in functions
1810b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric // Returns true if the function is called anywhere within the CFGBlock.
1840b57cec5SDimitry Andric // For member functions, the additional condition of being call from the
1850b57cec5SDimitry Andric // this pointer is required.
1860b57cec5SDimitry Andric static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) {
1870b57cec5SDimitry Andric   // Process all the Stmt's in this block to find any calls to FD.
1880b57cec5SDimitry Andric   for (const auto &B : Block) {
1890b57cec5SDimitry Andric     if (B.getKind() != CFGElement::Statement)
1900b57cec5SDimitry Andric       continue;
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric     const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
1930b57cec5SDimitry Andric     if (!CE || !CE->getCalleeDecl() ||
1940b57cec5SDimitry Andric         CE->getCalleeDecl()->getCanonicalDecl() != FD)
1950b57cec5SDimitry Andric       continue;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric     // Skip function calls which are qualified with a templated class.
1980b57cec5SDimitry Andric     if (const DeclRefExpr *DRE =
1990b57cec5SDimitry Andric             dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) {
2000b57cec5SDimitry Andric       if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
2010b57cec5SDimitry Andric         if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
2020b57cec5SDimitry Andric             isa<TemplateSpecializationType>(NNS->getAsType())) {
2030b57cec5SDimitry Andric           continue;
2040b57cec5SDimitry Andric         }
2050b57cec5SDimitry Andric       }
2060b57cec5SDimitry Andric     }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric     const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE);
2090b57cec5SDimitry Andric     if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
2100b57cec5SDimitry Andric         !MCE->getMethodDecl()->isVirtual())
2110b57cec5SDimitry Andric       return true;
2120b57cec5SDimitry Andric   }
2130b57cec5SDimitry Andric   return false;
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric // Returns true if every path from the entry block passes through a call to FD.
2170b57cec5SDimitry Andric static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
2180b57cec5SDimitry Andric   llvm::SmallPtrSet<CFGBlock *, 16> Visited;
2190b57cec5SDimitry Andric   llvm::SmallVector<CFGBlock *, 16> WorkList;
2200b57cec5SDimitry Andric   // Keep track of whether we found at least one recursive path.
2210b57cec5SDimitry Andric   bool foundRecursion = false;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   const unsigned ExitID = cfg->getExit().getBlockID();
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   // Seed the work list with the entry block.
2260b57cec5SDimitry Andric   WorkList.push_back(&cfg->getEntry());
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   while (!WorkList.empty()) {
2290b57cec5SDimitry Andric     CFGBlock *Block = WorkList.pop_back_val();
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric     for (auto I = Block->succ_begin(), E = Block->succ_end(); I != E; ++I) {
2320b57cec5SDimitry Andric       if (CFGBlock *SuccBlock = *I) {
2330b57cec5SDimitry Andric         if (!Visited.insert(SuccBlock).second)
2340b57cec5SDimitry Andric           continue;
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric         // Found a path to the exit node without a recursive call.
2370b57cec5SDimitry Andric         if (ExitID == SuccBlock->getBlockID())
2380b57cec5SDimitry Andric           return false;
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric         // If the successor block contains a recursive call, end analysis there.
2410b57cec5SDimitry Andric         if (hasRecursiveCallInPath(FD, *SuccBlock)) {
2420b57cec5SDimitry Andric           foundRecursion = true;
2430b57cec5SDimitry Andric           continue;
2440b57cec5SDimitry Andric         }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric         WorkList.push_back(SuccBlock);
2470b57cec5SDimitry Andric       }
2480b57cec5SDimitry Andric     }
2490b57cec5SDimitry Andric   }
2500b57cec5SDimitry Andric   return foundRecursion;
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
2540b57cec5SDimitry Andric                                    const Stmt *Body, AnalysisDeclContext &AC) {
2550b57cec5SDimitry Andric   FD = FD->getCanonicalDecl();
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   // Only run on non-templated functions and non-templated members of
2580b57cec5SDimitry Andric   // templated classes.
2590b57cec5SDimitry Andric   if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate &&
2600b57cec5SDimitry Andric       FD->getTemplatedKind() != FunctionDecl::TK_MemberSpecialization)
2610b57cec5SDimitry Andric     return;
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   CFG *cfg = AC.getCFG();
2640b57cec5SDimitry Andric   if (!cfg) return;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   // If the exit block is unreachable, skip processing the function.
2670b57cec5SDimitry Andric   if (cfg->getExit().pred_empty())
2680b57cec5SDimitry Andric     return;
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   // Emit diagnostic if a recursive function call is detected for all paths.
2710b57cec5SDimitry Andric   if (checkForRecursiveFunctionCall(FD, cfg))
2720b57cec5SDimitry Andric     S.Diag(Body->getBeginLoc(), diag::warn_infinite_recursive_function);
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2760b57cec5SDimitry Andric // Check for throw in a non-throwing function.
2770b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric /// Determine whether an exception thrown by E, unwinding from ThrowBlock,
2800b57cec5SDimitry Andric /// can reach ExitBlock.
2810b57cec5SDimitry Andric static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock,
2820b57cec5SDimitry Andric                          CFG *Body) {
2830b57cec5SDimitry Andric   SmallVector<CFGBlock *, 16> Stack;
2840b57cec5SDimitry Andric   llvm::BitVector Queued(Body->getNumBlockIDs());
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   Stack.push_back(&ThrowBlock);
2870b57cec5SDimitry Andric   Queued[ThrowBlock.getBlockID()] = true;
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   while (!Stack.empty()) {
2900b57cec5SDimitry Andric     CFGBlock &UnwindBlock = *Stack.back();
2910b57cec5SDimitry Andric     Stack.pop_back();
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric     for (auto &Succ : UnwindBlock.succs()) {
2940b57cec5SDimitry Andric       if (!Succ.isReachable() || Queued[Succ->getBlockID()])
2950b57cec5SDimitry Andric         continue;
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric       if (Succ->getBlockID() == Body->getExit().getBlockID())
2980b57cec5SDimitry Andric         return true;
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric       if (auto *Catch =
3010b57cec5SDimitry Andric               dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
3020b57cec5SDimitry Andric         QualType Caught = Catch->getCaughtType();
3030b57cec5SDimitry Andric         if (Caught.isNull() || // catch (...) catches everything
3040b57cec5SDimitry Andric             !E->getSubExpr() || // throw; is considered cuaght by any handler
3050b57cec5SDimitry Andric             S.handlerCanCatch(Caught, E->getSubExpr()->getType()))
3060b57cec5SDimitry Andric           // Exception doesn't escape via this path.
3070b57cec5SDimitry Andric           break;
3080b57cec5SDimitry Andric       } else {
3090b57cec5SDimitry Andric         Stack.push_back(Succ);
3100b57cec5SDimitry Andric         Queued[Succ->getBlockID()] = true;
3110b57cec5SDimitry Andric       }
3120b57cec5SDimitry Andric     }
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   return false;
3160b57cec5SDimitry Andric }
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric static void visitReachableThrows(
3190b57cec5SDimitry Andric     CFG *BodyCFG,
3200b57cec5SDimitry Andric     llvm::function_ref<void(const CXXThrowExpr *, CFGBlock &)> Visit) {
3210b57cec5SDimitry Andric   llvm::BitVector Reachable(BodyCFG->getNumBlockIDs());
3220b57cec5SDimitry Andric   clang::reachable_code::ScanReachableFromBlock(&BodyCFG->getEntry(), Reachable);
3230b57cec5SDimitry Andric   for (CFGBlock *B : *BodyCFG) {
3240b57cec5SDimitry Andric     if (!Reachable[B->getBlockID()])
3250b57cec5SDimitry Andric       continue;
3260b57cec5SDimitry Andric     for (CFGElement &E : *B) {
3270b57cec5SDimitry Andric       Optional<CFGStmt> S = E.getAs<CFGStmt>();
3280b57cec5SDimitry Andric       if (!S)
3290b57cec5SDimitry Andric         continue;
3300b57cec5SDimitry Andric       if (auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
3310b57cec5SDimitry Andric         Visit(Throw, *B);
3320b57cec5SDimitry Andric     }
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc,
3370b57cec5SDimitry Andric                                                  const FunctionDecl *FD) {
3380b57cec5SDimitry Andric   if (!S.getSourceManager().isInSystemHeader(OpLoc) &&
3390b57cec5SDimitry Andric       FD->getTypeSourceInfo()) {
3400b57cec5SDimitry Andric     S.Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
3410b57cec5SDimitry Andric     if (S.getLangOpts().CPlusPlus11 &&
3420b57cec5SDimitry Andric         (isa<CXXDestructorDecl>(FD) ||
3430b57cec5SDimitry Andric          FD->getDeclName().getCXXOverloadedOperator() == OO_Delete ||
3440b57cec5SDimitry Andric          FD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete)) {
3450b57cec5SDimitry Andric       if (const auto *Ty = FD->getTypeSourceInfo()->getType()->
3460b57cec5SDimitry Andric                                          getAs<FunctionProtoType>())
3470b57cec5SDimitry Andric         S.Diag(FD->getLocation(), diag::note_throw_in_dtor)
3480b57cec5SDimitry Andric             << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
3490b57cec5SDimitry Andric             << FD->getExceptionSpecSourceRange();
3500b57cec5SDimitry Andric     } else
3510b57cec5SDimitry Andric       S.Diag(FD->getLocation(), diag::note_throw_in_function)
3520b57cec5SDimitry Andric           << FD->getExceptionSpecSourceRange();
3530b57cec5SDimitry Andric   }
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD,
3570b57cec5SDimitry Andric                                         AnalysisDeclContext &AC) {
3580b57cec5SDimitry Andric   CFG *BodyCFG = AC.getCFG();
3590b57cec5SDimitry Andric   if (!BodyCFG)
3600b57cec5SDimitry Andric     return;
3610b57cec5SDimitry Andric   if (BodyCFG->getExit().pred_empty())
3620b57cec5SDimitry Andric     return;
3630b57cec5SDimitry Andric   visitReachableThrows(BodyCFG, [&](const CXXThrowExpr *Throw, CFGBlock &Block) {
3640b57cec5SDimitry Andric     if (throwEscapes(S, Throw, Block, BodyCFG))
3650b57cec5SDimitry Andric       EmitDiagForCXXThrowInNonThrowingFunc(S, Throw->getThrowLoc(), FD);
3660b57cec5SDimitry Andric   });
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric static bool isNoexcept(const FunctionDecl *FD) {
3700b57cec5SDimitry Andric   const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
3710b57cec5SDimitry Andric   if (FPT->isNothrow() || FD->hasAttr<NoThrowAttr>())
3720b57cec5SDimitry Andric     return true;
3730b57cec5SDimitry Andric   return false;
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3770b57cec5SDimitry Andric // Check for missing return value.
3780b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric enum ControlFlowKind {
3810b57cec5SDimitry Andric   UnknownFallThrough,
3820b57cec5SDimitry Andric   NeverFallThrough,
3830b57cec5SDimitry Andric   MaybeFallThrough,
3840b57cec5SDimitry Andric   AlwaysFallThrough,
3850b57cec5SDimitry Andric   NeverFallThroughOrReturn
3860b57cec5SDimitry Andric };
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric /// CheckFallThrough - Check that we don't fall off the end of a
3890b57cec5SDimitry Andric /// Statement that should return a value.
3900b57cec5SDimitry Andric ///
3910b57cec5SDimitry Andric /// \returns AlwaysFallThrough iff we always fall off the end of the statement,
3920b57cec5SDimitry Andric /// MaybeFallThrough iff we might or might not fall off the end,
3930b57cec5SDimitry Andric /// NeverFallThroughOrReturn iff we never fall off the end of the statement or
3940b57cec5SDimitry Andric /// return.  We assume NeverFallThrough iff we never fall off the end of the
3950b57cec5SDimitry Andric /// statement but we may return.  We assume that functions not marked noreturn
3960b57cec5SDimitry Andric /// will return.
3970b57cec5SDimitry Andric static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
3980b57cec5SDimitry Andric   CFG *cfg = AC.getCFG();
3990b57cec5SDimitry Andric   if (!cfg) return UnknownFallThrough;
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   // The CFG leaves in dead things, and we don't want the dead code paths to
4020b57cec5SDimitry Andric   // confuse us, so we mark all live things first.
4030b57cec5SDimitry Andric   llvm::BitVector live(cfg->getNumBlockIDs());
4040b57cec5SDimitry Andric   unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(),
4050b57cec5SDimitry Andric                                                           live);
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   bool AddEHEdges = AC.getAddEHEdges();
4080b57cec5SDimitry Andric   if (!AddEHEdges && count != cfg->getNumBlockIDs())
4090b57cec5SDimitry Andric     // When there are things remaining dead, and we didn't add EH edges
4100b57cec5SDimitry Andric     // from CallExprs to the catch clauses, we have to go back and
4110b57cec5SDimitry Andric     // mark them as live.
4120b57cec5SDimitry Andric     for (const auto *B : *cfg) {
4130b57cec5SDimitry Andric       if (!live[B->getBlockID()]) {
4140b57cec5SDimitry Andric         if (B->pred_begin() == B->pred_end()) {
4150b57cec5SDimitry Andric           const Stmt *Term = B->getTerminatorStmt();
4160b57cec5SDimitry Andric           if (Term && isa<CXXTryStmt>(Term))
4170b57cec5SDimitry Andric             // When not adding EH edges from calls, catch clauses
4180b57cec5SDimitry Andric             // can otherwise seem dead.  Avoid noting them as dead.
4190b57cec5SDimitry Andric             count += reachable_code::ScanReachableFromBlock(B, live);
4200b57cec5SDimitry Andric           continue;
4210b57cec5SDimitry Andric         }
4220b57cec5SDimitry Andric       }
4230b57cec5SDimitry Andric     }
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   // Now we know what is live, we check the live precessors of the exit block
4260b57cec5SDimitry Andric   // and look for fall through paths, being careful to ignore normal returns,
4270b57cec5SDimitry Andric   // and exceptional paths.
4280b57cec5SDimitry Andric   bool HasLiveReturn = false;
4290b57cec5SDimitry Andric   bool HasFakeEdge = false;
4300b57cec5SDimitry Andric   bool HasPlainEdge = false;
4310b57cec5SDimitry Andric   bool HasAbnormalEdge = false;
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   // Ignore default cases that aren't likely to be reachable because all
4340b57cec5SDimitry Andric   // enums in a switch(X) have explicit case statements.
4350b57cec5SDimitry Andric   CFGBlock::FilterOptions FO;
4360b57cec5SDimitry Andric   FO.IgnoreDefaultsWithCoveredEnums = 1;
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   for (CFGBlock::filtered_pred_iterator I =
4390b57cec5SDimitry Andric            cfg->getExit().filtered_pred_start_end(FO);
4400b57cec5SDimitry Andric        I.hasMore(); ++I) {
4410b57cec5SDimitry Andric     const CFGBlock &B = **I;
4420b57cec5SDimitry Andric     if (!live[B.getBlockID()])
4430b57cec5SDimitry Andric       continue;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric     // Skip blocks which contain an element marked as no-return. They don't
4460b57cec5SDimitry Andric     // represent actually viable edges into the exit block, so mark them as
4470b57cec5SDimitry Andric     // abnormal.
4480b57cec5SDimitry Andric     if (B.hasNoReturnElement()) {
4490b57cec5SDimitry Andric       HasAbnormalEdge = true;
4500b57cec5SDimitry Andric       continue;
4510b57cec5SDimitry Andric     }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric     // Destructors can appear after the 'return' in the CFG.  This is
4540b57cec5SDimitry Andric     // normal.  We need to look pass the destructors for the return
4550b57cec5SDimitry Andric     // statement (if it exists).
4560b57cec5SDimitry Andric     CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric     for ( ; ri != re ; ++ri)
4590b57cec5SDimitry Andric       if (ri->getAs<CFGStmt>())
4600b57cec5SDimitry Andric         break;
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric     // No more CFGElements in the block?
4630b57cec5SDimitry Andric     if (ri == re) {
4640b57cec5SDimitry Andric       const Stmt *Term = B.getTerminatorStmt();
4650b57cec5SDimitry Andric       if (Term && isa<CXXTryStmt>(Term)) {
4660b57cec5SDimitry Andric         HasAbnormalEdge = true;
4670b57cec5SDimitry Andric         continue;
4680b57cec5SDimitry Andric       }
4690b57cec5SDimitry Andric       // A labeled empty statement, or the entry block...
4700b57cec5SDimitry Andric       HasPlainEdge = true;
4710b57cec5SDimitry Andric       continue;
4720b57cec5SDimitry Andric     }
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric     CFGStmt CS = ri->castAs<CFGStmt>();
4750b57cec5SDimitry Andric     const Stmt *S = CS.getStmt();
4760b57cec5SDimitry Andric     if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
4770b57cec5SDimitry Andric       HasLiveReturn = true;
4780b57cec5SDimitry Andric       continue;
4790b57cec5SDimitry Andric     }
4800b57cec5SDimitry Andric     if (isa<ObjCAtThrowStmt>(S)) {
4810b57cec5SDimitry Andric       HasFakeEdge = true;
4820b57cec5SDimitry Andric       continue;
4830b57cec5SDimitry Andric     }
4840b57cec5SDimitry Andric     if (isa<CXXThrowExpr>(S)) {
4850b57cec5SDimitry Andric       HasFakeEdge = true;
4860b57cec5SDimitry Andric       continue;
4870b57cec5SDimitry Andric     }
4880b57cec5SDimitry Andric     if (isa<MSAsmStmt>(S)) {
4890b57cec5SDimitry Andric       // TODO: Verify this is correct.
4900b57cec5SDimitry Andric       HasFakeEdge = true;
4910b57cec5SDimitry Andric       HasLiveReturn = true;
4920b57cec5SDimitry Andric       continue;
4930b57cec5SDimitry Andric     }
4940b57cec5SDimitry Andric     if (isa<CXXTryStmt>(S)) {
4950b57cec5SDimitry Andric       HasAbnormalEdge = true;
4960b57cec5SDimitry Andric       continue;
4970b57cec5SDimitry Andric     }
4980b57cec5SDimitry Andric     if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
4990b57cec5SDimitry Andric         == B.succ_end()) {
5000b57cec5SDimitry Andric       HasAbnormalEdge = true;
5010b57cec5SDimitry Andric       continue;
5020b57cec5SDimitry Andric     }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric     HasPlainEdge = true;
5050b57cec5SDimitry Andric   }
5060b57cec5SDimitry Andric   if (!HasPlainEdge) {
5070b57cec5SDimitry Andric     if (HasLiveReturn)
5080b57cec5SDimitry Andric       return NeverFallThrough;
5090b57cec5SDimitry Andric     return NeverFallThroughOrReturn;
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric   if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
5120b57cec5SDimitry Andric     return MaybeFallThrough;
5130b57cec5SDimitry Andric   // This says AlwaysFallThrough for calls to functions that are not marked
5140b57cec5SDimitry Andric   // noreturn, that don't return.  If people would like this warning to be more
5150b57cec5SDimitry Andric   // accurate, such functions should be marked as noreturn.
5160b57cec5SDimitry Andric   return AlwaysFallThrough;
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric namespace {
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric struct CheckFallThroughDiagnostics {
5220b57cec5SDimitry Andric   unsigned diag_MaybeFallThrough_HasNoReturn;
5230b57cec5SDimitry Andric   unsigned diag_MaybeFallThrough_ReturnsNonVoid;
5240b57cec5SDimitry Andric   unsigned diag_AlwaysFallThrough_HasNoReturn;
5250b57cec5SDimitry Andric   unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
5260b57cec5SDimitry Andric   unsigned diag_NeverFallThroughOrReturn;
5270b57cec5SDimitry Andric   enum { Function, Block, Lambda, Coroutine } funMode;
5280b57cec5SDimitry Andric   SourceLocation FuncLoc;
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
5310b57cec5SDimitry Andric     CheckFallThroughDiagnostics D;
5320b57cec5SDimitry Andric     D.FuncLoc = Func->getLocation();
5330b57cec5SDimitry Andric     D.diag_MaybeFallThrough_HasNoReturn =
5340b57cec5SDimitry Andric       diag::warn_falloff_noreturn_function;
5350b57cec5SDimitry Andric     D.diag_MaybeFallThrough_ReturnsNonVoid =
5360b57cec5SDimitry Andric       diag::warn_maybe_falloff_nonvoid_function;
5370b57cec5SDimitry Andric     D.diag_AlwaysFallThrough_HasNoReturn =
5380b57cec5SDimitry Andric       diag::warn_falloff_noreturn_function;
5390b57cec5SDimitry Andric     D.diag_AlwaysFallThrough_ReturnsNonVoid =
5400b57cec5SDimitry Andric       diag::warn_falloff_nonvoid_function;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric     // Don't suggest that virtual functions be marked "noreturn", since they
5430b57cec5SDimitry Andric     // might be overridden by non-noreturn functions.
5440b57cec5SDimitry Andric     bool isVirtualMethod = false;
5450b57cec5SDimitry Andric     if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
5460b57cec5SDimitry Andric       isVirtualMethod = Method->isVirtual();
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric     // Don't suggest that template instantiations be marked "noreturn"
5490b57cec5SDimitry Andric     bool isTemplateInstantiation = false;
5500b57cec5SDimitry Andric     if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
5510b57cec5SDimitry Andric       isTemplateInstantiation = Function->isTemplateInstantiation();
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric     if (!isVirtualMethod && !isTemplateInstantiation)
5540b57cec5SDimitry Andric       D.diag_NeverFallThroughOrReturn =
5550b57cec5SDimitry Andric         diag::warn_suggest_noreturn_function;
5560b57cec5SDimitry Andric     else
5570b57cec5SDimitry Andric       D.diag_NeverFallThroughOrReturn = 0;
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric     D.funMode = Function;
5600b57cec5SDimitry Andric     return D;
5610b57cec5SDimitry Andric   }
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   static CheckFallThroughDiagnostics MakeForCoroutine(const Decl *Func) {
5640b57cec5SDimitry Andric     CheckFallThroughDiagnostics D;
5650b57cec5SDimitry Andric     D.FuncLoc = Func->getLocation();
5660b57cec5SDimitry Andric     D.diag_MaybeFallThrough_HasNoReturn = 0;
5670b57cec5SDimitry Andric     D.diag_MaybeFallThrough_ReturnsNonVoid =
5680b57cec5SDimitry Andric         diag::warn_maybe_falloff_nonvoid_coroutine;
5690b57cec5SDimitry Andric     D.diag_AlwaysFallThrough_HasNoReturn = 0;
5700b57cec5SDimitry Andric     D.diag_AlwaysFallThrough_ReturnsNonVoid =
5710b57cec5SDimitry Andric         diag::warn_falloff_nonvoid_coroutine;
5720b57cec5SDimitry Andric     D.funMode = Coroutine;
5730b57cec5SDimitry Andric     return D;
5740b57cec5SDimitry Andric   }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric   static CheckFallThroughDiagnostics MakeForBlock() {
5770b57cec5SDimitry Andric     CheckFallThroughDiagnostics D;
5780b57cec5SDimitry Andric     D.diag_MaybeFallThrough_HasNoReturn =
5790b57cec5SDimitry Andric       diag::err_noreturn_block_has_return_expr;
5800b57cec5SDimitry Andric     D.diag_MaybeFallThrough_ReturnsNonVoid =
5810b57cec5SDimitry Andric       diag::err_maybe_falloff_nonvoid_block;
5820b57cec5SDimitry Andric     D.diag_AlwaysFallThrough_HasNoReturn =
5830b57cec5SDimitry Andric       diag::err_noreturn_block_has_return_expr;
5840b57cec5SDimitry Andric     D.diag_AlwaysFallThrough_ReturnsNonVoid =
5850b57cec5SDimitry Andric       diag::err_falloff_nonvoid_block;
5860b57cec5SDimitry Andric     D.diag_NeverFallThroughOrReturn = 0;
5870b57cec5SDimitry Andric     D.funMode = Block;
5880b57cec5SDimitry Andric     return D;
5890b57cec5SDimitry Andric   }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   static CheckFallThroughDiagnostics MakeForLambda() {
5920b57cec5SDimitry Andric     CheckFallThroughDiagnostics D;
5930b57cec5SDimitry Andric     D.diag_MaybeFallThrough_HasNoReturn =
5940b57cec5SDimitry Andric       diag::err_noreturn_lambda_has_return_expr;
5950b57cec5SDimitry Andric     D.diag_MaybeFallThrough_ReturnsNonVoid =
5960b57cec5SDimitry Andric       diag::warn_maybe_falloff_nonvoid_lambda;
5970b57cec5SDimitry Andric     D.diag_AlwaysFallThrough_HasNoReturn =
5980b57cec5SDimitry Andric       diag::err_noreturn_lambda_has_return_expr;
5990b57cec5SDimitry Andric     D.diag_AlwaysFallThrough_ReturnsNonVoid =
6000b57cec5SDimitry Andric       diag::warn_falloff_nonvoid_lambda;
6010b57cec5SDimitry Andric     D.diag_NeverFallThroughOrReturn = 0;
6020b57cec5SDimitry Andric     D.funMode = Lambda;
6030b57cec5SDimitry Andric     return D;
6040b57cec5SDimitry Andric   }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid,
6070b57cec5SDimitry Andric                         bool HasNoReturn) const {
6080b57cec5SDimitry Andric     if (funMode == Function) {
6090b57cec5SDimitry Andric       return (ReturnsVoid ||
6100b57cec5SDimitry Andric               D.isIgnored(diag::warn_maybe_falloff_nonvoid_function,
6110b57cec5SDimitry Andric                           FuncLoc)) &&
6120b57cec5SDimitry Andric              (!HasNoReturn ||
6130b57cec5SDimitry Andric               D.isIgnored(diag::warn_noreturn_function_has_return_expr,
6140b57cec5SDimitry Andric                           FuncLoc)) &&
6150b57cec5SDimitry Andric              (!ReturnsVoid ||
6160b57cec5SDimitry Andric               D.isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
6170b57cec5SDimitry Andric     }
6180b57cec5SDimitry Andric     if (funMode == Coroutine) {
6190b57cec5SDimitry Andric       return (ReturnsVoid ||
6200b57cec5SDimitry Andric               D.isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
6210b57cec5SDimitry Andric               D.isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
6220b57cec5SDimitry Andric                           FuncLoc)) &&
6230b57cec5SDimitry Andric              (!HasNoReturn);
6240b57cec5SDimitry Andric     }
6250b57cec5SDimitry Andric     // For blocks / lambdas.
6260b57cec5SDimitry Andric     return ReturnsVoid && !HasNoReturn;
6270b57cec5SDimitry Andric   }
6280b57cec5SDimitry Andric };
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric } // anonymous namespace
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric /// CheckFallThroughForBody - Check that we don't fall off the end of a
6330b57cec5SDimitry Andric /// function that should return a value.  Check that we don't fall off the end
6340b57cec5SDimitry Andric /// of a noreturn function.  We assume that functions and blocks not marked
6350b57cec5SDimitry Andric /// noreturn will return.
6360b57cec5SDimitry Andric static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
6370b57cec5SDimitry Andric                                     QualType BlockType,
6380b57cec5SDimitry Andric                                     const CheckFallThroughDiagnostics &CD,
6390b57cec5SDimitry Andric                                     AnalysisDeclContext &AC,
6400b57cec5SDimitry Andric                                     sema::FunctionScopeInfo *FSI) {
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric   bool ReturnsVoid = false;
6430b57cec5SDimitry Andric   bool HasNoReturn = false;
6440b57cec5SDimitry Andric   bool IsCoroutine = FSI->isCoroutine();
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
6470b57cec5SDimitry Andric     if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
6480b57cec5SDimitry Andric       ReturnsVoid = CBody->getFallthroughHandler() != nullptr;
6490b57cec5SDimitry Andric     else
6500b57cec5SDimitry Andric       ReturnsVoid = FD->getReturnType()->isVoidType();
6510b57cec5SDimitry Andric     HasNoReturn = FD->isNoReturn();
6520b57cec5SDimitry Andric   }
6530b57cec5SDimitry Andric   else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
6540b57cec5SDimitry Andric     ReturnsVoid = MD->getReturnType()->isVoidType();
6550b57cec5SDimitry Andric     HasNoReturn = MD->hasAttr<NoReturnAttr>();
6560b57cec5SDimitry Andric   }
6570b57cec5SDimitry Andric   else if (isa<BlockDecl>(D)) {
6580b57cec5SDimitry Andric     if (const FunctionType *FT =
6590b57cec5SDimitry Andric           BlockType->getPointeeType()->getAs<FunctionType>()) {
6600b57cec5SDimitry Andric       if (FT->getReturnType()->isVoidType())
6610b57cec5SDimitry Andric         ReturnsVoid = true;
6620b57cec5SDimitry Andric       if (FT->getNoReturnAttr())
6630b57cec5SDimitry Andric         HasNoReturn = true;
6640b57cec5SDimitry Andric     }
6650b57cec5SDimitry Andric   }
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   DiagnosticsEngine &Diags = S.getDiagnostics();
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric   // Short circuit for compilation speed.
6700b57cec5SDimitry Andric   if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
6710b57cec5SDimitry Andric       return;
6720b57cec5SDimitry Andric   SourceLocation LBrace = Body->getBeginLoc(), RBrace = Body->getEndLoc();
6730b57cec5SDimitry Andric   auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
6740b57cec5SDimitry Andric     if (IsCoroutine)
6750b57cec5SDimitry Andric       S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType();
6760b57cec5SDimitry Andric     else
6770b57cec5SDimitry Andric       S.Diag(Loc, DiagID);
6780b57cec5SDimitry Andric   };
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric   // cpu_dispatch functions permit empty function bodies for ICC compatibility.
6810b57cec5SDimitry Andric   if (D->getAsFunction() && D->getAsFunction()->isCPUDispatchMultiVersion())
6820b57cec5SDimitry Andric     return;
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   // Either in a function body compound statement, or a function-try-block.
6850b57cec5SDimitry Andric   switch (CheckFallThrough(AC)) {
6860b57cec5SDimitry Andric     case UnknownFallThrough:
6870b57cec5SDimitry Andric       break;
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric     case MaybeFallThrough:
6900b57cec5SDimitry Andric       if (HasNoReturn)
6910b57cec5SDimitry Andric         EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
6920b57cec5SDimitry Andric       else if (!ReturnsVoid)
6930b57cec5SDimitry Andric         EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
6940b57cec5SDimitry Andric       break;
6950b57cec5SDimitry Andric     case AlwaysFallThrough:
6960b57cec5SDimitry Andric       if (HasNoReturn)
6970b57cec5SDimitry Andric         EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
6980b57cec5SDimitry Andric       else if (!ReturnsVoid)
6990b57cec5SDimitry Andric         EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
7000b57cec5SDimitry Andric       break;
7010b57cec5SDimitry Andric     case NeverFallThroughOrReturn:
7020b57cec5SDimitry Andric       if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
7030b57cec5SDimitry Andric         if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
7040b57cec5SDimitry Andric           S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
7050b57cec5SDimitry Andric         } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
7060b57cec5SDimitry Andric           S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
7070b57cec5SDimitry Andric         } else {
7080b57cec5SDimitry Andric           S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
7090b57cec5SDimitry Andric         }
7100b57cec5SDimitry Andric       }
7110b57cec5SDimitry Andric       break;
7120b57cec5SDimitry Andric     case NeverFallThrough:
7130b57cec5SDimitry Andric       break;
7140b57cec5SDimitry Andric   }
7150b57cec5SDimitry Andric }
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
7180b57cec5SDimitry Andric // -Wuninitialized
7190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric namespace {
7220b57cec5SDimitry Andric /// ContainsReference - A visitor class to search for references to
7230b57cec5SDimitry Andric /// a particular declaration (the needle) within any evaluated component of an
7240b57cec5SDimitry Andric /// expression (recursively).
7250b57cec5SDimitry Andric class ContainsReference : public ConstEvaluatedExprVisitor<ContainsReference> {
7260b57cec5SDimitry Andric   bool FoundReference;
7270b57cec5SDimitry Andric   const DeclRefExpr *Needle;
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric public:
7300b57cec5SDimitry Andric   typedef ConstEvaluatedExprVisitor<ContainsReference> Inherited;
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric   ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
7330b57cec5SDimitry Andric     : Inherited(Context), FoundReference(false), Needle(Needle) {}
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric   void VisitExpr(const Expr *E) {
7360b57cec5SDimitry Andric     // Stop evaluating if we already have a reference.
7370b57cec5SDimitry Andric     if (FoundReference)
7380b57cec5SDimitry Andric       return;
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric     Inherited::VisitExpr(E);
7410b57cec5SDimitry Andric   }
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   void VisitDeclRefExpr(const DeclRefExpr *E) {
7440b57cec5SDimitry Andric     if (E == Needle)
7450b57cec5SDimitry Andric       FoundReference = true;
7460b57cec5SDimitry Andric     else
7470b57cec5SDimitry Andric       Inherited::VisitDeclRefExpr(E);
7480b57cec5SDimitry Andric   }
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric   bool doesContainReference() const { return FoundReference; }
7510b57cec5SDimitry Andric };
7520b57cec5SDimitry Andric } // anonymous namespace
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
7550b57cec5SDimitry Andric   QualType VariableTy = VD->getType().getCanonicalType();
7560b57cec5SDimitry Andric   if (VariableTy->isBlockPointerType() &&
7570b57cec5SDimitry Andric       !VD->hasAttr<BlocksAttr>()) {
7580b57cec5SDimitry Andric     S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization)
7590b57cec5SDimitry Andric         << VD->getDeclName()
7600b57cec5SDimitry Andric         << FixItHint::CreateInsertion(VD->getLocation(), "__block ");
7610b57cec5SDimitry Andric     return true;
7620b57cec5SDimitry Andric   }
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric   // Don't issue a fixit if there is already an initializer.
7650b57cec5SDimitry Andric   if (VD->getInit())
7660b57cec5SDimitry Andric     return false;
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric   // Don't suggest a fixit inside macros.
7690b57cec5SDimitry Andric   if (VD->getEndLoc().isMacroID())
7700b57cec5SDimitry Andric     return false;
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric   SourceLocation Loc = S.getLocForEndOfToken(VD->getEndLoc());
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric   // Suggest possible initialization (if any).
7750b57cec5SDimitry Andric   std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
7760b57cec5SDimitry Andric   if (Init.empty())
7770b57cec5SDimitry Andric     return false;
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric   S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()
7800b57cec5SDimitry Andric     << FixItHint::CreateInsertion(Loc, Init);
7810b57cec5SDimitry Andric   return true;
7820b57cec5SDimitry Andric }
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric /// Create a fixit to remove an if-like statement, on the assumption that its
7850b57cec5SDimitry Andric /// condition is CondVal.
7860b57cec5SDimitry Andric static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then,
7870b57cec5SDimitry Andric                           const Stmt *Else, bool CondVal,
7880b57cec5SDimitry Andric                           FixItHint &Fixit1, FixItHint &Fixit2) {
7890b57cec5SDimitry Andric   if (CondVal) {
7900b57cec5SDimitry Andric     // If condition is always true, remove all but the 'then'.
7910b57cec5SDimitry Andric     Fixit1 = FixItHint::CreateRemoval(
7920b57cec5SDimitry Andric         CharSourceRange::getCharRange(If->getBeginLoc(), Then->getBeginLoc()));
7930b57cec5SDimitry Andric     if (Else) {
7940b57cec5SDimitry Andric       SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getEndLoc());
7950b57cec5SDimitry Andric       Fixit2 =
7960b57cec5SDimitry Andric           FixItHint::CreateRemoval(SourceRange(ElseKwLoc, Else->getEndLoc()));
7970b57cec5SDimitry Andric     }
7980b57cec5SDimitry Andric   } else {
7990b57cec5SDimitry Andric     // If condition is always false, remove all but the 'else'.
8000b57cec5SDimitry Andric     if (Else)
8010b57cec5SDimitry Andric       Fixit1 = FixItHint::CreateRemoval(CharSourceRange::getCharRange(
8020b57cec5SDimitry Andric           If->getBeginLoc(), Else->getBeginLoc()));
8030b57cec5SDimitry Andric     else
8040b57cec5SDimitry Andric       Fixit1 = FixItHint::CreateRemoval(If->getSourceRange());
8050b57cec5SDimitry Andric   }
8060b57cec5SDimitry Andric }
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric /// DiagUninitUse -- Helper function to produce a diagnostic for an
8090b57cec5SDimitry Andric /// uninitialized use of a variable.
8100b57cec5SDimitry Andric static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
8110b57cec5SDimitry Andric                           bool IsCapturedByBlock) {
8120b57cec5SDimitry Andric   bool Diagnosed = false;
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric   switch (Use.getKind()) {
8150b57cec5SDimitry Andric   case UninitUse::Always:
8160b57cec5SDimitry Andric     S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_var)
8170b57cec5SDimitry Andric         << VD->getDeclName() << IsCapturedByBlock
8180b57cec5SDimitry Andric         << Use.getUser()->getSourceRange();
8190b57cec5SDimitry Andric     return;
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric   case UninitUse::AfterDecl:
8220b57cec5SDimitry Andric   case UninitUse::AfterCall:
8230b57cec5SDimitry Andric     S.Diag(VD->getLocation(), diag::warn_sometimes_uninit_var)
8240b57cec5SDimitry Andric       << VD->getDeclName() << IsCapturedByBlock
8250b57cec5SDimitry Andric       << (Use.getKind() == UninitUse::AfterDecl ? 4 : 5)
8260b57cec5SDimitry Andric       << const_cast<DeclContext*>(VD->getLexicalDeclContext())
8270b57cec5SDimitry Andric       << VD->getSourceRange();
8280b57cec5SDimitry Andric     S.Diag(Use.getUser()->getBeginLoc(), diag::note_uninit_var_use)
8290b57cec5SDimitry Andric         << IsCapturedByBlock << Use.getUser()->getSourceRange();
8300b57cec5SDimitry Andric     return;
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   case UninitUse::Maybe:
8330b57cec5SDimitry Andric   case UninitUse::Sometimes:
8340b57cec5SDimitry Andric     // Carry on to report sometimes-uninitialized branches, if possible,
8350b57cec5SDimitry Andric     // or a 'may be used uninitialized' diagnostic otherwise.
8360b57cec5SDimitry Andric     break;
8370b57cec5SDimitry Andric   }
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric   // Diagnose each branch which leads to a sometimes-uninitialized use.
8400b57cec5SDimitry Andric   for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end();
8410b57cec5SDimitry Andric        I != E; ++I) {
8420b57cec5SDimitry Andric     assert(Use.getKind() == UninitUse::Sometimes);
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric     const Expr *User = Use.getUser();
8450b57cec5SDimitry Andric     const Stmt *Term = I->Terminator;
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric     // Information used when building the diagnostic.
8480b57cec5SDimitry Andric     unsigned DiagKind;
8490b57cec5SDimitry Andric     StringRef Str;
8500b57cec5SDimitry Andric     SourceRange Range;
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric     // FixIts to suppress the diagnostic by removing the dead condition.
8530b57cec5SDimitry Andric     // For all binary terminators, branch 0 is taken if the condition is true,
8540b57cec5SDimitry Andric     // and branch 1 is taken if the condition is false.
8550b57cec5SDimitry Andric     int RemoveDiagKind = -1;
8560b57cec5SDimitry Andric     const char *FixitStr =
8570b57cec5SDimitry Andric         S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false")
8580b57cec5SDimitry Andric                                   : (I->Output ? "1" : "0");
8590b57cec5SDimitry Andric     FixItHint Fixit1, Fixit2;
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric     switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) {
8620b57cec5SDimitry Andric     default:
8630b57cec5SDimitry Andric       // Don't know how to report this. Just fall back to 'may be used
8640b57cec5SDimitry Andric       // uninitialized'. FIXME: Can this happen?
8650b57cec5SDimitry Andric       continue;
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric     // "condition is true / condition is false".
8680b57cec5SDimitry Andric     case Stmt::IfStmtClass: {
8690b57cec5SDimitry Andric       const IfStmt *IS = cast<IfStmt>(Term);
8700b57cec5SDimitry Andric       DiagKind = 0;
8710b57cec5SDimitry Andric       Str = "if";
8720b57cec5SDimitry Andric       Range = IS->getCond()->getSourceRange();
8730b57cec5SDimitry Andric       RemoveDiagKind = 0;
8740b57cec5SDimitry Andric       CreateIfFixit(S, IS, IS->getThen(), IS->getElse(),
8750b57cec5SDimitry Andric                     I->Output, Fixit1, Fixit2);
8760b57cec5SDimitry Andric       break;
8770b57cec5SDimitry Andric     }
8780b57cec5SDimitry Andric     case Stmt::ConditionalOperatorClass: {
8790b57cec5SDimitry Andric       const ConditionalOperator *CO = cast<ConditionalOperator>(Term);
8800b57cec5SDimitry Andric       DiagKind = 0;
8810b57cec5SDimitry Andric       Str = "?:";
8820b57cec5SDimitry Andric       Range = CO->getCond()->getSourceRange();
8830b57cec5SDimitry Andric       RemoveDiagKind = 0;
8840b57cec5SDimitry Andric       CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(),
8850b57cec5SDimitry Andric                     I->Output, Fixit1, Fixit2);
8860b57cec5SDimitry Andric       break;
8870b57cec5SDimitry Andric     }
8880b57cec5SDimitry Andric     case Stmt::BinaryOperatorClass: {
8890b57cec5SDimitry Andric       const BinaryOperator *BO = cast<BinaryOperator>(Term);
8900b57cec5SDimitry Andric       if (!BO->isLogicalOp())
8910b57cec5SDimitry Andric         continue;
8920b57cec5SDimitry Andric       DiagKind = 0;
8930b57cec5SDimitry Andric       Str = BO->getOpcodeStr();
8940b57cec5SDimitry Andric       Range = BO->getLHS()->getSourceRange();
8950b57cec5SDimitry Andric       RemoveDiagKind = 0;
8960b57cec5SDimitry Andric       if ((BO->getOpcode() == BO_LAnd && I->Output) ||
8970b57cec5SDimitry Andric           (BO->getOpcode() == BO_LOr && !I->Output))
8980b57cec5SDimitry Andric         // true && y -> y, false || y -> y.
8990b57cec5SDimitry Andric         Fixit1 = FixItHint::CreateRemoval(
9000b57cec5SDimitry Andric             SourceRange(BO->getBeginLoc(), BO->getOperatorLoc()));
9010b57cec5SDimitry Andric       else
9020b57cec5SDimitry Andric         // false && y -> false, true || y -> true.
9030b57cec5SDimitry Andric         Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr);
9040b57cec5SDimitry Andric       break;
9050b57cec5SDimitry Andric     }
9060b57cec5SDimitry Andric 
9070b57cec5SDimitry Andric     // "loop is entered / loop is exited".
9080b57cec5SDimitry Andric     case Stmt::WhileStmtClass:
9090b57cec5SDimitry Andric       DiagKind = 1;
9100b57cec5SDimitry Andric       Str = "while";
9110b57cec5SDimitry Andric       Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
9120b57cec5SDimitry Andric       RemoveDiagKind = 1;
9130b57cec5SDimitry Andric       Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
9140b57cec5SDimitry Andric       break;
9150b57cec5SDimitry Andric     case Stmt::ForStmtClass:
9160b57cec5SDimitry Andric       DiagKind = 1;
9170b57cec5SDimitry Andric       Str = "for";
9180b57cec5SDimitry Andric       Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
9190b57cec5SDimitry Andric       RemoveDiagKind = 1;
9200b57cec5SDimitry Andric       if (I->Output)
9210b57cec5SDimitry Andric         Fixit1 = FixItHint::CreateRemoval(Range);
9220b57cec5SDimitry Andric       else
9230b57cec5SDimitry Andric         Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
9240b57cec5SDimitry Andric       break;
9250b57cec5SDimitry Andric     case Stmt::CXXForRangeStmtClass:
9260b57cec5SDimitry Andric       if (I->Output == 1) {
9270b57cec5SDimitry Andric         // The use occurs if a range-based for loop's body never executes.
9280b57cec5SDimitry Andric         // That may be impossible, and there's no syntactic fix for this,
9290b57cec5SDimitry Andric         // so treat it as a 'may be uninitialized' case.
9300b57cec5SDimitry Andric         continue;
9310b57cec5SDimitry Andric       }
9320b57cec5SDimitry Andric       DiagKind = 1;
9330b57cec5SDimitry Andric       Str = "for";
9340b57cec5SDimitry Andric       Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
9350b57cec5SDimitry Andric       break;
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric     // "condition is true / loop is exited".
9380b57cec5SDimitry Andric     case Stmt::DoStmtClass:
9390b57cec5SDimitry Andric       DiagKind = 2;
9400b57cec5SDimitry Andric       Str = "do";
9410b57cec5SDimitry Andric       Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
9420b57cec5SDimitry Andric       RemoveDiagKind = 1;
9430b57cec5SDimitry Andric       Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
9440b57cec5SDimitry Andric       break;
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric     // "switch case is taken".
9470b57cec5SDimitry Andric     case Stmt::CaseStmtClass:
9480b57cec5SDimitry Andric       DiagKind = 3;
9490b57cec5SDimitry Andric       Str = "case";
9500b57cec5SDimitry Andric       Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
9510b57cec5SDimitry Andric       break;
9520b57cec5SDimitry Andric     case Stmt::DefaultStmtClass:
9530b57cec5SDimitry Andric       DiagKind = 3;
9540b57cec5SDimitry Andric       Str = "default";
9550b57cec5SDimitry Andric       Range = cast<DefaultStmt>(Term)->getDefaultLoc();
9560b57cec5SDimitry Andric       break;
9570b57cec5SDimitry Andric     }
9580b57cec5SDimitry Andric 
9590b57cec5SDimitry Andric     S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var)
9600b57cec5SDimitry Andric       << VD->getDeclName() << IsCapturedByBlock << DiagKind
9610b57cec5SDimitry Andric       << Str << I->Output << Range;
9620b57cec5SDimitry Andric     S.Diag(User->getBeginLoc(), diag::note_uninit_var_use)
9630b57cec5SDimitry Andric         << IsCapturedByBlock << User->getSourceRange();
9640b57cec5SDimitry Andric     if (RemoveDiagKind != -1)
9650b57cec5SDimitry Andric       S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond)
9660b57cec5SDimitry Andric         << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
9670b57cec5SDimitry Andric 
9680b57cec5SDimitry Andric     Diagnosed = true;
9690b57cec5SDimitry Andric   }
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric   if (!Diagnosed)
9720b57cec5SDimitry Andric     S.Diag(Use.getUser()->getBeginLoc(), diag::warn_maybe_uninit_var)
9730b57cec5SDimitry Andric         << VD->getDeclName() << IsCapturedByBlock
9740b57cec5SDimitry Andric         << Use.getUser()->getSourceRange();
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric /// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
9780b57cec5SDimitry Andric /// uninitialized variable. This manages the different forms of diagnostic
9790b57cec5SDimitry Andric /// emitted for particular types of uses. Returns true if the use was diagnosed
9800b57cec5SDimitry Andric /// as a warning. If a particular use is one we omit warnings for, returns
9810b57cec5SDimitry Andric /// false.
9820b57cec5SDimitry Andric static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
9830b57cec5SDimitry Andric                                      const UninitUse &Use,
9840b57cec5SDimitry Andric                                      bool alwaysReportSelfInit = false) {
9850b57cec5SDimitry Andric   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) {
9860b57cec5SDimitry Andric     // Inspect the initializer of the variable declaration which is
9870b57cec5SDimitry Andric     // being referenced prior to its initialization. We emit
9880b57cec5SDimitry Andric     // specialized diagnostics for self-initialization, and we
9890b57cec5SDimitry Andric     // specifically avoid warning about self references which take the
9900b57cec5SDimitry Andric     // form of:
9910b57cec5SDimitry Andric     //
9920b57cec5SDimitry Andric     //   int x = x;
9930b57cec5SDimitry Andric     //
9940b57cec5SDimitry Andric     // This is used to indicate to GCC that 'x' is intentionally left
9950b57cec5SDimitry Andric     // uninitialized. Proven code paths which access 'x' in
9960b57cec5SDimitry Andric     // an uninitialized state after this will still warn.
9970b57cec5SDimitry Andric     if (const Expr *Initializer = VD->getInit()) {
9980b57cec5SDimitry Andric       if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
9990b57cec5SDimitry Andric         return false;
10000b57cec5SDimitry Andric 
10010b57cec5SDimitry Andric       ContainsReference CR(S.Context, DRE);
10020b57cec5SDimitry Andric       CR.Visit(Initializer);
10030b57cec5SDimitry Andric       if (CR.doesContainReference()) {
10040b57cec5SDimitry Andric         S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
10050b57cec5SDimitry Andric             << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
10060b57cec5SDimitry Andric         return true;
10070b57cec5SDimitry Andric       }
10080b57cec5SDimitry Andric     }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric     DiagUninitUse(S, VD, Use, false);
10110b57cec5SDimitry Andric   } else {
10120b57cec5SDimitry Andric     const BlockExpr *BE = cast<BlockExpr>(Use.getUser());
10130b57cec5SDimitry Andric     if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>())
10140b57cec5SDimitry Andric       S.Diag(BE->getBeginLoc(),
10150b57cec5SDimitry Andric              diag::warn_uninit_byref_blockvar_captured_by_block)
10160b57cec5SDimitry Andric           << VD->getDeclName()
10170b57cec5SDimitry Andric           << VD->getType().getQualifiers().hasObjCLifetime();
10180b57cec5SDimitry Andric     else
10190b57cec5SDimitry Andric       DiagUninitUse(S, VD, Use, true);
10200b57cec5SDimitry Andric   }
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric   // Report where the variable was declared when the use wasn't within
10230b57cec5SDimitry Andric   // the initializer of that declaration & we didn't already suggest
10240b57cec5SDimitry Andric   // an initialization fixit.
10250b57cec5SDimitry Andric   if (!SuggestInitializationFixit(S, VD))
10260b57cec5SDimitry Andric     S.Diag(VD->getBeginLoc(), diag::note_var_declared_here)
10270b57cec5SDimitry Andric         << VD->getDeclName();
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric   return true;
10300b57cec5SDimitry Andric }
10310b57cec5SDimitry Andric 
10320b57cec5SDimitry Andric namespace {
10330b57cec5SDimitry Andric   class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> {
10340b57cec5SDimitry Andric   public:
10350b57cec5SDimitry Andric     FallthroughMapper(Sema &S)
10360b57cec5SDimitry Andric       : FoundSwitchStatements(false),
10370b57cec5SDimitry Andric         S(S) {
10380b57cec5SDimitry Andric     }
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric     bool foundSwitchStatements() const { return FoundSwitchStatements; }
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric     void markFallthroughVisited(const AttributedStmt *Stmt) {
10430b57cec5SDimitry Andric       bool Found = FallthroughStmts.erase(Stmt);
10440b57cec5SDimitry Andric       assert(Found);
10450b57cec5SDimitry Andric       (void)Found;
10460b57cec5SDimitry Andric     }
10470b57cec5SDimitry Andric 
10480b57cec5SDimitry Andric     typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric     const AttrStmts &getFallthroughStmts() const {
10510b57cec5SDimitry Andric       return FallthroughStmts;
10520b57cec5SDimitry Andric     }
10530b57cec5SDimitry Andric 
10540b57cec5SDimitry Andric     void fillReachableBlocks(CFG *Cfg) {
10550b57cec5SDimitry Andric       assert(ReachableBlocks.empty() && "ReachableBlocks already filled");
10560b57cec5SDimitry Andric       std::deque<const CFGBlock *> BlockQueue;
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric       ReachableBlocks.insert(&Cfg->getEntry());
10590b57cec5SDimitry Andric       BlockQueue.push_back(&Cfg->getEntry());
10600b57cec5SDimitry Andric       // Mark all case blocks reachable to avoid problems with switching on
10610b57cec5SDimitry Andric       // constants, covered enums, etc.
10620b57cec5SDimitry Andric       // These blocks can contain fall-through annotations, and we don't want to
10630b57cec5SDimitry Andric       // issue a warn_fallthrough_attr_unreachable for them.
10640b57cec5SDimitry Andric       for (const auto *B : *Cfg) {
10650b57cec5SDimitry Andric         const Stmt *L = B->getLabel();
10660b57cec5SDimitry Andric         if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
10670b57cec5SDimitry Andric           BlockQueue.push_back(B);
10680b57cec5SDimitry Andric       }
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric       while (!BlockQueue.empty()) {
10710b57cec5SDimitry Andric         const CFGBlock *P = BlockQueue.front();
10720b57cec5SDimitry Andric         BlockQueue.pop_front();
10730b57cec5SDimitry Andric         for (CFGBlock::const_succ_iterator I = P->succ_begin(),
10740b57cec5SDimitry Andric                                            E = P->succ_end();
10750b57cec5SDimitry Andric              I != E; ++I) {
10760b57cec5SDimitry Andric           if (*I && ReachableBlocks.insert(*I).second)
10770b57cec5SDimitry Andric             BlockQueue.push_back(*I);
10780b57cec5SDimitry Andric         }
10790b57cec5SDimitry Andric       }
10800b57cec5SDimitry Andric     }
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric     bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt,
10830b57cec5SDimitry Andric                                    bool IsTemplateInstantiation) {
10840b57cec5SDimitry Andric       assert(!ReachableBlocks.empty() && "ReachableBlocks empty");
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric       int UnannotatedCnt = 0;
10870b57cec5SDimitry Andric       AnnotatedCnt = 0;
10880b57cec5SDimitry Andric 
10890b57cec5SDimitry Andric       std::deque<const CFGBlock*> BlockQueue(B.pred_begin(), B.pred_end());
10900b57cec5SDimitry Andric       while (!BlockQueue.empty()) {
10910b57cec5SDimitry Andric         const CFGBlock *P = BlockQueue.front();
10920b57cec5SDimitry Andric         BlockQueue.pop_front();
10930b57cec5SDimitry Andric         if (!P) continue;
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric         const Stmt *Term = P->getTerminatorStmt();
10960b57cec5SDimitry Andric         if (Term && isa<SwitchStmt>(Term))
10970b57cec5SDimitry Andric           continue; // Switch statement, good.
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric         const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel());
11000b57cec5SDimitry Andric         if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end())
11010b57cec5SDimitry Andric           continue; // Previous case label has no statements, good.
11020b57cec5SDimitry Andric 
11030b57cec5SDimitry Andric         const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel());
11040b57cec5SDimitry Andric         if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end())
11050b57cec5SDimitry Andric           continue; // Case label is preceded with a normal label, good.
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric         if (!ReachableBlocks.count(P)) {
11080b57cec5SDimitry Andric           for (CFGBlock::const_reverse_iterator ElemIt = P->rbegin(),
11090b57cec5SDimitry Andric                                                 ElemEnd = P->rend();
11100b57cec5SDimitry Andric                ElemIt != ElemEnd; ++ElemIt) {
11110b57cec5SDimitry Andric             if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) {
11120b57cec5SDimitry Andric               if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
11130b57cec5SDimitry Andric                 // Don't issue a warning for an unreachable fallthrough
11140b57cec5SDimitry Andric                 // attribute in template instantiations as it may not be
11150b57cec5SDimitry Andric                 // unreachable in all instantiations of the template.
11160b57cec5SDimitry Andric                 if (!IsTemplateInstantiation)
11170b57cec5SDimitry Andric                   S.Diag(AS->getBeginLoc(),
11180b57cec5SDimitry Andric                          diag::warn_fallthrough_attr_unreachable);
11190b57cec5SDimitry Andric                 markFallthroughVisited(AS);
11200b57cec5SDimitry Andric                 ++AnnotatedCnt;
11210b57cec5SDimitry Andric                 break;
11220b57cec5SDimitry Andric               }
11230b57cec5SDimitry Andric               // Don't care about other unreachable statements.
11240b57cec5SDimitry Andric             }
11250b57cec5SDimitry Andric           }
11260b57cec5SDimitry Andric           // If there are no unreachable statements, this may be a special
11270b57cec5SDimitry Andric           // case in CFG:
11280b57cec5SDimitry Andric           // case X: {
11290b57cec5SDimitry Andric           //    A a;  // A has a destructor.
11300b57cec5SDimitry Andric           //    break;
11310b57cec5SDimitry Andric           // }
11320b57cec5SDimitry Andric           // // <<<< This place is represented by a 'hanging' CFG block.
11330b57cec5SDimitry Andric           // case Y:
11340b57cec5SDimitry Andric           continue;
11350b57cec5SDimitry Andric         }
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric         const Stmt *LastStmt = getLastStmt(*P);
11380b57cec5SDimitry Andric         if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) {
11390b57cec5SDimitry Andric           markFallthroughVisited(AS);
11400b57cec5SDimitry Andric           ++AnnotatedCnt;
11410b57cec5SDimitry Andric           continue; // Fallthrough annotation, good.
11420b57cec5SDimitry Andric         }
11430b57cec5SDimitry Andric 
11440b57cec5SDimitry Andric         if (!LastStmt) { // This block contains no executable statements.
11450b57cec5SDimitry Andric           // Traverse its predecessors.
11460b57cec5SDimitry Andric           std::copy(P->pred_begin(), P->pred_end(),
11470b57cec5SDimitry Andric                     std::back_inserter(BlockQueue));
11480b57cec5SDimitry Andric           continue;
11490b57cec5SDimitry Andric         }
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric         ++UnannotatedCnt;
11520b57cec5SDimitry Andric       }
11530b57cec5SDimitry Andric       return !!UnannotatedCnt;
11540b57cec5SDimitry Andric     }
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric     // RecursiveASTVisitor setup.
11570b57cec5SDimitry Andric     bool shouldWalkTypesOfTypeLocs() const { return false; }
11580b57cec5SDimitry Andric 
11590b57cec5SDimitry Andric     bool VisitAttributedStmt(AttributedStmt *S) {
11600b57cec5SDimitry Andric       if (asFallThroughAttr(S))
11610b57cec5SDimitry Andric         FallthroughStmts.insert(S);
11620b57cec5SDimitry Andric       return true;
11630b57cec5SDimitry Andric     }
11640b57cec5SDimitry Andric 
11650b57cec5SDimitry Andric     bool VisitSwitchStmt(SwitchStmt *S) {
11660b57cec5SDimitry Andric       FoundSwitchStatements = true;
11670b57cec5SDimitry Andric       return true;
11680b57cec5SDimitry Andric     }
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric     // We don't want to traverse local type declarations. We analyze their
11710b57cec5SDimitry Andric     // methods separately.
11720b57cec5SDimitry Andric     bool TraverseDecl(Decl *D) { return true; }
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric     // We analyze lambda bodies separately. Skip them here.
11750b57cec5SDimitry Andric     bool TraverseLambdaExpr(LambdaExpr *LE) {
11760b57cec5SDimitry Andric       // Traverse the captures, but not the body.
11770b57cec5SDimitry Andric       for (const auto &C : zip(LE->captures(), LE->capture_inits()))
11780b57cec5SDimitry Andric         TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
11790b57cec5SDimitry Andric       return true;
11800b57cec5SDimitry Andric     }
11810b57cec5SDimitry Andric 
11820b57cec5SDimitry Andric   private:
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric     static const AttributedStmt *asFallThroughAttr(const Stmt *S) {
11850b57cec5SDimitry Andric       if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
11860b57cec5SDimitry Andric         if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
11870b57cec5SDimitry Andric           return AS;
11880b57cec5SDimitry Andric       }
11890b57cec5SDimitry Andric       return nullptr;
11900b57cec5SDimitry Andric     }
11910b57cec5SDimitry Andric 
11920b57cec5SDimitry Andric     static const Stmt *getLastStmt(const CFGBlock &B) {
11930b57cec5SDimitry Andric       if (const Stmt *Term = B.getTerminatorStmt())
11940b57cec5SDimitry Andric         return Term;
11950b57cec5SDimitry Andric       for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(),
11960b57cec5SDimitry Andric                                             ElemEnd = B.rend();
11970b57cec5SDimitry Andric                                             ElemIt != ElemEnd; ++ElemIt) {
11980b57cec5SDimitry Andric         if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>())
11990b57cec5SDimitry Andric           return CS->getStmt();
12000b57cec5SDimitry Andric       }
12010b57cec5SDimitry Andric       // Workaround to detect a statement thrown out by CFGBuilder:
12020b57cec5SDimitry Andric       //   case X: {} case Y:
12030b57cec5SDimitry Andric       //   case X: ; case Y:
12040b57cec5SDimitry Andric       if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel()))
12050b57cec5SDimitry Andric         if (!isa<SwitchCase>(SW->getSubStmt()))
12060b57cec5SDimitry Andric           return SW->getSubStmt();
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric       return nullptr;
12090b57cec5SDimitry Andric     }
12100b57cec5SDimitry Andric 
12110b57cec5SDimitry Andric     bool FoundSwitchStatements;
12120b57cec5SDimitry Andric     AttrStmts FallthroughStmts;
12130b57cec5SDimitry Andric     Sema &S;
12140b57cec5SDimitry Andric     llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
12150b57cec5SDimitry Andric   };
12160b57cec5SDimitry Andric } // anonymous namespace
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric static StringRef getFallthroughAttrSpelling(Preprocessor &PP,
12190b57cec5SDimitry Andric                                             SourceLocation Loc) {
12200b57cec5SDimitry Andric   TokenValue FallthroughTokens[] = {
12210b57cec5SDimitry Andric     tok::l_square, tok::l_square,
12220b57cec5SDimitry Andric     PP.getIdentifierInfo("fallthrough"),
12230b57cec5SDimitry Andric     tok::r_square, tok::r_square
12240b57cec5SDimitry Andric   };
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric   TokenValue ClangFallthroughTokens[] = {
12270b57cec5SDimitry Andric     tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"),
12280b57cec5SDimitry Andric     tok::coloncolon, PP.getIdentifierInfo("fallthrough"),
12290b57cec5SDimitry Andric     tok::r_square, tok::r_square
12300b57cec5SDimitry Andric   };
12310b57cec5SDimitry Andric 
1232*a7dea167SDimitry Andric   bool PreferClangAttr = !PP.getLangOpts().CPlusPlus17 && !PP.getLangOpts().C2x;
12330b57cec5SDimitry Andric 
12340b57cec5SDimitry Andric   StringRef MacroName;
12350b57cec5SDimitry Andric   if (PreferClangAttr)
12360b57cec5SDimitry Andric     MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);
12370b57cec5SDimitry Andric   if (MacroName.empty())
12380b57cec5SDimitry Andric     MacroName = PP.getLastMacroWithSpelling(Loc, FallthroughTokens);
12390b57cec5SDimitry Andric   if (MacroName.empty() && !PreferClangAttr)
12400b57cec5SDimitry Andric     MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);
1241*a7dea167SDimitry Andric   if (MacroName.empty()) {
1242*a7dea167SDimitry Andric     if (!PreferClangAttr)
1243*a7dea167SDimitry Andric       MacroName = "[[fallthrough]]";
1244*a7dea167SDimitry Andric     else if (PP.getLangOpts().CPlusPlus)
1245*a7dea167SDimitry Andric       MacroName = "[[clang::fallthrough]]";
1246*a7dea167SDimitry Andric     else
1247*a7dea167SDimitry Andric       MacroName = "__attribute__((fallthrough))";
1248*a7dea167SDimitry Andric   }
12490b57cec5SDimitry Andric   return MacroName;
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
12530b57cec5SDimitry Andric                                             bool PerFunction) {
12540b57cec5SDimitry Andric   FallthroughMapper FM(S);
12550b57cec5SDimitry Andric   FM.TraverseStmt(AC.getBody());
12560b57cec5SDimitry Andric 
12570b57cec5SDimitry Andric   if (!FM.foundSwitchStatements())
12580b57cec5SDimitry Andric     return;
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric   if (PerFunction && FM.getFallthroughStmts().empty())
12610b57cec5SDimitry Andric     return;
12620b57cec5SDimitry Andric 
12630b57cec5SDimitry Andric   CFG *Cfg = AC.getCFG();
12640b57cec5SDimitry Andric 
12650b57cec5SDimitry Andric   if (!Cfg)
12660b57cec5SDimitry Andric     return;
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric   FM.fillReachableBlocks(Cfg);
12690b57cec5SDimitry Andric 
12700b57cec5SDimitry Andric   for (const CFGBlock *B : llvm::reverse(*Cfg)) {
12710b57cec5SDimitry Andric     const Stmt *Label = B->getLabel();
12720b57cec5SDimitry Andric 
12730b57cec5SDimitry Andric     if (!Label || !isa<SwitchCase>(Label))
12740b57cec5SDimitry Andric       continue;
12750b57cec5SDimitry Andric 
12760b57cec5SDimitry Andric     int AnnotatedCnt;
12770b57cec5SDimitry Andric 
12780b57cec5SDimitry Andric     bool IsTemplateInstantiation = false;
12790b57cec5SDimitry Andric     if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(AC.getDecl()))
12800b57cec5SDimitry Andric       IsTemplateInstantiation = Function->isTemplateInstantiation();
12810b57cec5SDimitry Andric     if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
12820b57cec5SDimitry Andric                                       IsTemplateInstantiation))
12830b57cec5SDimitry Andric       continue;
12840b57cec5SDimitry Andric 
12850b57cec5SDimitry Andric     S.Diag(Label->getBeginLoc(),
12860b57cec5SDimitry Andric            PerFunction ? diag::warn_unannotated_fallthrough_per_function
12870b57cec5SDimitry Andric                        : diag::warn_unannotated_fallthrough);
12880b57cec5SDimitry Andric 
12890b57cec5SDimitry Andric     if (!AnnotatedCnt) {
12900b57cec5SDimitry Andric       SourceLocation L = Label->getBeginLoc();
12910b57cec5SDimitry Andric       if (L.isMacroID())
12920b57cec5SDimitry Andric         continue;
1293*a7dea167SDimitry Andric 
12940b57cec5SDimitry Andric       const Stmt *Term = B->getTerminatorStmt();
12950b57cec5SDimitry Andric       // Skip empty cases.
12960b57cec5SDimitry Andric       while (B->empty() && !Term && B->succ_size() == 1) {
12970b57cec5SDimitry Andric         B = *B->succ_begin();
12980b57cec5SDimitry Andric         Term = B->getTerminatorStmt();
12990b57cec5SDimitry Andric       }
13000b57cec5SDimitry Andric       if (!(B->empty() && Term && isa<BreakStmt>(Term))) {
13010b57cec5SDimitry Andric         Preprocessor &PP = S.getPreprocessor();
13020b57cec5SDimitry Andric         StringRef AnnotationSpelling = getFallthroughAttrSpelling(PP, L);
13030b57cec5SDimitry Andric         SmallString<64> TextToInsert(AnnotationSpelling);
13040b57cec5SDimitry Andric         TextToInsert += "; ";
1305*a7dea167SDimitry Andric         S.Diag(L, diag::note_insert_fallthrough_fixit)
1306*a7dea167SDimitry Andric             << AnnotationSpelling
1307*a7dea167SDimitry Andric             << FixItHint::CreateInsertion(L, TextToInsert);
13080b57cec5SDimitry Andric       }
1309*a7dea167SDimitry Andric       S.Diag(L, diag::note_insert_break_fixit)
1310*a7dea167SDimitry Andric           << FixItHint::CreateInsertion(L, "break; ");
13110b57cec5SDimitry Andric     }
13120b57cec5SDimitry Andric   }
13130b57cec5SDimitry Andric 
13140b57cec5SDimitry Andric   for (const auto *F : FM.getFallthroughStmts())
13150b57cec5SDimitry Andric     S.Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);
13160b57cec5SDimitry Andric }
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
13190b57cec5SDimitry Andric                      const Stmt *S) {
13200b57cec5SDimitry Andric   assert(S);
13210b57cec5SDimitry Andric 
13220b57cec5SDimitry Andric   do {
13230b57cec5SDimitry Andric     switch (S->getStmtClass()) {
13240b57cec5SDimitry Andric     case Stmt::ForStmtClass:
13250b57cec5SDimitry Andric     case Stmt::WhileStmtClass:
13260b57cec5SDimitry Andric     case Stmt::CXXForRangeStmtClass:
13270b57cec5SDimitry Andric     case Stmt::ObjCForCollectionStmtClass:
13280b57cec5SDimitry Andric       return true;
13290b57cec5SDimitry Andric     case Stmt::DoStmtClass: {
13300b57cec5SDimitry Andric       Expr::EvalResult Result;
13310b57cec5SDimitry Andric       if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))
13320b57cec5SDimitry Andric         return true;
13330b57cec5SDimitry Andric       return Result.Val.getInt().getBoolValue();
13340b57cec5SDimitry Andric     }
13350b57cec5SDimitry Andric     default:
13360b57cec5SDimitry Andric       break;
13370b57cec5SDimitry Andric     }
13380b57cec5SDimitry Andric   } while ((S = PM.getParent(S)));
13390b57cec5SDimitry Andric 
13400b57cec5SDimitry Andric   return false;
13410b57cec5SDimitry Andric }
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric static void diagnoseRepeatedUseOfWeak(Sema &S,
13440b57cec5SDimitry Andric                                       const sema::FunctionScopeInfo *CurFn,
13450b57cec5SDimitry Andric                                       const Decl *D,
13460b57cec5SDimitry Andric                                       const ParentMap &PM) {
13470b57cec5SDimitry Andric   typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy;
13480b57cec5SDimitry Andric   typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap;
13490b57cec5SDimitry Andric   typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector;
13500b57cec5SDimitry Andric   typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
13510b57cec5SDimitry Andric   StmtUsesPair;
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric   ASTContext &Ctx = S.getASTContext();
13540b57cec5SDimitry Andric 
13550b57cec5SDimitry Andric   const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses();
13560b57cec5SDimitry Andric 
13570b57cec5SDimitry Andric   // Extract all weak objects that are referenced more than once.
13580b57cec5SDimitry Andric   SmallVector<StmtUsesPair, 8> UsesByStmt;
13590b57cec5SDimitry Andric   for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
13600b57cec5SDimitry Andric        I != E; ++I) {
13610b57cec5SDimitry Andric     const WeakUseVector &Uses = I->second;
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric     // Find the first read of the weak object.
13640b57cec5SDimitry Andric     WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
13650b57cec5SDimitry Andric     for ( ; UI != UE; ++UI) {
13660b57cec5SDimitry Andric       if (UI->isUnsafe())
13670b57cec5SDimitry Andric         break;
13680b57cec5SDimitry Andric     }
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric     // If there were only writes to this object, don't warn.
13710b57cec5SDimitry Andric     if (UI == UE)
13720b57cec5SDimitry Andric       continue;
13730b57cec5SDimitry Andric 
13740b57cec5SDimitry Andric     // If there was only one read, followed by any number of writes, and the
13750b57cec5SDimitry Andric     // read is not within a loop, don't warn. Additionally, don't warn in a
13760b57cec5SDimitry Andric     // loop if the base object is a local variable -- local variables are often
13770b57cec5SDimitry Andric     // changed in loops.
13780b57cec5SDimitry Andric     if (UI == Uses.begin()) {
13790b57cec5SDimitry Andric       WeakUseVector::const_iterator UI2 = UI;
13800b57cec5SDimitry Andric       for (++UI2; UI2 != UE; ++UI2)
13810b57cec5SDimitry Andric         if (UI2->isUnsafe())
13820b57cec5SDimitry Andric           break;
13830b57cec5SDimitry Andric 
13840b57cec5SDimitry Andric       if (UI2 == UE) {
13850b57cec5SDimitry Andric         if (!isInLoop(Ctx, PM, UI->getUseExpr()))
13860b57cec5SDimitry Andric           continue;
13870b57cec5SDimitry Andric 
13880b57cec5SDimitry Andric         const WeakObjectProfileTy &Profile = I->first;
13890b57cec5SDimitry Andric         if (!Profile.isExactProfile())
13900b57cec5SDimitry Andric           continue;
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric         const NamedDecl *Base = Profile.getBase();
13930b57cec5SDimitry Andric         if (!Base)
13940b57cec5SDimitry Andric           Base = Profile.getProperty();
13950b57cec5SDimitry Andric         assert(Base && "A profile always has a base or property.");
13960b57cec5SDimitry Andric 
13970b57cec5SDimitry Andric         if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
13980b57cec5SDimitry Andric           if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
13990b57cec5SDimitry Andric             continue;
14000b57cec5SDimitry Andric       }
14010b57cec5SDimitry Andric     }
14020b57cec5SDimitry Andric 
14030b57cec5SDimitry Andric     UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
14040b57cec5SDimitry Andric   }
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric   if (UsesByStmt.empty())
14070b57cec5SDimitry Andric     return;
14080b57cec5SDimitry Andric 
14090b57cec5SDimitry Andric   // Sort by first use so that we emit the warnings in a deterministic order.
14100b57cec5SDimitry Andric   SourceManager &SM = S.getSourceManager();
14110b57cec5SDimitry Andric   llvm::sort(UsesByStmt,
14120b57cec5SDimitry Andric              [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
14130b57cec5SDimitry Andric                return SM.isBeforeInTranslationUnit(LHS.first->getBeginLoc(),
14140b57cec5SDimitry Andric                                                    RHS.first->getBeginLoc());
14150b57cec5SDimitry Andric              });
14160b57cec5SDimitry Andric 
14170b57cec5SDimitry Andric   // Classify the current code body for better warning text.
14180b57cec5SDimitry Andric   // This enum should stay in sync with the cases in
14190b57cec5SDimitry Andric   // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
14200b57cec5SDimitry Andric   // FIXME: Should we use a common classification enum and the same set of
14210b57cec5SDimitry Andric   // possibilities all throughout Sema?
14220b57cec5SDimitry Andric   enum {
14230b57cec5SDimitry Andric     Function,
14240b57cec5SDimitry Andric     Method,
14250b57cec5SDimitry Andric     Block,
14260b57cec5SDimitry Andric     Lambda
14270b57cec5SDimitry Andric   } FunctionKind;
14280b57cec5SDimitry Andric 
14290b57cec5SDimitry Andric   if (isa<sema::BlockScopeInfo>(CurFn))
14300b57cec5SDimitry Andric     FunctionKind = Block;
14310b57cec5SDimitry Andric   else if (isa<sema::LambdaScopeInfo>(CurFn))
14320b57cec5SDimitry Andric     FunctionKind = Lambda;
14330b57cec5SDimitry Andric   else if (isa<ObjCMethodDecl>(D))
14340b57cec5SDimitry Andric     FunctionKind = Method;
14350b57cec5SDimitry Andric   else
14360b57cec5SDimitry Andric     FunctionKind = Function;
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric   // Iterate through the sorted problems and emit warnings for each.
14390b57cec5SDimitry Andric   for (const auto &P : UsesByStmt) {
14400b57cec5SDimitry Andric     const Stmt *FirstRead = P.first;
14410b57cec5SDimitry Andric     const WeakObjectProfileTy &Key = P.second->first;
14420b57cec5SDimitry Andric     const WeakUseVector &Uses = P.second->second;
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric     // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy
14450b57cec5SDimitry Andric     // may not contain enough information to determine that these are different
14460b57cec5SDimitry Andric     // properties. We can only be 100% sure of a repeated use in certain cases,
14470b57cec5SDimitry Andric     // and we adjust the diagnostic kind accordingly so that the less certain
14480b57cec5SDimitry Andric     // case can be turned off if it is too noisy.
14490b57cec5SDimitry Andric     unsigned DiagKind;
14500b57cec5SDimitry Andric     if (Key.isExactProfile())
14510b57cec5SDimitry Andric       DiagKind = diag::warn_arc_repeated_use_of_weak;
14520b57cec5SDimitry Andric     else
14530b57cec5SDimitry Andric       DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
14540b57cec5SDimitry Andric 
14550b57cec5SDimitry Andric     // Classify the weak object being accessed for better warning text.
14560b57cec5SDimitry Andric     // This enum should stay in sync with the cases in
14570b57cec5SDimitry Andric     // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
14580b57cec5SDimitry Andric     enum {
14590b57cec5SDimitry Andric       Variable,
14600b57cec5SDimitry Andric       Property,
14610b57cec5SDimitry Andric       ImplicitProperty,
14620b57cec5SDimitry Andric       Ivar
14630b57cec5SDimitry Andric     } ObjectKind;
14640b57cec5SDimitry Andric 
14650b57cec5SDimitry Andric     const NamedDecl *KeyProp = Key.getProperty();
14660b57cec5SDimitry Andric     if (isa<VarDecl>(KeyProp))
14670b57cec5SDimitry Andric       ObjectKind = Variable;
14680b57cec5SDimitry Andric     else if (isa<ObjCPropertyDecl>(KeyProp))
14690b57cec5SDimitry Andric       ObjectKind = Property;
14700b57cec5SDimitry Andric     else if (isa<ObjCMethodDecl>(KeyProp))
14710b57cec5SDimitry Andric       ObjectKind = ImplicitProperty;
14720b57cec5SDimitry Andric     else if (isa<ObjCIvarDecl>(KeyProp))
14730b57cec5SDimitry Andric       ObjectKind = Ivar;
14740b57cec5SDimitry Andric     else
14750b57cec5SDimitry Andric       llvm_unreachable("Unexpected weak object kind!");
14760b57cec5SDimitry Andric 
14770b57cec5SDimitry Andric     // Do not warn about IBOutlet weak property receivers being set to null
14780b57cec5SDimitry Andric     // since they are typically only used from the main thread.
14790b57cec5SDimitry Andric     if (const ObjCPropertyDecl *Prop = dyn_cast<ObjCPropertyDecl>(KeyProp))
14800b57cec5SDimitry Andric       if (Prop->hasAttr<IBOutletAttr>())
14810b57cec5SDimitry Andric         continue;
14820b57cec5SDimitry Andric 
14830b57cec5SDimitry Andric     // Show the first time the object was read.
14840b57cec5SDimitry Andric     S.Diag(FirstRead->getBeginLoc(), DiagKind)
14850b57cec5SDimitry Andric         << int(ObjectKind) << KeyProp << int(FunctionKind)
14860b57cec5SDimitry Andric         << FirstRead->getSourceRange();
14870b57cec5SDimitry Andric 
14880b57cec5SDimitry Andric     // Print all the other accesses as notes.
14890b57cec5SDimitry Andric     for (const auto &Use : Uses) {
14900b57cec5SDimitry Andric       if (Use.getUseExpr() == FirstRead)
14910b57cec5SDimitry Andric         continue;
14920b57cec5SDimitry Andric       S.Diag(Use.getUseExpr()->getBeginLoc(),
14930b57cec5SDimitry Andric              diag::note_arc_weak_also_accessed_here)
14940b57cec5SDimitry Andric           << Use.getUseExpr()->getSourceRange();
14950b57cec5SDimitry Andric     }
14960b57cec5SDimitry Andric   }
14970b57cec5SDimitry Andric }
14980b57cec5SDimitry Andric 
14990b57cec5SDimitry Andric namespace {
15000b57cec5SDimitry Andric class UninitValsDiagReporter : public UninitVariablesHandler {
15010b57cec5SDimitry Andric   Sema &S;
15020b57cec5SDimitry Andric   typedef SmallVector<UninitUse, 2> UsesVec;
15030b57cec5SDimitry Andric   typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
15040b57cec5SDimitry Andric   // Prefer using MapVector to DenseMap, so that iteration order will be
15050b57cec5SDimitry Andric   // the same as insertion order. This is needed to obtain a deterministic
15060b57cec5SDimitry Andric   // order of diagnostics when calling flushDiagnostics().
15070b57cec5SDimitry Andric   typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
15080b57cec5SDimitry Andric   UsesMap uses;
15090b57cec5SDimitry Andric 
15100b57cec5SDimitry Andric public:
15110b57cec5SDimitry Andric   UninitValsDiagReporter(Sema &S) : S(S) {}
15120b57cec5SDimitry Andric   ~UninitValsDiagReporter() override { flushDiagnostics(); }
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric   MappedType &getUses(const VarDecl *vd) {
15150b57cec5SDimitry Andric     MappedType &V = uses[vd];
15160b57cec5SDimitry Andric     if (!V.getPointer())
15170b57cec5SDimitry Andric       V.setPointer(new UsesVec());
15180b57cec5SDimitry Andric     return V;
15190b57cec5SDimitry Andric   }
15200b57cec5SDimitry Andric 
15210b57cec5SDimitry Andric   void handleUseOfUninitVariable(const VarDecl *vd,
15220b57cec5SDimitry Andric                                  const UninitUse &use) override {
15230b57cec5SDimitry Andric     getUses(vd).getPointer()->push_back(use);
15240b57cec5SDimitry Andric   }
15250b57cec5SDimitry Andric 
15260b57cec5SDimitry Andric   void handleSelfInit(const VarDecl *vd) override {
15270b57cec5SDimitry Andric     getUses(vd).setInt(true);
15280b57cec5SDimitry Andric   }
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric   void flushDiagnostics() {
15310b57cec5SDimitry Andric     for (const auto &P : uses) {
15320b57cec5SDimitry Andric       const VarDecl *vd = P.first;
15330b57cec5SDimitry Andric       const MappedType &V = P.second;
15340b57cec5SDimitry Andric 
15350b57cec5SDimitry Andric       UsesVec *vec = V.getPointer();
15360b57cec5SDimitry Andric       bool hasSelfInit = V.getInt();
15370b57cec5SDimitry Andric 
15380b57cec5SDimitry Andric       // Specially handle the case where we have uses of an uninitialized
15390b57cec5SDimitry Andric       // variable, but the root cause is an idiomatic self-init.  We want
15400b57cec5SDimitry Andric       // to report the diagnostic at the self-init since that is the root cause.
15410b57cec5SDimitry Andric       if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
15420b57cec5SDimitry Andric         DiagnoseUninitializedUse(S, vd,
15430b57cec5SDimitry Andric                                  UninitUse(vd->getInit()->IgnoreParenCasts(),
15440b57cec5SDimitry Andric                                            /* isAlwaysUninit */ true),
15450b57cec5SDimitry Andric                                  /* alwaysReportSelfInit */ true);
15460b57cec5SDimitry Andric       else {
15470b57cec5SDimitry Andric         // Sort the uses by their SourceLocations.  While not strictly
15480b57cec5SDimitry Andric         // guaranteed to produce them in line/column order, this will provide
15490b57cec5SDimitry Andric         // a stable ordering.
15500b57cec5SDimitry Andric         llvm::sort(vec->begin(), vec->end(),
15510b57cec5SDimitry Andric                    [](const UninitUse &a, const UninitUse &b) {
15520b57cec5SDimitry Andric           // Prefer a more confident report over a less confident one.
15530b57cec5SDimitry Andric           if (a.getKind() != b.getKind())
15540b57cec5SDimitry Andric             return a.getKind() > b.getKind();
15550b57cec5SDimitry Andric           return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();
15560b57cec5SDimitry Andric         });
15570b57cec5SDimitry Andric 
15580b57cec5SDimitry Andric         for (const auto &U : *vec) {
15590b57cec5SDimitry Andric           // If we have self-init, downgrade all uses to 'may be uninitialized'.
15600b57cec5SDimitry Andric           UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric           if (DiagnoseUninitializedUse(S, vd, Use))
15630b57cec5SDimitry Andric             // Skip further diagnostics for this variable. We try to warn only
15640b57cec5SDimitry Andric             // on the first point at which a variable is used uninitialized.
15650b57cec5SDimitry Andric             break;
15660b57cec5SDimitry Andric         }
15670b57cec5SDimitry Andric       }
15680b57cec5SDimitry Andric 
15690b57cec5SDimitry Andric       // Release the uses vector.
15700b57cec5SDimitry Andric       delete vec;
15710b57cec5SDimitry Andric     }
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric     uses.clear();
15740b57cec5SDimitry Andric   }
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric private:
15770b57cec5SDimitry Andric   static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
15780b57cec5SDimitry Andric     return std::any_of(vec->begin(), vec->end(), [](const UninitUse &U) {
15790b57cec5SDimitry Andric       return U.getKind() == UninitUse::Always ||
15800b57cec5SDimitry Andric              U.getKind() == UninitUse::AfterCall ||
15810b57cec5SDimitry Andric              U.getKind() == UninitUse::AfterDecl;
15820b57cec5SDimitry Andric     });
15830b57cec5SDimitry Andric   }
15840b57cec5SDimitry Andric };
15850b57cec5SDimitry Andric } // anonymous namespace
15860b57cec5SDimitry Andric 
15870b57cec5SDimitry Andric namespace clang {
15880b57cec5SDimitry Andric namespace {
15890b57cec5SDimitry Andric typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
15900b57cec5SDimitry Andric typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
15910b57cec5SDimitry Andric typedef std::list<DelayedDiag> DiagList;
15920b57cec5SDimitry Andric 
15930b57cec5SDimitry Andric struct SortDiagBySourceLocation {
15940b57cec5SDimitry Andric   SourceManager &SM;
15950b57cec5SDimitry Andric   SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}
15960b57cec5SDimitry Andric 
15970b57cec5SDimitry Andric   bool operator()(const DelayedDiag &left, const DelayedDiag &right) {
15980b57cec5SDimitry Andric     // Although this call will be slow, this is only called when outputting
15990b57cec5SDimitry Andric     // multiple warnings.
16000b57cec5SDimitry Andric     return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
16010b57cec5SDimitry Andric   }
16020b57cec5SDimitry Andric };
16030b57cec5SDimitry Andric } // anonymous namespace
16040b57cec5SDimitry Andric } // namespace clang
16050b57cec5SDimitry Andric 
16060b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
16070b57cec5SDimitry Andric // -Wthread-safety
16080b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
16090b57cec5SDimitry Andric namespace clang {
16100b57cec5SDimitry Andric namespace threadSafety {
16110b57cec5SDimitry Andric namespace {
16120b57cec5SDimitry Andric class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
16130b57cec5SDimitry Andric   Sema &S;
16140b57cec5SDimitry Andric   DiagList Warnings;
16150b57cec5SDimitry Andric   SourceLocation FunLocation, FunEndLocation;
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric   const FunctionDecl *CurrentFunction;
16180b57cec5SDimitry Andric   bool Verbose;
16190b57cec5SDimitry Andric 
16200b57cec5SDimitry Andric   OptionalNotes getNotes() const {
16210b57cec5SDimitry Andric     if (Verbose && CurrentFunction) {
16220b57cec5SDimitry Andric       PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
16230b57cec5SDimitry Andric                                 S.PDiag(diag::note_thread_warning_in_fun)
16240b57cec5SDimitry Andric                                     << CurrentFunction);
16250b57cec5SDimitry Andric       return OptionalNotes(1, FNote);
16260b57cec5SDimitry Andric     }
16270b57cec5SDimitry Andric     return OptionalNotes();
16280b57cec5SDimitry Andric   }
16290b57cec5SDimitry Andric 
16300b57cec5SDimitry Andric   OptionalNotes getNotes(const PartialDiagnosticAt &Note) const {
16310b57cec5SDimitry Andric     OptionalNotes ONS(1, Note);
16320b57cec5SDimitry Andric     if (Verbose && CurrentFunction) {
16330b57cec5SDimitry Andric       PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
16340b57cec5SDimitry Andric                                 S.PDiag(diag::note_thread_warning_in_fun)
16350b57cec5SDimitry Andric                                     << CurrentFunction);
16360b57cec5SDimitry Andric       ONS.push_back(std::move(FNote));
16370b57cec5SDimitry Andric     }
16380b57cec5SDimitry Andric     return ONS;
16390b57cec5SDimitry Andric   }
16400b57cec5SDimitry Andric 
16410b57cec5SDimitry Andric   OptionalNotes getNotes(const PartialDiagnosticAt &Note1,
16420b57cec5SDimitry Andric                          const PartialDiagnosticAt &Note2) const {
16430b57cec5SDimitry Andric     OptionalNotes ONS;
16440b57cec5SDimitry Andric     ONS.push_back(Note1);
16450b57cec5SDimitry Andric     ONS.push_back(Note2);
16460b57cec5SDimitry Andric     if (Verbose && CurrentFunction) {
16470b57cec5SDimitry Andric       PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
16480b57cec5SDimitry Andric                                 S.PDiag(diag::note_thread_warning_in_fun)
16490b57cec5SDimitry Andric                                     << CurrentFunction);
16500b57cec5SDimitry Andric       ONS.push_back(std::move(FNote));
16510b57cec5SDimitry Andric     }
16520b57cec5SDimitry Andric     return ONS;
16530b57cec5SDimitry Andric   }
16540b57cec5SDimitry Andric 
16550b57cec5SDimitry Andric   OptionalNotes makeLockedHereNote(SourceLocation LocLocked, StringRef Kind) {
16560b57cec5SDimitry Andric     return LocLocked.isValid()
16570b57cec5SDimitry Andric                ? getNotes(PartialDiagnosticAt(
16580b57cec5SDimitry Andric                      LocLocked, S.PDiag(diag::note_locked_here) << Kind))
16590b57cec5SDimitry Andric                : getNotes();
16600b57cec5SDimitry Andric   }
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric  public:
16630b57cec5SDimitry Andric   ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL)
16640b57cec5SDimitry Andric     : S(S), FunLocation(FL), FunEndLocation(FEL),
16650b57cec5SDimitry Andric       CurrentFunction(nullptr), Verbose(false) {}
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric   void setVerbose(bool b) { Verbose = b; }
16680b57cec5SDimitry Andric 
16690b57cec5SDimitry Andric   /// Emit all buffered diagnostics in order of sourcelocation.
16700b57cec5SDimitry Andric   /// We need to output diagnostics produced while iterating through
16710b57cec5SDimitry Andric   /// the lockset in deterministic order, so this function orders diagnostics
16720b57cec5SDimitry Andric   /// and outputs them.
16730b57cec5SDimitry Andric   void emitDiagnostics() {
16740b57cec5SDimitry Andric     Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
16750b57cec5SDimitry Andric     for (const auto &Diag : Warnings) {
16760b57cec5SDimitry Andric       S.Diag(Diag.first.first, Diag.first.second);
16770b57cec5SDimitry Andric       for (const auto &Note : Diag.second)
16780b57cec5SDimitry Andric         S.Diag(Note.first, Note.second);
16790b57cec5SDimitry Andric     }
16800b57cec5SDimitry Andric   }
16810b57cec5SDimitry Andric 
16820b57cec5SDimitry Andric   void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) override {
16830b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock)
16840b57cec5SDimitry Andric                                          << Loc);
16850b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), getNotes());
16860b57cec5SDimitry Andric   }
16870b57cec5SDimitry Andric 
16880b57cec5SDimitry Andric   void handleUnmatchedUnlock(StringRef Kind, Name LockName,
16890b57cec5SDimitry Andric                              SourceLocation Loc) override {
16900b57cec5SDimitry Andric     if (Loc.isInvalid())
16910b57cec5SDimitry Andric       Loc = FunLocation;
16920b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_but_no_lock)
16930b57cec5SDimitry Andric                                          << Kind << LockName);
16940b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), getNotes());
16950b57cec5SDimitry Andric   }
16960b57cec5SDimitry Andric 
16970b57cec5SDimitry Andric   void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
16980b57cec5SDimitry Andric                                  LockKind Expected, LockKind Received,
16990b57cec5SDimitry Andric                                  SourceLocation LocLocked,
17000b57cec5SDimitry Andric                                  SourceLocation LocUnlock) override {
17010b57cec5SDimitry Andric     if (LocUnlock.isInvalid())
17020b57cec5SDimitry Andric       LocUnlock = FunLocation;
17030b57cec5SDimitry Andric     PartialDiagnosticAt Warning(
17040b57cec5SDimitry Andric         LocUnlock, S.PDiag(diag::warn_unlock_kind_mismatch)
17050b57cec5SDimitry Andric                        << Kind << LockName << Received << Expected);
17060b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning),
17070b57cec5SDimitry Andric                           makeLockedHereNote(LocLocked, Kind));
17080b57cec5SDimitry Andric   }
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric   void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation LocLocked,
17110b57cec5SDimitry Andric                         SourceLocation LocDoubleLock) override {
17120b57cec5SDimitry Andric     if (LocDoubleLock.isInvalid())
17130b57cec5SDimitry Andric       LocDoubleLock = FunLocation;
17140b57cec5SDimitry Andric     PartialDiagnosticAt Warning(LocDoubleLock, S.PDiag(diag::warn_double_lock)
17150b57cec5SDimitry Andric                                                    << Kind << LockName);
17160b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning),
17170b57cec5SDimitry Andric                           makeLockedHereNote(LocLocked, Kind));
17180b57cec5SDimitry Andric   }
17190b57cec5SDimitry Andric 
17200b57cec5SDimitry Andric   void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
17210b57cec5SDimitry Andric                                  SourceLocation LocLocked,
17220b57cec5SDimitry Andric                                  SourceLocation LocEndOfScope,
17230b57cec5SDimitry Andric                                  LockErrorKind LEK) override {
17240b57cec5SDimitry Andric     unsigned DiagID = 0;
17250b57cec5SDimitry Andric     switch (LEK) {
17260b57cec5SDimitry Andric       case LEK_LockedSomePredecessors:
17270b57cec5SDimitry Andric         DiagID = diag::warn_lock_some_predecessors;
17280b57cec5SDimitry Andric         break;
17290b57cec5SDimitry Andric       case LEK_LockedSomeLoopIterations:
17300b57cec5SDimitry Andric         DiagID = diag::warn_expecting_lock_held_on_loop;
17310b57cec5SDimitry Andric         break;
17320b57cec5SDimitry Andric       case LEK_LockedAtEndOfFunction:
17330b57cec5SDimitry Andric         DiagID = diag::warn_no_unlock;
17340b57cec5SDimitry Andric         break;
17350b57cec5SDimitry Andric       case LEK_NotLockedAtEndOfFunction:
17360b57cec5SDimitry Andric         DiagID = diag::warn_expecting_locked;
17370b57cec5SDimitry Andric         break;
17380b57cec5SDimitry Andric     }
17390b57cec5SDimitry Andric     if (LocEndOfScope.isInvalid())
17400b57cec5SDimitry Andric       LocEndOfScope = FunEndLocation;
17410b57cec5SDimitry Andric 
17420b57cec5SDimitry Andric     PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << Kind
17430b57cec5SDimitry Andric                                                                << LockName);
17440b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning),
17450b57cec5SDimitry Andric                           makeLockedHereNote(LocLocked, Kind));
17460b57cec5SDimitry Andric   }
17470b57cec5SDimitry Andric 
17480b57cec5SDimitry Andric   void handleExclusiveAndShared(StringRef Kind, Name LockName,
17490b57cec5SDimitry Andric                                 SourceLocation Loc1,
17500b57cec5SDimitry Andric                                 SourceLocation Loc2) override {
17510b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc1,
17520b57cec5SDimitry Andric                                 S.PDiag(diag::warn_lock_exclusive_and_shared)
17530b57cec5SDimitry Andric                                     << Kind << LockName);
17540b57cec5SDimitry Andric     PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared)
17550b57cec5SDimitry Andric                                        << Kind << LockName);
17560b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), getNotes(Note));
17570b57cec5SDimitry Andric   }
17580b57cec5SDimitry Andric 
17590b57cec5SDimitry Andric   void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
17600b57cec5SDimitry Andric                          ProtectedOperationKind POK, AccessKind AK,
17610b57cec5SDimitry Andric                          SourceLocation Loc) override {
17620b57cec5SDimitry Andric     assert((POK == POK_VarAccess || POK == POK_VarDereference) &&
17630b57cec5SDimitry Andric            "Only works for variables");
17640b57cec5SDimitry Andric     unsigned DiagID = POK == POK_VarAccess?
17650b57cec5SDimitry Andric                         diag::warn_variable_requires_any_lock:
17660b57cec5SDimitry Andric                         diag::warn_var_deref_requires_any_lock;
17670b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
17680b57cec5SDimitry Andric       << D << getLockKindFromAccessKind(AK));
17690b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), getNotes());
17700b57cec5SDimitry Andric   }
17710b57cec5SDimitry Andric 
17720b57cec5SDimitry Andric   void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
17730b57cec5SDimitry Andric                           ProtectedOperationKind POK, Name LockName,
17740b57cec5SDimitry Andric                           LockKind LK, SourceLocation Loc,
17750b57cec5SDimitry Andric                           Name *PossibleMatch) override {
17760b57cec5SDimitry Andric     unsigned DiagID = 0;
17770b57cec5SDimitry Andric     if (PossibleMatch) {
17780b57cec5SDimitry Andric       switch (POK) {
17790b57cec5SDimitry Andric         case POK_VarAccess:
17800b57cec5SDimitry Andric           DiagID = diag::warn_variable_requires_lock_precise;
17810b57cec5SDimitry Andric           break;
17820b57cec5SDimitry Andric         case POK_VarDereference:
17830b57cec5SDimitry Andric           DiagID = diag::warn_var_deref_requires_lock_precise;
17840b57cec5SDimitry Andric           break;
17850b57cec5SDimitry Andric         case POK_FunctionCall:
17860b57cec5SDimitry Andric           DiagID = diag::warn_fun_requires_lock_precise;
17870b57cec5SDimitry Andric           break;
17880b57cec5SDimitry Andric         case POK_PassByRef:
17890b57cec5SDimitry Andric           DiagID = diag::warn_guarded_pass_by_reference;
17900b57cec5SDimitry Andric           break;
17910b57cec5SDimitry Andric         case POK_PtPassByRef:
17920b57cec5SDimitry Andric           DiagID = diag::warn_pt_guarded_pass_by_reference;
17930b57cec5SDimitry Andric           break;
17940b57cec5SDimitry Andric       }
17950b57cec5SDimitry Andric       PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
17960b57cec5SDimitry Andric                                                        << D
17970b57cec5SDimitry Andric                                                        << LockName << LK);
17980b57cec5SDimitry Andric       PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
17990b57cec5SDimitry Andric                                         << *PossibleMatch);
18000b57cec5SDimitry Andric       if (Verbose && POK == POK_VarAccess) {
18010b57cec5SDimitry Andric         PartialDiagnosticAt VNote(D->getLocation(),
18020b57cec5SDimitry Andric                                  S.PDiag(diag::note_guarded_by_declared_here)
18030b57cec5SDimitry Andric                                      << D->getNameAsString());
18040b57cec5SDimitry Andric         Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote));
18050b57cec5SDimitry Andric       } else
18060b57cec5SDimitry Andric         Warnings.emplace_back(std::move(Warning), getNotes(Note));
18070b57cec5SDimitry Andric     } else {
18080b57cec5SDimitry Andric       switch (POK) {
18090b57cec5SDimitry Andric         case POK_VarAccess:
18100b57cec5SDimitry Andric           DiagID = diag::warn_variable_requires_lock;
18110b57cec5SDimitry Andric           break;
18120b57cec5SDimitry Andric         case POK_VarDereference:
18130b57cec5SDimitry Andric           DiagID = diag::warn_var_deref_requires_lock;
18140b57cec5SDimitry Andric           break;
18150b57cec5SDimitry Andric         case POK_FunctionCall:
18160b57cec5SDimitry Andric           DiagID = diag::warn_fun_requires_lock;
18170b57cec5SDimitry Andric           break;
18180b57cec5SDimitry Andric         case POK_PassByRef:
18190b57cec5SDimitry Andric           DiagID = diag::warn_guarded_pass_by_reference;
18200b57cec5SDimitry Andric           break;
18210b57cec5SDimitry Andric         case POK_PtPassByRef:
18220b57cec5SDimitry Andric           DiagID = diag::warn_pt_guarded_pass_by_reference;
18230b57cec5SDimitry Andric           break;
18240b57cec5SDimitry Andric       }
18250b57cec5SDimitry Andric       PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
18260b57cec5SDimitry Andric                                                        << D
18270b57cec5SDimitry Andric                                                        << LockName << LK);
18280b57cec5SDimitry Andric       if (Verbose && POK == POK_VarAccess) {
18290b57cec5SDimitry Andric         PartialDiagnosticAt Note(D->getLocation(),
18300b57cec5SDimitry Andric                                  S.PDiag(diag::note_guarded_by_declared_here));
18310b57cec5SDimitry Andric         Warnings.emplace_back(std::move(Warning), getNotes(Note));
18320b57cec5SDimitry Andric       } else
18330b57cec5SDimitry Andric         Warnings.emplace_back(std::move(Warning), getNotes());
18340b57cec5SDimitry Andric     }
18350b57cec5SDimitry Andric   }
18360b57cec5SDimitry Andric 
18370b57cec5SDimitry Andric   void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
18380b57cec5SDimitry Andric                              SourceLocation Loc) override {
18390b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc,
18400b57cec5SDimitry Andric         S.PDiag(diag::warn_acquire_requires_negative_cap)
18410b57cec5SDimitry Andric         << Kind << LockName << Neg);
18420b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), getNotes());
18430b57cec5SDimitry Andric   }
18440b57cec5SDimitry Andric 
18450b57cec5SDimitry Andric   void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
18460b57cec5SDimitry Andric                              SourceLocation Loc) override {
18470b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
18480b57cec5SDimitry Andric                                          << Kind << FunName << LockName);
18490b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), getNotes());
18500b57cec5SDimitry Andric   }
18510b57cec5SDimitry Andric 
18520b57cec5SDimitry Andric   void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
18530b57cec5SDimitry Andric                                 SourceLocation Loc) override {
18540b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc,
18550b57cec5SDimitry Andric       S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
18560b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), getNotes());
18570b57cec5SDimitry Andric   }
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric   void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override {
18600b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc,
18610b57cec5SDimitry Andric       S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
18620b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), getNotes());
18630b57cec5SDimitry Andric   }
18640b57cec5SDimitry Andric 
18650b57cec5SDimitry Andric   void enterFunction(const FunctionDecl* FD) override {
18660b57cec5SDimitry Andric     CurrentFunction = FD;
18670b57cec5SDimitry Andric   }
18680b57cec5SDimitry Andric 
18690b57cec5SDimitry Andric   void leaveFunction(const FunctionDecl* FD) override {
18700b57cec5SDimitry Andric     CurrentFunction = nullptr;
18710b57cec5SDimitry Andric   }
18720b57cec5SDimitry Andric };
18730b57cec5SDimitry Andric } // anonymous namespace
18740b57cec5SDimitry Andric } // namespace threadSafety
18750b57cec5SDimitry Andric } // namespace clang
18760b57cec5SDimitry Andric 
18770b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
18780b57cec5SDimitry Andric // -Wconsumed
18790b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
18800b57cec5SDimitry Andric 
18810b57cec5SDimitry Andric namespace clang {
18820b57cec5SDimitry Andric namespace consumed {
18830b57cec5SDimitry Andric namespace {
18840b57cec5SDimitry Andric class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase {
18850b57cec5SDimitry Andric 
18860b57cec5SDimitry Andric   Sema &S;
18870b57cec5SDimitry Andric   DiagList Warnings;
18880b57cec5SDimitry Andric 
18890b57cec5SDimitry Andric public:
18900b57cec5SDimitry Andric 
18910b57cec5SDimitry Andric   ConsumedWarningsHandler(Sema &S) : S(S) {}
18920b57cec5SDimitry Andric 
18930b57cec5SDimitry Andric   void emitDiagnostics() override {
18940b57cec5SDimitry Andric     Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
18950b57cec5SDimitry Andric     for (const auto &Diag : Warnings) {
18960b57cec5SDimitry Andric       S.Diag(Diag.first.first, Diag.first.second);
18970b57cec5SDimitry Andric       for (const auto &Note : Diag.second)
18980b57cec5SDimitry Andric         S.Diag(Note.first, Note.second);
18990b57cec5SDimitry Andric     }
19000b57cec5SDimitry Andric   }
19010b57cec5SDimitry Andric 
19020b57cec5SDimitry Andric   void warnLoopStateMismatch(SourceLocation Loc,
19030b57cec5SDimitry Andric                              StringRef VariableName) override {
19040b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) <<
19050b57cec5SDimitry Andric       VariableName);
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), OptionalNotes());
19080b57cec5SDimitry Andric   }
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric   void warnParamReturnTypestateMismatch(SourceLocation Loc,
19110b57cec5SDimitry Andric                                         StringRef VariableName,
19120b57cec5SDimitry Andric                                         StringRef ExpectedState,
19130b57cec5SDimitry Andric                                         StringRef ObservedState) override {
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(
19160b57cec5SDimitry Andric       diag::warn_param_return_typestate_mismatch) << VariableName <<
19170b57cec5SDimitry Andric         ExpectedState << ObservedState);
19180b57cec5SDimitry Andric 
19190b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), OptionalNotes());
19200b57cec5SDimitry Andric   }
19210b57cec5SDimitry Andric 
19220b57cec5SDimitry Andric   void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
19230b57cec5SDimitry Andric                                   StringRef ObservedState) override {
19240b57cec5SDimitry Andric 
19250b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(
19260b57cec5SDimitry Andric       diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
19270b57cec5SDimitry Andric 
19280b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), OptionalNotes());
19290b57cec5SDimitry Andric   }
19300b57cec5SDimitry Andric 
19310b57cec5SDimitry Andric   void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
19320b57cec5SDimitry Andric                                               StringRef TypeName) override {
19330b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(
19340b57cec5SDimitry Andric       diag::warn_return_typestate_for_unconsumable_type) << TypeName);
19350b57cec5SDimitry Andric 
19360b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), OptionalNotes());
19370b57cec5SDimitry Andric   }
19380b57cec5SDimitry Andric 
19390b57cec5SDimitry Andric   void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
19400b57cec5SDimitry Andric                                    StringRef ObservedState) override {
19410b57cec5SDimitry Andric 
19420b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(
19430b57cec5SDimitry Andric       diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
19440b57cec5SDimitry Andric 
19450b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), OptionalNotes());
19460b57cec5SDimitry Andric   }
19470b57cec5SDimitry Andric 
19480b57cec5SDimitry Andric   void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
19490b57cec5SDimitry Andric                                    SourceLocation Loc) override {
19500b57cec5SDimitry Andric 
19510b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(
19520b57cec5SDimitry Andric       diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
19530b57cec5SDimitry Andric 
19540b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), OptionalNotes());
19550b57cec5SDimitry Andric   }
19560b57cec5SDimitry Andric 
19570b57cec5SDimitry Andric   void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
19580b57cec5SDimitry Andric                              StringRef State, SourceLocation Loc) override {
19590b57cec5SDimitry Andric 
19600b57cec5SDimitry Andric     PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
19610b57cec5SDimitry Andric                                 MethodName << VariableName << State);
19620b57cec5SDimitry Andric 
19630b57cec5SDimitry Andric     Warnings.emplace_back(std::move(Warning), OptionalNotes());
19640b57cec5SDimitry Andric   }
19650b57cec5SDimitry Andric };
19660b57cec5SDimitry Andric } // anonymous namespace
19670b57cec5SDimitry Andric } // namespace consumed
19680b57cec5SDimitry Andric } // namespace clang
19690b57cec5SDimitry Andric 
19700b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
19710b57cec5SDimitry Andric // AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
19720b57cec5SDimitry Andric //  warnings on a function, method, or block.
19730b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
19740b57cec5SDimitry Andric 
19750b57cec5SDimitry Andric clang::sema::AnalysisBasedWarnings::Policy::Policy() {
19760b57cec5SDimitry Andric   enableCheckFallThrough = 1;
19770b57cec5SDimitry Andric   enableCheckUnreachable = 0;
19780b57cec5SDimitry Andric   enableThreadSafetyAnalysis = 0;
19790b57cec5SDimitry Andric   enableConsumedAnalysis = 0;
19800b57cec5SDimitry Andric }
19810b57cec5SDimitry Andric 
19820b57cec5SDimitry Andric static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag) {
19830b57cec5SDimitry Andric   return (unsigned)!D.isIgnored(diag, SourceLocation());
19840b57cec5SDimitry Andric }
19850b57cec5SDimitry Andric 
19860b57cec5SDimitry Andric clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
19870b57cec5SDimitry Andric   : S(s),
19880b57cec5SDimitry Andric     NumFunctionsAnalyzed(0),
19890b57cec5SDimitry Andric     NumFunctionsWithBadCFGs(0),
19900b57cec5SDimitry Andric     NumCFGBlocks(0),
19910b57cec5SDimitry Andric     MaxCFGBlocksPerFunction(0),
19920b57cec5SDimitry Andric     NumUninitAnalysisFunctions(0),
19930b57cec5SDimitry Andric     NumUninitAnalysisVariables(0),
19940b57cec5SDimitry Andric     MaxUninitAnalysisVariablesPerFunction(0),
19950b57cec5SDimitry Andric     NumUninitAnalysisBlockVisits(0),
19960b57cec5SDimitry Andric     MaxUninitAnalysisBlockVisitsPerFunction(0) {
19970b57cec5SDimitry Andric 
19980b57cec5SDimitry Andric   using namespace diag;
19990b57cec5SDimitry Andric   DiagnosticsEngine &D = S.getDiagnostics();
20000b57cec5SDimitry Andric 
20010b57cec5SDimitry Andric   DefaultPolicy.enableCheckUnreachable =
20020b57cec5SDimitry Andric     isEnabled(D, warn_unreachable) ||
20030b57cec5SDimitry Andric     isEnabled(D, warn_unreachable_break) ||
20040b57cec5SDimitry Andric     isEnabled(D, warn_unreachable_return) ||
20050b57cec5SDimitry Andric     isEnabled(D, warn_unreachable_loop_increment);
20060b57cec5SDimitry Andric 
20070b57cec5SDimitry Andric   DefaultPolicy.enableThreadSafetyAnalysis =
20080b57cec5SDimitry Andric     isEnabled(D, warn_double_lock);
20090b57cec5SDimitry Andric 
20100b57cec5SDimitry Andric   DefaultPolicy.enableConsumedAnalysis =
20110b57cec5SDimitry Andric     isEnabled(D, warn_use_in_invalid_state);
20120b57cec5SDimitry Andric }
20130b57cec5SDimitry Andric 
20140b57cec5SDimitry Andric static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
20150b57cec5SDimitry Andric   for (const auto &D : fscope->PossiblyUnreachableDiags)
20160b57cec5SDimitry Andric     S.Diag(D.Loc, D.PD);
20170b57cec5SDimitry Andric }
20180b57cec5SDimitry Andric 
20190b57cec5SDimitry Andric void clang::sema::
20200b57cec5SDimitry Andric AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
20210b57cec5SDimitry Andric                                      sema::FunctionScopeInfo *fscope,
20220b57cec5SDimitry Andric                                      const Decl *D, QualType BlockType) {
20230b57cec5SDimitry Andric 
20240b57cec5SDimitry Andric   // We avoid doing analysis-based warnings when there are errors for
20250b57cec5SDimitry Andric   // two reasons:
20260b57cec5SDimitry Andric   // (1) The CFGs often can't be constructed (if the body is invalid), so
20270b57cec5SDimitry Andric   //     don't bother trying.
20280b57cec5SDimitry Andric   // (2) The code already has problems; running the analysis just takes more
20290b57cec5SDimitry Andric   //     time.
20300b57cec5SDimitry Andric   DiagnosticsEngine &Diags = S.getDiagnostics();
20310b57cec5SDimitry Andric 
20320b57cec5SDimitry Andric   // Do not do any analysis if we are going to just ignore them.
20330b57cec5SDimitry Andric   if (Diags.getIgnoreAllWarnings() ||
20340b57cec5SDimitry Andric       (Diags.getSuppressSystemWarnings() &&
20350b57cec5SDimitry Andric        S.SourceMgr.isInSystemHeader(D->getLocation())))
20360b57cec5SDimitry Andric     return;
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric   // For code in dependent contexts, we'll do this at instantiation time.
20390b57cec5SDimitry Andric   if (cast<DeclContext>(D)->isDependentContext())
20400b57cec5SDimitry Andric     return;
20410b57cec5SDimitry Andric 
20420b57cec5SDimitry Andric   if (Diags.hasUncompilableErrorOccurred()) {
20430b57cec5SDimitry Andric     // Flush out any possibly unreachable diagnostics.
20440b57cec5SDimitry Andric     flushDiagnostics(S, fscope);
20450b57cec5SDimitry Andric     return;
20460b57cec5SDimitry Andric   }
20470b57cec5SDimitry Andric 
20480b57cec5SDimitry Andric   const Stmt *Body = D->getBody();
20490b57cec5SDimitry Andric   assert(Body);
20500b57cec5SDimitry Andric 
20510b57cec5SDimitry Andric   // Construct the analysis context with the specified CFG build options.
20520b57cec5SDimitry Andric   AnalysisDeclContext AC(/* AnalysisDeclContextManager */ nullptr, D);
20530b57cec5SDimitry Andric 
20540b57cec5SDimitry Andric   // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
20550b57cec5SDimitry Andric   // explosion for destructors that can result and the compile time hit.
20560b57cec5SDimitry Andric   AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true;
20570b57cec5SDimitry Andric   AC.getCFGBuildOptions().AddEHEdges = false;
20580b57cec5SDimitry Andric   AC.getCFGBuildOptions().AddInitializers = true;
20590b57cec5SDimitry Andric   AC.getCFGBuildOptions().AddImplicitDtors = true;
20600b57cec5SDimitry Andric   AC.getCFGBuildOptions().AddTemporaryDtors = true;
20610b57cec5SDimitry Andric   AC.getCFGBuildOptions().AddCXXNewAllocator = false;
20620b57cec5SDimitry Andric   AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true;
20630b57cec5SDimitry Andric 
20640b57cec5SDimitry Andric   // Force that certain expressions appear as CFGElements in the CFG.  This
20650b57cec5SDimitry Andric   // is used to speed up various analyses.
20660b57cec5SDimitry Andric   // FIXME: This isn't the right factoring.  This is here for initial
20670b57cec5SDimitry Andric   // prototyping, but we need a way for analyses to say what expressions they
20680b57cec5SDimitry Andric   // expect to always be CFGElements and then fill in the BuildOptions
20690b57cec5SDimitry Andric   // appropriately.  This is essentially a layering violation.
20700b57cec5SDimitry Andric   if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
20710b57cec5SDimitry Andric       P.enableConsumedAnalysis) {
20720b57cec5SDimitry Andric     // Unreachable code analysis and thread safety require a linearized CFG.
20730b57cec5SDimitry Andric     AC.getCFGBuildOptions().setAllAlwaysAdd();
20740b57cec5SDimitry Andric   }
20750b57cec5SDimitry Andric   else {
20760b57cec5SDimitry Andric     AC.getCFGBuildOptions()
20770b57cec5SDimitry Andric       .setAlwaysAdd(Stmt::BinaryOperatorClass)
20780b57cec5SDimitry Andric       .setAlwaysAdd(Stmt::CompoundAssignOperatorClass)
20790b57cec5SDimitry Andric       .setAlwaysAdd(Stmt::BlockExprClass)
20800b57cec5SDimitry Andric       .setAlwaysAdd(Stmt::CStyleCastExprClass)
20810b57cec5SDimitry Andric       .setAlwaysAdd(Stmt::DeclRefExprClass)
20820b57cec5SDimitry Andric       .setAlwaysAdd(Stmt::ImplicitCastExprClass)
20830b57cec5SDimitry Andric       .setAlwaysAdd(Stmt::UnaryOperatorClass)
20840b57cec5SDimitry Andric       .setAlwaysAdd(Stmt::AttributedStmtClass);
20850b57cec5SDimitry Andric   }
20860b57cec5SDimitry Andric 
2087*a7dea167SDimitry Andric   // Install the logical handler.
20880b57cec5SDimitry Andric   llvm::Optional<LogicalErrorHandler> LEH;
2089*a7dea167SDimitry Andric   if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
20900b57cec5SDimitry Andric     LEH.emplace(S);
20910b57cec5SDimitry Andric     AC.getCFGBuildOptions().Observer = &*LEH;
20920b57cec5SDimitry Andric   }
20930b57cec5SDimitry Andric 
20940b57cec5SDimitry Andric   // Emit delayed diagnostics.
20950b57cec5SDimitry Andric   if (!fscope->PossiblyUnreachableDiags.empty()) {
20960b57cec5SDimitry Andric     bool analyzed = false;
20970b57cec5SDimitry Andric 
20980b57cec5SDimitry Andric     // Register the expressions with the CFGBuilder.
20990b57cec5SDimitry Andric     for (const auto &D : fscope->PossiblyUnreachableDiags) {
21000b57cec5SDimitry Andric       for (const Stmt *S : D.Stmts)
21010b57cec5SDimitry Andric         AC.registerForcedBlockExpression(S);
21020b57cec5SDimitry Andric     }
21030b57cec5SDimitry Andric 
21040b57cec5SDimitry Andric     if (AC.getCFG()) {
21050b57cec5SDimitry Andric       analyzed = true;
21060b57cec5SDimitry Andric       for (const auto &D : fscope->PossiblyUnreachableDiags) {
21070b57cec5SDimitry Andric         bool AllReachable = true;
21080b57cec5SDimitry Andric         for (const Stmt *S : D.Stmts) {
21090b57cec5SDimitry Andric           const CFGBlock *block = AC.getBlockForRegisteredExpression(S);
21100b57cec5SDimitry Andric           CFGReverseBlockReachabilityAnalysis *cra =
21110b57cec5SDimitry Andric               AC.getCFGReachablityAnalysis();
21120b57cec5SDimitry Andric           // FIXME: We should be able to assert that block is non-null, but
21130b57cec5SDimitry Andric           // the CFG analysis can skip potentially-evaluated expressions in
21140b57cec5SDimitry Andric           // edge cases; see test/Sema/vla-2.c.
21150b57cec5SDimitry Andric           if (block && cra) {
21160b57cec5SDimitry Andric             // Can this block be reached from the entrance?
21170b57cec5SDimitry Andric             if (!cra->isReachable(&AC.getCFG()->getEntry(), block)) {
21180b57cec5SDimitry Andric               AllReachable = false;
21190b57cec5SDimitry Andric               break;
21200b57cec5SDimitry Andric             }
21210b57cec5SDimitry Andric           }
21220b57cec5SDimitry Andric           // If we cannot map to a basic block, assume the statement is
21230b57cec5SDimitry Andric           // reachable.
21240b57cec5SDimitry Andric         }
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric         if (AllReachable)
21270b57cec5SDimitry Andric           S.Diag(D.Loc, D.PD);
21280b57cec5SDimitry Andric       }
21290b57cec5SDimitry Andric     }
21300b57cec5SDimitry Andric 
21310b57cec5SDimitry Andric     if (!analyzed)
21320b57cec5SDimitry Andric       flushDiagnostics(S, fscope);
21330b57cec5SDimitry Andric   }
21340b57cec5SDimitry Andric 
21350b57cec5SDimitry Andric   // Warning: check missing 'return'
21360b57cec5SDimitry Andric   if (P.enableCheckFallThrough) {
21370b57cec5SDimitry Andric     const CheckFallThroughDiagnostics &CD =
21380b57cec5SDimitry Andric         (isa<BlockDecl>(D)
21390b57cec5SDimitry Andric              ? CheckFallThroughDiagnostics::MakeForBlock()
21400b57cec5SDimitry Andric              : (isa<CXXMethodDecl>(D) &&
21410b57cec5SDimitry Andric                 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
21420b57cec5SDimitry Andric                 cast<CXXMethodDecl>(D)->getParent()->isLambda())
21430b57cec5SDimitry Andric                    ? CheckFallThroughDiagnostics::MakeForLambda()
21440b57cec5SDimitry Andric                    : (fscope->isCoroutine()
21450b57cec5SDimitry Andric                           ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
21460b57cec5SDimitry Andric                           : CheckFallThroughDiagnostics::MakeForFunction(D)));
21470b57cec5SDimitry Andric     CheckFallThroughForBody(S, D, Body, BlockType, CD, AC, fscope);
21480b57cec5SDimitry Andric   }
21490b57cec5SDimitry Andric 
21500b57cec5SDimitry Andric   // Warning: check for unreachable code
21510b57cec5SDimitry Andric   if (P.enableCheckUnreachable) {
21520b57cec5SDimitry Andric     // Only check for unreachable code on non-template instantiations.
21530b57cec5SDimitry Andric     // Different template instantiations can effectively change the control-flow
21540b57cec5SDimitry Andric     // and it is very difficult to prove that a snippet of code in a template
21550b57cec5SDimitry Andric     // is unreachable for all instantiations.
21560b57cec5SDimitry Andric     bool isTemplateInstantiation = false;
21570b57cec5SDimitry Andric     if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
21580b57cec5SDimitry Andric       isTemplateInstantiation = Function->isTemplateInstantiation();
21590b57cec5SDimitry Andric     if (!isTemplateInstantiation)
21600b57cec5SDimitry Andric       CheckUnreachable(S, AC);
21610b57cec5SDimitry Andric   }
21620b57cec5SDimitry Andric 
21630b57cec5SDimitry Andric   // Check for thread safety violations
21640b57cec5SDimitry Andric   if (P.enableThreadSafetyAnalysis) {
21650b57cec5SDimitry Andric     SourceLocation FL = AC.getDecl()->getLocation();
21660b57cec5SDimitry Andric     SourceLocation FEL = AC.getDecl()->getEndLoc();
21670b57cec5SDimitry Andric     threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
21680b57cec5SDimitry Andric     if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getBeginLoc()))
21690b57cec5SDimitry Andric       Reporter.setIssueBetaWarnings(true);
21700b57cec5SDimitry Andric     if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getBeginLoc()))
21710b57cec5SDimitry Andric       Reporter.setVerbose(true);
21720b57cec5SDimitry Andric 
21730b57cec5SDimitry Andric     threadSafety::runThreadSafetyAnalysis(AC, Reporter,
21740b57cec5SDimitry Andric                                           &S.ThreadSafetyDeclCache);
21750b57cec5SDimitry Andric     Reporter.emitDiagnostics();
21760b57cec5SDimitry Andric   }
21770b57cec5SDimitry Andric 
21780b57cec5SDimitry Andric   // Check for violations of consumed properties.
21790b57cec5SDimitry Andric   if (P.enableConsumedAnalysis) {
21800b57cec5SDimitry Andric     consumed::ConsumedWarningsHandler WarningHandler(S);
21810b57cec5SDimitry Andric     consumed::ConsumedAnalyzer Analyzer(WarningHandler);
21820b57cec5SDimitry Andric     Analyzer.run(AC);
21830b57cec5SDimitry Andric   }
21840b57cec5SDimitry Andric 
21850b57cec5SDimitry Andric   if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||
21860b57cec5SDimitry Andric       !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
21870b57cec5SDimitry Andric       !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc())) {
21880b57cec5SDimitry Andric     if (CFG *cfg = AC.getCFG()) {
21890b57cec5SDimitry Andric       UninitValsDiagReporter reporter(S);
21900b57cec5SDimitry Andric       UninitVariablesAnalysisStats stats;
21910b57cec5SDimitry Andric       std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats));
21920b57cec5SDimitry Andric       runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
21930b57cec5SDimitry Andric                                         reporter, stats);
21940b57cec5SDimitry Andric 
21950b57cec5SDimitry Andric       if (S.CollectStats && stats.NumVariablesAnalyzed > 0) {
21960b57cec5SDimitry Andric         ++NumUninitAnalysisFunctions;
21970b57cec5SDimitry Andric         NumUninitAnalysisVariables += stats.NumVariablesAnalyzed;
21980b57cec5SDimitry Andric         NumUninitAnalysisBlockVisits += stats.NumBlockVisits;
21990b57cec5SDimitry Andric         MaxUninitAnalysisVariablesPerFunction =
22000b57cec5SDimitry Andric             std::max(MaxUninitAnalysisVariablesPerFunction,
22010b57cec5SDimitry Andric                      stats.NumVariablesAnalyzed);
22020b57cec5SDimitry Andric         MaxUninitAnalysisBlockVisitsPerFunction =
22030b57cec5SDimitry Andric             std::max(MaxUninitAnalysisBlockVisitsPerFunction,
22040b57cec5SDimitry Andric                      stats.NumBlockVisits);
22050b57cec5SDimitry Andric       }
22060b57cec5SDimitry Andric     }
22070b57cec5SDimitry Andric   }
22080b57cec5SDimitry Andric 
22090b57cec5SDimitry Andric   bool FallThroughDiagFull =
22100b57cec5SDimitry Andric       !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc());
22110b57cec5SDimitry Andric   bool FallThroughDiagPerFunction = !Diags.isIgnored(
22120b57cec5SDimitry Andric       diag::warn_unannotated_fallthrough_per_function, D->getBeginLoc());
22130b57cec5SDimitry Andric   if (FallThroughDiagFull || FallThroughDiagPerFunction ||
22140b57cec5SDimitry Andric       fscope->HasFallthroughStmt) {
22150b57cec5SDimitry Andric     DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
22160b57cec5SDimitry Andric   }
22170b57cec5SDimitry Andric 
22180b57cec5SDimitry Andric   if (S.getLangOpts().ObjCWeak &&
22190b57cec5SDimitry Andric       !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getBeginLoc()))
22200b57cec5SDimitry Andric     diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
22210b57cec5SDimitry Andric 
22220b57cec5SDimitry Andric 
22230b57cec5SDimitry Andric   // Check for infinite self-recursion in functions
22240b57cec5SDimitry Andric   if (!Diags.isIgnored(diag::warn_infinite_recursive_function,
22250b57cec5SDimitry Andric                        D->getBeginLoc())) {
22260b57cec5SDimitry Andric     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
22270b57cec5SDimitry Andric       checkRecursiveFunction(S, FD, Body, AC);
22280b57cec5SDimitry Andric     }
22290b57cec5SDimitry Andric   }
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric   // Check for throw out of non-throwing function.
22320b57cec5SDimitry Andric   if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getBeginLoc()))
22330b57cec5SDimitry Andric     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
22340b57cec5SDimitry Andric       if (S.getLangOpts().CPlusPlus && isNoexcept(FD))
22350b57cec5SDimitry Andric         checkThrowInNonThrowingFunc(S, FD, AC);
22360b57cec5SDimitry Andric 
22370b57cec5SDimitry Andric   // If none of the previous checks caused a CFG build, trigger one here
2238*a7dea167SDimitry Andric   // for the logical error handler.
2239*a7dea167SDimitry Andric   if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
22400b57cec5SDimitry Andric     AC.getCFG();
22410b57cec5SDimitry Andric   }
22420b57cec5SDimitry Andric 
22430b57cec5SDimitry Andric   // Collect statistics about the CFG if it was built.
22440b57cec5SDimitry Andric   if (S.CollectStats && AC.isCFGBuilt()) {
22450b57cec5SDimitry Andric     ++NumFunctionsAnalyzed;
22460b57cec5SDimitry Andric     if (CFG *cfg = AC.getCFG()) {
22470b57cec5SDimitry Andric       // If we successfully built a CFG for this context, record some more
22480b57cec5SDimitry Andric       // detail information about it.
22490b57cec5SDimitry Andric       NumCFGBlocks += cfg->getNumBlockIDs();
22500b57cec5SDimitry Andric       MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,
22510b57cec5SDimitry Andric                                          cfg->getNumBlockIDs());
22520b57cec5SDimitry Andric     } else {
22530b57cec5SDimitry Andric       ++NumFunctionsWithBadCFGs;
22540b57cec5SDimitry Andric     }
22550b57cec5SDimitry Andric   }
22560b57cec5SDimitry Andric }
22570b57cec5SDimitry Andric 
22580b57cec5SDimitry Andric void clang::sema::AnalysisBasedWarnings::PrintStats() const {
22590b57cec5SDimitry Andric   llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
22600b57cec5SDimitry Andric 
22610b57cec5SDimitry Andric   unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
22620b57cec5SDimitry Andric   unsigned AvgCFGBlocksPerFunction =
22630b57cec5SDimitry Andric       !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
22640b57cec5SDimitry Andric   llvm::errs() << NumFunctionsAnalyzed << " functions analyzed ("
22650b57cec5SDimitry Andric                << NumFunctionsWithBadCFGs << " w/o CFGs).\n"
22660b57cec5SDimitry Andric                << "  " << NumCFGBlocks << " CFG blocks built.\n"
22670b57cec5SDimitry Andric                << "  " << AvgCFGBlocksPerFunction
22680b57cec5SDimitry Andric                << " average CFG blocks per function.\n"
22690b57cec5SDimitry Andric                << "  " << MaxCFGBlocksPerFunction
22700b57cec5SDimitry Andric                << " max CFG blocks per function.\n";
22710b57cec5SDimitry Andric 
22720b57cec5SDimitry Andric   unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
22730b57cec5SDimitry Andric       : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
22740b57cec5SDimitry Andric   unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
22750b57cec5SDimitry Andric       : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
22760b57cec5SDimitry Andric   llvm::errs() << NumUninitAnalysisFunctions
22770b57cec5SDimitry Andric                << " functions analyzed for uninitialiazed variables\n"
22780b57cec5SDimitry Andric                << "  " << NumUninitAnalysisVariables << " variables analyzed.\n"
22790b57cec5SDimitry Andric                << "  " << AvgUninitVariablesPerFunction
22800b57cec5SDimitry Andric                << " average variables per function.\n"
22810b57cec5SDimitry Andric                << "  " << MaxUninitAnalysisVariablesPerFunction
22820b57cec5SDimitry Andric                << " max variables per function.\n"
22830b57cec5SDimitry Andric                << "  " << NumUninitAnalysisBlockVisits << " block visits.\n"
22840b57cec5SDimitry Andric                << "  " << AvgUninitBlockVisitsPerFunction
22850b57cec5SDimitry Andric                << " average block visits per function.\n"
22860b57cec5SDimitry Andric                << "  " << MaxUninitAnalysisBlockVisitsPerFunction
22870b57cec5SDimitry Andric                << " max block visits per function.\n";
22880b57cec5SDimitry Andric }
2289