Path: blob/main/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
35233 views
//=== AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines analysis_warnings::[Policy,Executor].9// Together they are used by Sema to issue warnings based on inexpensive10// static analysis algorithms in libAnalysis.11//12//===----------------------------------------------------------------------===//1314#include "clang/Sema/AnalysisBasedWarnings.h"15#include "clang/AST/Decl.h"16#include "clang/AST/DeclCXX.h"17#include "clang/AST/DeclObjC.h"18#include "clang/AST/EvaluatedExprVisitor.h"19#include "clang/AST/Expr.h"20#include "clang/AST/ExprCXX.h"21#include "clang/AST/ExprObjC.h"22#include "clang/AST/OperationKinds.h"23#include "clang/AST/ParentMap.h"24#include "clang/AST/RecursiveASTVisitor.h"25#include "clang/AST/StmtCXX.h"26#include "clang/AST/StmtObjC.h"27#include "clang/AST/StmtVisitor.h"28#include "clang/AST/Type.h"29#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"30#include "clang/Analysis/Analyses/CalledOnceCheck.h"31#include "clang/Analysis/Analyses/Consumed.h"32#include "clang/Analysis/Analyses/ReachableCode.h"33#include "clang/Analysis/Analyses/ThreadSafety.h"34#include "clang/Analysis/Analyses/UninitializedValues.h"35#include "clang/Analysis/Analyses/UnsafeBufferUsage.h"36#include "clang/Analysis/AnalysisDeclContext.h"37#include "clang/Analysis/CFG.h"38#include "clang/Analysis/CFGStmtMap.h"39#include "clang/Basic/Diagnostic.h"40#include "clang/Basic/DiagnosticSema.h"41#include "clang/Basic/SourceLocation.h"42#include "clang/Basic/SourceManager.h"43#include "clang/Lex/Preprocessor.h"44#include "clang/Sema/ScopeInfo.h"45#include "clang/Sema/SemaInternal.h"46#include "llvm/ADT/ArrayRef.h"47#include "llvm/ADT/BitVector.h"48#include "llvm/ADT/MapVector.h"49#include "llvm/ADT/STLFunctionalExtras.h"50#include "llvm/ADT/SmallString.h"51#include "llvm/ADT/SmallVector.h"52#include "llvm/ADT/StringRef.h"53#include "llvm/Support/Casting.h"54#include <algorithm>55#include <deque>56#include <iterator>57#include <optional>5859using namespace clang;6061//===----------------------------------------------------------------------===//62// Unreachable code analysis.63//===----------------------------------------------------------------------===//6465namespace {66class UnreachableCodeHandler : public reachable_code::Callback {67Sema &S;68SourceRange PreviousSilenceableCondVal;6970public:71UnreachableCodeHandler(Sema &s) : S(s) {}7273void HandleUnreachable(reachable_code::UnreachableKind UK, SourceLocation L,74SourceRange SilenceableCondVal, SourceRange R1,75SourceRange R2, bool HasFallThroughAttr) override {76// If the diagnosed code is `[[fallthrough]];` and77// `-Wunreachable-code-fallthrough` is enabled, suppress `code will never78// be executed` warning to avoid generating diagnostic twice79if (HasFallThroughAttr &&80!S.getDiagnostics().isIgnored(diag::warn_unreachable_fallthrough_attr,81SourceLocation()))82return;8384// Avoid reporting multiple unreachable code diagnostics that are85// triggered by the same conditional value.86if (PreviousSilenceableCondVal.isValid() &&87SilenceableCondVal.isValid() &&88PreviousSilenceableCondVal == SilenceableCondVal)89return;90PreviousSilenceableCondVal = SilenceableCondVal;9192unsigned diag = diag::warn_unreachable;93switch (UK) {94case reachable_code::UK_Break:95diag = diag::warn_unreachable_break;96break;97case reachable_code::UK_Return:98diag = diag::warn_unreachable_return;99break;100case reachable_code::UK_Loop_Increment:101diag = diag::warn_unreachable_loop_increment;102break;103case reachable_code::UK_Other:104break;105}106107S.Diag(L, diag) << R1 << R2;108109SourceLocation Open = SilenceableCondVal.getBegin();110if (Open.isValid()) {111SourceLocation Close = SilenceableCondVal.getEnd();112Close = S.getLocForEndOfToken(Close);113if (Close.isValid()) {114S.Diag(Open, diag::note_unreachable_silence)115<< FixItHint::CreateInsertion(Open, "/* DISABLES CODE */ (")116<< FixItHint::CreateInsertion(Close, ")");117}118}119}120};121} // anonymous namespace122123/// CheckUnreachable - Check for unreachable code.124static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {125// As a heuristic prune all diagnostics not in the main file. Currently126// the majority of warnings in headers are false positives. These127// are largely caused by configuration state, e.g. preprocessor128// defined code, etc.129//130// Note that this is also a performance optimization. Analyzing131// headers many times can be expensive.132if (!S.getSourceManager().isInMainFile(AC.getDecl()->getBeginLoc()))133return;134135UnreachableCodeHandler UC(S);136reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC);137}138139namespace {140/// Warn on logical operator errors in CFGBuilder141class LogicalErrorHandler : public CFGCallback {142Sema &S;143144public:145LogicalErrorHandler(Sema &S) : S(S) {}146147static bool HasMacroID(const Expr *E) {148if (E->getExprLoc().isMacroID())149return true;150151// Recurse to children.152for (const Stmt *SubStmt : E->children())153if (const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))154if (HasMacroID(SubExpr))155return true;156157return false;158}159160void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override {161if (HasMacroID(B))162return;163164unsigned DiagID = isAlwaysTrue165? diag::warn_tautological_negation_or_compare166: diag::warn_tautological_negation_and_compare;167SourceRange DiagRange = B->getSourceRange();168S.Diag(B->getExprLoc(), DiagID) << DiagRange;169}170171void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override {172if (HasMacroID(B))173return;174175SourceRange DiagRange = B->getSourceRange();176S.Diag(B->getExprLoc(), diag::warn_tautological_overlap_comparison)177<< DiagRange << isAlwaysTrue;178}179180void compareBitwiseEquality(const BinaryOperator *B,181bool isAlwaysTrue) override {182if (HasMacroID(B))183return;184185SourceRange DiagRange = B->getSourceRange();186S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_always)187<< DiagRange << isAlwaysTrue;188}189190void compareBitwiseOr(const BinaryOperator *B) override {191if (HasMacroID(B))192return;193194SourceRange DiagRange = B->getSourceRange();195S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_or) << DiagRange;196}197198static bool hasActiveDiagnostics(DiagnosticsEngine &Diags,199SourceLocation Loc) {200return !Diags.isIgnored(diag::warn_tautological_overlap_comparison, Loc) ||201!Diags.isIgnored(diag::warn_comparison_bitwise_or, Loc) ||202!Diags.isIgnored(diag::warn_tautological_negation_and_compare, Loc);203}204};205} // anonymous namespace206207//===----------------------------------------------------------------------===//208// Check for infinite self-recursion in functions209//===----------------------------------------------------------------------===//210211// Returns true if the function is called anywhere within the CFGBlock.212// For member functions, the additional condition of being call from the213// this pointer is required.214static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) {215// Process all the Stmt's in this block to find any calls to FD.216for (const auto &B : Block) {217if (B.getKind() != CFGElement::Statement)218continue;219220const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());221if (!CE || !CE->getCalleeDecl() ||222CE->getCalleeDecl()->getCanonicalDecl() != FD)223continue;224225// Skip function calls which are qualified with a templated class.226if (const DeclRefExpr *DRE =227dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) {228if (NestedNameSpecifier *NNS = DRE->getQualifier()) {229if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&230isa<TemplateSpecializationType>(NNS->getAsType())) {231continue;232}233}234}235236const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE);237if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||238!MCE->getMethodDecl()->isVirtual())239return true;240}241return false;242}243244// Returns true if every path from the entry block passes through a call to FD.245static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {246llvm::SmallPtrSet<CFGBlock *, 16> Visited;247llvm::SmallVector<CFGBlock *, 16> WorkList;248// Keep track of whether we found at least one recursive path.249bool foundRecursion = false;250251const unsigned ExitID = cfg->getExit().getBlockID();252253// Seed the work list with the entry block.254WorkList.push_back(&cfg->getEntry());255256while (!WorkList.empty()) {257CFGBlock *Block = WorkList.pop_back_val();258259for (auto I = Block->succ_begin(), E = Block->succ_end(); I != E; ++I) {260if (CFGBlock *SuccBlock = *I) {261if (!Visited.insert(SuccBlock).second)262continue;263264// Found a path to the exit node without a recursive call.265if (ExitID == SuccBlock->getBlockID())266return false;267268// If the successor block contains a recursive call, end analysis there.269if (hasRecursiveCallInPath(FD, *SuccBlock)) {270foundRecursion = true;271continue;272}273274WorkList.push_back(SuccBlock);275}276}277}278return foundRecursion;279}280281static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,282const Stmt *Body, AnalysisDeclContext &AC) {283FD = FD->getCanonicalDecl();284285// Only run on non-templated functions and non-templated members of286// templated classes.287if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate &&288FD->getTemplatedKind() != FunctionDecl::TK_MemberSpecialization)289return;290291CFG *cfg = AC.getCFG();292if (!cfg) return;293294// If the exit block is unreachable, skip processing the function.295if (cfg->getExit().pred_empty())296return;297298// Emit diagnostic if a recursive function call is detected for all paths.299if (checkForRecursiveFunctionCall(FD, cfg))300S.Diag(Body->getBeginLoc(), diag::warn_infinite_recursive_function);301}302303//===----------------------------------------------------------------------===//304// Check for throw in a non-throwing function.305//===----------------------------------------------------------------------===//306307/// Determine whether an exception thrown by E, unwinding from ThrowBlock,308/// can reach ExitBlock.309static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock,310CFG *Body) {311SmallVector<CFGBlock *, 16> Stack;312llvm::BitVector Queued(Body->getNumBlockIDs());313314Stack.push_back(&ThrowBlock);315Queued[ThrowBlock.getBlockID()] = true;316317while (!Stack.empty()) {318CFGBlock &UnwindBlock = *Stack.back();319Stack.pop_back();320321for (auto &Succ : UnwindBlock.succs()) {322if (!Succ.isReachable() || Queued[Succ->getBlockID()])323continue;324325if (Succ->getBlockID() == Body->getExit().getBlockID())326return true;327328if (auto *Catch =329dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {330QualType Caught = Catch->getCaughtType();331if (Caught.isNull() || // catch (...) catches everything332!E->getSubExpr() || // throw; is considered cuaght by any handler333S.handlerCanCatch(Caught, E->getSubExpr()->getType()))334// Exception doesn't escape via this path.335break;336} else {337Stack.push_back(Succ);338Queued[Succ->getBlockID()] = true;339}340}341}342343return false;344}345346static void visitReachableThrows(347CFG *BodyCFG,348llvm::function_ref<void(const CXXThrowExpr *, CFGBlock &)> Visit) {349llvm::BitVector Reachable(BodyCFG->getNumBlockIDs());350clang::reachable_code::ScanReachableFromBlock(&BodyCFG->getEntry(), Reachable);351for (CFGBlock *B : *BodyCFG) {352if (!Reachable[B->getBlockID()])353continue;354for (CFGElement &E : *B) {355std::optional<CFGStmt> S = E.getAs<CFGStmt>();356if (!S)357continue;358if (auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))359Visit(Throw, *B);360}361}362}363364static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc,365const FunctionDecl *FD) {366if (!S.getSourceManager().isInSystemHeader(OpLoc) &&367FD->getTypeSourceInfo()) {368S.Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;369if (S.getLangOpts().CPlusPlus11 &&370(isa<CXXDestructorDecl>(FD) ||371FD->getDeclName().getCXXOverloadedOperator() == OO_Delete ||372FD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete)) {373if (const auto *Ty = FD->getTypeSourceInfo()->getType()->374getAs<FunctionProtoType>())375S.Diag(FD->getLocation(), diag::note_throw_in_dtor)376<< !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()377<< FD->getExceptionSpecSourceRange();378} else379S.Diag(FD->getLocation(), diag::note_throw_in_function)380<< FD->getExceptionSpecSourceRange();381}382}383384static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD,385AnalysisDeclContext &AC) {386CFG *BodyCFG = AC.getCFG();387if (!BodyCFG)388return;389if (BodyCFG->getExit().pred_empty())390return;391visitReachableThrows(BodyCFG, [&](const CXXThrowExpr *Throw, CFGBlock &Block) {392if (throwEscapes(S, Throw, Block, BodyCFG))393EmitDiagForCXXThrowInNonThrowingFunc(S, Throw->getThrowLoc(), FD);394});395}396397static bool isNoexcept(const FunctionDecl *FD) {398const auto *FPT = FD->getType()->castAs<FunctionProtoType>();399if (FPT->isNothrow() || FD->hasAttr<NoThrowAttr>())400return true;401return false;402}403404//===----------------------------------------------------------------------===//405// Check for missing return value.406//===----------------------------------------------------------------------===//407408enum ControlFlowKind {409UnknownFallThrough,410NeverFallThrough,411MaybeFallThrough,412AlwaysFallThrough,413NeverFallThroughOrReturn414};415416/// CheckFallThrough - Check that we don't fall off the end of a417/// Statement that should return a value.418///419/// \returns AlwaysFallThrough iff we always fall off the end of the statement,420/// MaybeFallThrough iff we might or might not fall off the end,421/// NeverFallThroughOrReturn iff we never fall off the end of the statement or422/// return. We assume NeverFallThrough iff we never fall off the end of the423/// statement but we may return. We assume that functions not marked noreturn424/// will return.425static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {426CFG *cfg = AC.getCFG();427if (!cfg) return UnknownFallThrough;428429// The CFG leaves in dead things, and we don't want the dead code paths to430// confuse us, so we mark all live things first.431llvm::BitVector live(cfg->getNumBlockIDs());432unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(),433live);434435bool AddEHEdges = AC.getAddEHEdges();436if (!AddEHEdges && count != cfg->getNumBlockIDs())437// When there are things remaining dead, and we didn't add EH edges438// from CallExprs to the catch clauses, we have to go back and439// mark them as live.440for (const auto *B : *cfg) {441if (!live[B->getBlockID()]) {442if (B->pred_begin() == B->pred_end()) {443const Stmt *Term = B->getTerminatorStmt();444if (isa_and_nonnull<CXXTryStmt>(Term))445// When not adding EH edges from calls, catch clauses446// can otherwise seem dead. Avoid noting them as dead.447count += reachable_code::ScanReachableFromBlock(B, live);448continue;449}450}451}452453// Now we know what is live, we check the live precessors of the exit block454// and look for fall through paths, being careful to ignore normal returns,455// and exceptional paths.456bool HasLiveReturn = false;457bool HasFakeEdge = false;458bool HasPlainEdge = false;459bool HasAbnormalEdge = false;460461// Ignore default cases that aren't likely to be reachable because all462// enums in a switch(X) have explicit case statements.463CFGBlock::FilterOptions FO;464FO.IgnoreDefaultsWithCoveredEnums = 1;465466for (CFGBlock::filtered_pred_iterator I =467cfg->getExit().filtered_pred_start_end(FO);468I.hasMore(); ++I) {469const CFGBlock &B = **I;470if (!live[B.getBlockID()])471continue;472473// Skip blocks which contain an element marked as no-return. They don't474// represent actually viable edges into the exit block, so mark them as475// abnormal.476if (B.hasNoReturnElement()) {477HasAbnormalEdge = true;478continue;479}480481// Destructors can appear after the 'return' in the CFG. This is482// normal. We need to look pass the destructors for the return483// statement (if it exists).484CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();485486for ( ; ri != re ; ++ri)487if (ri->getAs<CFGStmt>())488break;489490// No more CFGElements in the block?491if (ri == re) {492const Stmt *Term = B.getTerminatorStmt();493if (Term && (isa<CXXTryStmt>(Term) || isa<ObjCAtTryStmt>(Term))) {494HasAbnormalEdge = true;495continue;496}497// A labeled empty statement, or the entry block...498HasPlainEdge = true;499continue;500}501502CFGStmt CS = ri->castAs<CFGStmt>();503const Stmt *S = CS.getStmt();504if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {505HasLiveReturn = true;506continue;507}508if (isa<ObjCAtThrowStmt>(S)) {509HasFakeEdge = true;510continue;511}512if (isa<CXXThrowExpr>(S)) {513HasFakeEdge = true;514continue;515}516if (isa<MSAsmStmt>(S)) {517// TODO: Verify this is correct.518HasFakeEdge = true;519HasLiveReturn = true;520continue;521}522if (isa<CXXTryStmt>(S)) {523HasAbnormalEdge = true;524continue;525}526if (!llvm::is_contained(B.succs(), &cfg->getExit())) {527HasAbnormalEdge = true;528continue;529}530531HasPlainEdge = true;532}533if (!HasPlainEdge) {534if (HasLiveReturn)535return NeverFallThrough;536return NeverFallThroughOrReturn;537}538if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)539return MaybeFallThrough;540// This says AlwaysFallThrough for calls to functions that are not marked541// noreturn, that don't return. If people would like this warning to be more542// accurate, such functions should be marked as noreturn.543return AlwaysFallThrough;544}545546namespace {547548struct CheckFallThroughDiagnostics {549unsigned diag_MaybeFallThrough_HasNoReturn;550unsigned diag_MaybeFallThrough_ReturnsNonVoid;551unsigned diag_AlwaysFallThrough_HasNoReturn;552unsigned diag_AlwaysFallThrough_ReturnsNonVoid;553unsigned diag_NeverFallThroughOrReturn;554enum { Function, Block, Lambda, Coroutine } funMode;555SourceLocation FuncLoc;556557static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {558CheckFallThroughDiagnostics D;559D.FuncLoc = Func->getLocation();560D.diag_MaybeFallThrough_HasNoReturn =561diag::warn_falloff_noreturn_function;562D.diag_MaybeFallThrough_ReturnsNonVoid =563diag::warn_maybe_falloff_nonvoid_function;564D.diag_AlwaysFallThrough_HasNoReturn =565diag::warn_falloff_noreturn_function;566D.diag_AlwaysFallThrough_ReturnsNonVoid =567diag::warn_falloff_nonvoid_function;568569// Don't suggest that virtual functions be marked "noreturn", since they570// might be overridden by non-noreturn functions.571bool isVirtualMethod = false;572if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))573isVirtualMethod = Method->isVirtual();574575// Don't suggest that template instantiations be marked "noreturn"576bool isTemplateInstantiation = false;577if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))578isTemplateInstantiation = Function->isTemplateInstantiation();579580if (!isVirtualMethod && !isTemplateInstantiation)581D.diag_NeverFallThroughOrReturn =582diag::warn_suggest_noreturn_function;583else584D.diag_NeverFallThroughOrReturn = 0;585586D.funMode = Function;587return D;588}589590static CheckFallThroughDiagnostics MakeForCoroutine(const Decl *Func) {591CheckFallThroughDiagnostics D;592D.FuncLoc = Func->getLocation();593D.diag_MaybeFallThrough_HasNoReturn = 0;594D.diag_MaybeFallThrough_ReturnsNonVoid =595diag::warn_maybe_falloff_nonvoid_coroutine;596D.diag_AlwaysFallThrough_HasNoReturn = 0;597D.diag_AlwaysFallThrough_ReturnsNonVoid =598diag::warn_falloff_nonvoid_coroutine;599D.diag_NeverFallThroughOrReturn = 0;600D.funMode = Coroutine;601return D;602}603604static CheckFallThroughDiagnostics MakeForBlock() {605CheckFallThroughDiagnostics D;606D.diag_MaybeFallThrough_HasNoReturn =607diag::err_noreturn_block_has_return_expr;608D.diag_MaybeFallThrough_ReturnsNonVoid =609diag::err_maybe_falloff_nonvoid_block;610D.diag_AlwaysFallThrough_HasNoReturn =611diag::err_noreturn_block_has_return_expr;612D.diag_AlwaysFallThrough_ReturnsNonVoid =613diag::err_falloff_nonvoid_block;614D.diag_NeverFallThroughOrReturn = 0;615D.funMode = Block;616return D;617}618619static CheckFallThroughDiagnostics MakeForLambda() {620CheckFallThroughDiagnostics D;621D.diag_MaybeFallThrough_HasNoReturn =622diag::err_noreturn_lambda_has_return_expr;623D.diag_MaybeFallThrough_ReturnsNonVoid =624diag::warn_maybe_falloff_nonvoid_lambda;625D.diag_AlwaysFallThrough_HasNoReturn =626diag::err_noreturn_lambda_has_return_expr;627D.diag_AlwaysFallThrough_ReturnsNonVoid =628diag::warn_falloff_nonvoid_lambda;629D.diag_NeverFallThroughOrReturn = 0;630D.funMode = Lambda;631return D;632}633634bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid,635bool HasNoReturn) const {636if (funMode == Function) {637return (ReturnsVoid ||638D.isIgnored(diag::warn_maybe_falloff_nonvoid_function,639FuncLoc)) &&640(!HasNoReturn ||641D.isIgnored(diag::warn_noreturn_function_has_return_expr,642FuncLoc)) &&643(!ReturnsVoid ||644D.isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));645}646if (funMode == Coroutine) {647return (ReturnsVoid ||648D.isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||649D.isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,650FuncLoc)) &&651(!HasNoReturn);652}653// For blocks / lambdas.654return ReturnsVoid && !HasNoReturn;655}656};657658} // anonymous namespace659660/// CheckFallThroughForBody - Check that we don't fall off the end of a661/// function that should return a value. Check that we don't fall off the end662/// of a noreturn function. We assume that functions and blocks not marked663/// noreturn will return.664static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,665QualType BlockType,666const CheckFallThroughDiagnostics &CD,667AnalysisDeclContext &AC,668sema::FunctionScopeInfo *FSI) {669670bool ReturnsVoid = false;671bool HasNoReturn = false;672bool IsCoroutine = FSI->isCoroutine();673674if (const auto *FD = dyn_cast<FunctionDecl>(D)) {675if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))676ReturnsVoid = CBody->getFallthroughHandler() != nullptr;677else678ReturnsVoid = FD->getReturnType()->isVoidType();679HasNoReturn = FD->isNoReturn();680}681else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {682ReturnsVoid = MD->getReturnType()->isVoidType();683HasNoReturn = MD->hasAttr<NoReturnAttr>();684}685else if (isa<BlockDecl>(D)) {686if (const FunctionType *FT =687BlockType->getPointeeType()->getAs<FunctionType>()) {688if (FT->getReturnType()->isVoidType())689ReturnsVoid = true;690if (FT->getNoReturnAttr())691HasNoReturn = true;692}693}694695DiagnosticsEngine &Diags = S.getDiagnostics();696697// Short circuit for compilation speed.698if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))699return;700SourceLocation LBrace = Body->getBeginLoc(), RBrace = Body->getEndLoc();701auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {702if (IsCoroutine)703S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType();704else705S.Diag(Loc, DiagID);706};707708// cpu_dispatch functions permit empty function bodies for ICC compatibility.709if (D->getAsFunction() && D->getAsFunction()->isCPUDispatchMultiVersion())710return;711712// Either in a function body compound statement, or a function-try-block.713switch (CheckFallThrough(AC)) {714case UnknownFallThrough:715break;716717case MaybeFallThrough:718if (HasNoReturn)719EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);720else if (!ReturnsVoid)721EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);722break;723case AlwaysFallThrough:724if (HasNoReturn)725EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);726else if (!ReturnsVoid)727EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);728break;729case NeverFallThroughOrReturn:730if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {731if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {732S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;733} else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {734S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;735} else {736S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn);737}738}739break;740case NeverFallThrough:741break;742}743}744745//===----------------------------------------------------------------------===//746// -Wuninitialized747//===----------------------------------------------------------------------===//748749namespace {750/// ContainsReference - A visitor class to search for references to751/// a particular declaration (the needle) within any evaluated component of an752/// expression (recursively).753class ContainsReference : public ConstEvaluatedExprVisitor<ContainsReference> {754bool FoundReference;755const DeclRefExpr *Needle;756757public:758typedef ConstEvaluatedExprVisitor<ContainsReference> Inherited;759760ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)761: Inherited(Context), FoundReference(false), Needle(Needle) {}762763void VisitExpr(const Expr *E) {764// Stop evaluating if we already have a reference.765if (FoundReference)766return;767768Inherited::VisitExpr(E);769}770771void VisitDeclRefExpr(const DeclRefExpr *E) {772if (E == Needle)773FoundReference = true;774else775Inherited::VisitDeclRefExpr(E);776}777778bool doesContainReference() const { return FoundReference; }779};780} // anonymous namespace781782static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {783QualType VariableTy = VD->getType().getCanonicalType();784if (VariableTy->isBlockPointerType() &&785!VD->hasAttr<BlocksAttr>()) {786S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization)787<< VD->getDeclName()788<< FixItHint::CreateInsertion(VD->getLocation(), "__block ");789return true;790}791792// Don't issue a fixit if there is already an initializer.793if (VD->getInit())794return false;795796// Don't suggest a fixit inside macros.797if (VD->getEndLoc().isMacroID())798return false;799800SourceLocation Loc = S.getLocForEndOfToken(VD->getEndLoc());801802// Suggest possible initialization (if any).803std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);804if (Init.empty())805return false;806807S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()808<< FixItHint::CreateInsertion(Loc, Init);809return true;810}811812/// Create a fixit to remove an if-like statement, on the assumption that its813/// condition is CondVal.814static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then,815const Stmt *Else, bool CondVal,816FixItHint &Fixit1, FixItHint &Fixit2) {817if (CondVal) {818// If condition is always true, remove all but the 'then'.819Fixit1 = FixItHint::CreateRemoval(820CharSourceRange::getCharRange(If->getBeginLoc(), Then->getBeginLoc()));821if (Else) {822SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getEndLoc());823Fixit2 =824FixItHint::CreateRemoval(SourceRange(ElseKwLoc, Else->getEndLoc()));825}826} else {827// If condition is always false, remove all but the 'else'.828if (Else)829Fixit1 = FixItHint::CreateRemoval(CharSourceRange::getCharRange(830If->getBeginLoc(), Else->getBeginLoc()));831else832Fixit1 = FixItHint::CreateRemoval(If->getSourceRange());833}834}835836/// DiagUninitUse -- Helper function to produce a diagnostic for an837/// uninitialized use of a variable.838static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,839bool IsCapturedByBlock) {840bool Diagnosed = false;841842switch (Use.getKind()) {843case UninitUse::Always:844S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_var)845<< VD->getDeclName() << IsCapturedByBlock846<< Use.getUser()->getSourceRange();847return;848849case UninitUse::AfterDecl:850case UninitUse::AfterCall:851S.Diag(VD->getLocation(), diag::warn_sometimes_uninit_var)852<< VD->getDeclName() << IsCapturedByBlock853<< (Use.getKind() == UninitUse::AfterDecl ? 4 : 5)854<< const_cast<DeclContext*>(VD->getLexicalDeclContext())855<< VD->getSourceRange();856S.Diag(Use.getUser()->getBeginLoc(), diag::note_uninit_var_use)857<< IsCapturedByBlock << Use.getUser()->getSourceRange();858return;859860case UninitUse::Maybe:861case UninitUse::Sometimes:862// Carry on to report sometimes-uninitialized branches, if possible,863// or a 'may be used uninitialized' diagnostic otherwise.864break;865}866867// Diagnose each branch which leads to a sometimes-uninitialized use.868for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end();869I != E; ++I) {870assert(Use.getKind() == UninitUse::Sometimes);871872const Expr *User = Use.getUser();873const Stmt *Term = I->Terminator;874875// Information used when building the diagnostic.876unsigned DiagKind;877StringRef Str;878SourceRange Range;879880// FixIts to suppress the diagnostic by removing the dead condition.881// For all binary terminators, branch 0 is taken if the condition is true,882// and branch 1 is taken if the condition is false.883int RemoveDiagKind = -1;884const char *FixitStr =885S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false")886: (I->Output ? "1" : "0");887FixItHint Fixit1, Fixit2;888889switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) {890default:891// Don't know how to report this. Just fall back to 'may be used892// uninitialized'. FIXME: Can this happen?893continue;894895// "condition is true / condition is false".896case Stmt::IfStmtClass: {897const IfStmt *IS = cast<IfStmt>(Term);898DiagKind = 0;899Str = "if";900Range = IS->getCond()->getSourceRange();901RemoveDiagKind = 0;902CreateIfFixit(S, IS, IS->getThen(), IS->getElse(),903I->Output, Fixit1, Fixit2);904break;905}906case Stmt::ConditionalOperatorClass: {907const ConditionalOperator *CO = cast<ConditionalOperator>(Term);908DiagKind = 0;909Str = "?:";910Range = CO->getCond()->getSourceRange();911RemoveDiagKind = 0;912CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(),913I->Output, Fixit1, Fixit2);914break;915}916case Stmt::BinaryOperatorClass: {917const BinaryOperator *BO = cast<BinaryOperator>(Term);918if (!BO->isLogicalOp())919continue;920DiagKind = 0;921Str = BO->getOpcodeStr();922Range = BO->getLHS()->getSourceRange();923RemoveDiagKind = 0;924if ((BO->getOpcode() == BO_LAnd && I->Output) ||925(BO->getOpcode() == BO_LOr && !I->Output))926// true && y -> y, false || y -> y.927Fixit1 = FixItHint::CreateRemoval(928SourceRange(BO->getBeginLoc(), BO->getOperatorLoc()));929else930// false && y -> false, true || y -> true.931Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr);932break;933}934935// "loop is entered / loop is exited".936case Stmt::WhileStmtClass:937DiagKind = 1;938Str = "while";939Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();940RemoveDiagKind = 1;941Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);942break;943case Stmt::ForStmtClass:944DiagKind = 1;945Str = "for";946Range = cast<ForStmt>(Term)->getCond()->getSourceRange();947RemoveDiagKind = 1;948if (I->Output)949Fixit1 = FixItHint::CreateRemoval(Range);950else951Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);952break;953case Stmt::CXXForRangeStmtClass:954if (I->Output == 1) {955// The use occurs if a range-based for loop's body never executes.956// That may be impossible, and there's no syntactic fix for this,957// so treat it as a 'may be uninitialized' case.958continue;959}960DiagKind = 1;961Str = "for";962Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();963break;964965// "condition is true / loop is exited".966case Stmt::DoStmtClass:967DiagKind = 2;968Str = "do";969Range = cast<DoStmt>(Term)->getCond()->getSourceRange();970RemoveDiagKind = 1;971Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);972break;973974// "switch case is taken".975case Stmt::CaseStmtClass:976DiagKind = 3;977Str = "case";978Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();979break;980case Stmt::DefaultStmtClass:981DiagKind = 3;982Str = "default";983Range = cast<DefaultStmt>(Term)->getDefaultLoc();984break;985}986987S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var)988<< VD->getDeclName() << IsCapturedByBlock << DiagKind989<< Str << I->Output << Range;990S.Diag(User->getBeginLoc(), diag::note_uninit_var_use)991<< IsCapturedByBlock << User->getSourceRange();992if (RemoveDiagKind != -1)993S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond)994<< RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;995996Diagnosed = true;997}998999if (!Diagnosed)1000S.Diag(Use.getUser()->getBeginLoc(), diag::warn_maybe_uninit_var)1001<< VD->getDeclName() << IsCapturedByBlock1002<< Use.getUser()->getSourceRange();1003}10041005/// Diagnose uninitialized const reference usages.1006static bool DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD,1007const UninitUse &Use) {1008S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_reference)1009<< VD->getDeclName() << Use.getUser()->getSourceRange();1010return true;1011}10121013/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an1014/// uninitialized variable. This manages the different forms of diagnostic1015/// emitted for particular types of uses. Returns true if the use was diagnosed1016/// as a warning. If a particular use is one we omit warnings for, returns1017/// false.1018static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,1019const UninitUse &Use,1020bool alwaysReportSelfInit = false) {1021if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) {1022// Inspect the initializer of the variable declaration which is1023// being referenced prior to its initialization. We emit1024// specialized diagnostics for self-initialization, and we1025// specifically avoid warning about self references which take the1026// form of:1027//1028// int x = x;1029//1030// This is used to indicate to GCC that 'x' is intentionally left1031// uninitialized. Proven code paths which access 'x' in1032// an uninitialized state after this will still warn.1033if (const Expr *Initializer = VD->getInit()) {1034if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())1035return false;10361037ContainsReference CR(S.Context, DRE);1038CR.Visit(Initializer);1039if (CR.doesContainReference()) {1040S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)1041<< VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();1042return true;1043}1044}10451046DiagUninitUse(S, VD, Use, false);1047} else {1048const BlockExpr *BE = cast<BlockExpr>(Use.getUser());1049if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>())1050S.Diag(BE->getBeginLoc(),1051diag::warn_uninit_byref_blockvar_captured_by_block)1052<< VD->getDeclName()1053<< VD->getType().getQualifiers().hasObjCLifetime();1054else1055DiagUninitUse(S, VD, Use, true);1056}10571058// Report where the variable was declared when the use wasn't within1059// the initializer of that declaration & we didn't already suggest1060// an initialization fixit.1061if (!SuggestInitializationFixit(S, VD))1062S.Diag(VD->getBeginLoc(), diag::note_var_declared_here)1063<< VD->getDeclName();10641065return true;1066}10671068namespace {1069class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> {1070public:1071FallthroughMapper(Sema &S)1072: FoundSwitchStatements(false),1073S(S) {1074}10751076bool foundSwitchStatements() const { return FoundSwitchStatements; }10771078void markFallthroughVisited(const AttributedStmt *Stmt) {1079bool Found = FallthroughStmts.erase(Stmt);1080assert(Found);1081(void)Found;1082}10831084typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;10851086const AttrStmts &getFallthroughStmts() const {1087return FallthroughStmts;1088}10891090void fillReachableBlocks(CFG *Cfg) {1091assert(ReachableBlocks.empty() && "ReachableBlocks already filled");1092std::deque<const CFGBlock *> BlockQueue;10931094ReachableBlocks.insert(&Cfg->getEntry());1095BlockQueue.push_back(&Cfg->getEntry());1096// Mark all case blocks reachable to avoid problems with switching on1097// constants, covered enums, etc.1098// These blocks can contain fall-through annotations, and we don't want to1099// issue a warn_fallthrough_attr_unreachable for them.1100for (const auto *B : *Cfg) {1101const Stmt *L = B->getLabel();1102if (isa_and_nonnull<SwitchCase>(L) && ReachableBlocks.insert(B).second)1103BlockQueue.push_back(B);1104}11051106while (!BlockQueue.empty()) {1107const CFGBlock *P = BlockQueue.front();1108BlockQueue.pop_front();1109for (const CFGBlock *B : P->succs()) {1110if (B && ReachableBlocks.insert(B).second)1111BlockQueue.push_back(B);1112}1113}1114}11151116bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt,1117bool IsTemplateInstantiation) {1118assert(!ReachableBlocks.empty() && "ReachableBlocks empty");11191120int UnannotatedCnt = 0;1121AnnotatedCnt = 0;11221123std::deque<const CFGBlock*> BlockQueue(B.pred_begin(), B.pred_end());1124while (!BlockQueue.empty()) {1125const CFGBlock *P = BlockQueue.front();1126BlockQueue.pop_front();1127if (!P) continue;11281129const Stmt *Term = P->getTerminatorStmt();1130if (isa_and_nonnull<SwitchStmt>(Term))1131continue; // Switch statement, good.11321133const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel());1134if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end())1135continue; // Previous case label has no statements, good.11361137const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel());1138if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end())1139continue; // Case label is preceded with a normal label, good.11401141if (!ReachableBlocks.count(P)) {1142for (const CFGElement &Elem : llvm::reverse(*P)) {1143if (std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>()) {1144if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {1145// Don't issue a warning for an unreachable fallthrough1146// attribute in template instantiations as it may not be1147// unreachable in all instantiations of the template.1148if (!IsTemplateInstantiation)1149S.Diag(AS->getBeginLoc(),1150diag::warn_unreachable_fallthrough_attr);1151markFallthroughVisited(AS);1152++AnnotatedCnt;1153break;1154}1155// Don't care about other unreachable statements.1156}1157}1158// If there are no unreachable statements, this may be a special1159// case in CFG:1160// case X: {1161// A a; // A has a destructor.1162// break;1163// }1164// // <<<< This place is represented by a 'hanging' CFG block.1165// case Y:1166continue;1167}11681169const Stmt *LastStmt = getLastStmt(*P);1170if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) {1171markFallthroughVisited(AS);1172++AnnotatedCnt;1173continue; // Fallthrough annotation, good.1174}11751176if (!LastStmt) { // This block contains no executable statements.1177// Traverse its predecessors.1178std::copy(P->pred_begin(), P->pred_end(),1179std::back_inserter(BlockQueue));1180continue;1181}11821183++UnannotatedCnt;1184}1185return !!UnannotatedCnt;1186}11871188// RecursiveASTVisitor setup.1189bool shouldWalkTypesOfTypeLocs() const { return false; }11901191bool VisitAttributedStmt(AttributedStmt *S) {1192if (asFallThroughAttr(S))1193FallthroughStmts.insert(S);1194return true;1195}11961197bool VisitSwitchStmt(SwitchStmt *S) {1198FoundSwitchStatements = true;1199return true;1200}12011202// We don't want to traverse local type declarations. We analyze their1203// methods separately.1204bool TraverseDecl(Decl *D) { return true; }12051206// We analyze lambda bodies separately. Skip them here.1207bool TraverseLambdaExpr(LambdaExpr *LE) {1208// Traverse the captures, but not the body.1209for (const auto C : zip(LE->captures(), LE->capture_inits()))1210TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));1211return true;1212}12131214private:12151216static const AttributedStmt *asFallThroughAttr(const Stmt *S) {1217if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {1218if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))1219return AS;1220}1221return nullptr;1222}12231224static const Stmt *getLastStmt(const CFGBlock &B) {1225if (const Stmt *Term = B.getTerminatorStmt())1226return Term;1227for (const CFGElement &Elem : llvm::reverse(B))1228if (std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>())1229return CS->getStmt();1230// Workaround to detect a statement thrown out by CFGBuilder:1231// case X: {} case Y:1232// case X: ; case Y:1233if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel()))1234if (!isa<SwitchCase>(SW->getSubStmt()))1235return SW->getSubStmt();12361237return nullptr;1238}12391240bool FoundSwitchStatements;1241AttrStmts FallthroughStmts;1242Sema &S;1243llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;1244};1245} // anonymous namespace12461247static StringRef getFallthroughAttrSpelling(Preprocessor &PP,1248SourceLocation Loc) {1249TokenValue FallthroughTokens[] = {1250tok::l_square, tok::l_square,1251PP.getIdentifierInfo("fallthrough"),1252tok::r_square, tok::r_square1253};12541255TokenValue ClangFallthroughTokens[] = {1256tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"),1257tok::coloncolon, PP.getIdentifierInfo("fallthrough"),1258tok::r_square, tok::r_square1259};12601261bool PreferClangAttr = !PP.getLangOpts().CPlusPlus17 && !PP.getLangOpts().C23;12621263StringRef MacroName;1264if (PreferClangAttr)1265MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);1266if (MacroName.empty())1267MacroName = PP.getLastMacroWithSpelling(Loc, FallthroughTokens);1268if (MacroName.empty() && !PreferClangAttr)1269MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens);1270if (MacroName.empty()) {1271if (!PreferClangAttr)1272MacroName = "[[fallthrough]]";1273else if (PP.getLangOpts().CPlusPlus)1274MacroName = "[[clang::fallthrough]]";1275else1276MacroName = "__attribute__((fallthrough))";1277}1278return MacroName;1279}12801281static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,1282bool PerFunction) {1283FallthroughMapper FM(S);1284FM.TraverseStmt(AC.getBody());12851286if (!FM.foundSwitchStatements())1287return;12881289if (PerFunction && FM.getFallthroughStmts().empty())1290return;12911292CFG *Cfg = AC.getCFG();12931294if (!Cfg)1295return;12961297FM.fillReachableBlocks(Cfg);12981299for (const CFGBlock *B : llvm::reverse(*Cfg)) {1300const Stmt *Label = B->getLabel();13011302if (!isa_and_nonnull<SwitchCase>(Label))1303continue;13041305int AnnotatedCnt;13061307bool IsTemplateInstantiation = false;1308if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(AC.getDecl()))1309IsTemplateInstantiation = Function->isTemplateInstantiation();1310if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,1311IsTemplateInstantiation))1312continue;13131314S.Diag(Label->getBeginLoc(),1315PerFunction ? diag::warn_unannotated_fallthrough_per_function1316: diag::warn_unannotated_fallthrough);13171318if (!AnnotatedCnt) {1319SourceLocation L = Label->getBeginLoc();1320if (L.isMacroID())1321continue;13221323const Stmt *Term = B->getTerminatorStmt();1324// Skip empty cases.1325while (B->empty() && !Term && B->succ_size() == 1) {1326B = *B->succ_begin();1327Term = B->getTerminatorStmt();1328}1329if (!(B->empty() && isa_and_nonnull<BreakStmt>(Term))) {1330Preprocessor &PP = S.getPreprocessor();1331StringRef AnnotationSpelling = getFallthroughAttrSpelling(PP, L);1332SmallString<64> TextToInsert(AnnotationSpelling);1333TextToInsert += "; ";1334S.Diag(L, diag::note_insert_fallthrough_fixit)1335<< AnnotationSpelling1336<< FixItHint::CreateInsertion(L, TextToInsert);1337}1338S.Diag(L, diag::note_insert_break_fixit)1339<< FixItHint::CreateInsertion(L, "break; ");1340}1341}13421343for (const auto *F : FM.getFallthroughStmts())1344S.Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);1345}13461347static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,1348const Stmt *S) {1349assert(S);13501351do {1352switch (S->getStmtClass()) {1353case Stmt::ForStmtClass:1354case Stmt::WhileStmtClass:1355case Stmt::CXXForRangeStmtClass:1356case Stmt::ObjCForCollectionStmtClass:1357return true;1358case Stmt::DoStmtClass: {1359Expr::EvalResult Result;1360if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))1361return true;1362return Result.Val.getInt().getBoolValue();1363}1364default:1365break;1366}1367} while ((S = PM.getParent(S)));13681369return false;1370}13711372static void diagnoseRepeatedUseOfWeak(Sema &S,1373const sema::FunctionScopeInfo *CurFn,1374const Decl *D,1375const ParentMap &PM) {1376typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy;1377typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap;1378typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector;1379typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>1380StmtUsesPair;13811382ASTContext &Ctx = S.getASTContext();13831384const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses();13851386// Extract all weak objects that are referenced more than once.1387SmallVector<StmtUsesPair, 8> UsesByStmt;1388for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();1389I != E; ++I) {1390const WeakUseVector &Uses = I->second;13911392// Find the first read of the weak object.1393WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();1394for ( ; UI != UE; ++UI) {1395if (UI->isUnsafe())1396break;1397}13981399// If there were only writes to this object, don't warn.1400if (UI == UE)1401continue;14021403// If there was only one read, followed by any number of writes, and the1404// read is not within a loop, don't warn. Additionally, don't warn in a1405// loop if the base object is a local variable -- local variables are often1406// changed in loops.1407if (UI == Uses.begin()) {1408WeakUseVector::const_iterator UI2 = UI;1409for (++UI2; UI2 != UE; ++UI2)1410if (UI2->isUnsafe())1411break;14121413if (UI2 == UE) {1414if (!isInLoop(Ctx, PM, UI->getUseExpr()))1415continue;14161417const WeakObjectProfileTy &Profile = I->first;1418if (!Profile.isExactProfile())1419continue;14201421const NamedDecl *Base = Profile.getBase();1422if (!Base)1423Base = Profile.getProperty();1424assert(Base && "A profile always has a base or property.");14251426if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))1427if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))1428continue;1429}1430}14311432UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));1433}14341435if (UsesByStmt.empty())1436return;14371438// Sort by first use so that we emit the warnings in a deterministic order.1439SourceManager &SM = S.getSourceManager();1440llvm::sort(UsesByStmt,1441[&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {1442return SM.isBeforeInTranslationUnit(LHS.first->getBeginLoc(),1443RHS.first->getBeginLoc());1444});14451446// Classify the current code body for better warning text.1447// This enum should stay in sync with the cases in1448// warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.1449// FIXME: Should we use a common classification enum and the same set of1450// possibilities all throughout Sema?1451enum {1452Function,1453Method,1454Block,1455Lambda1456} FunctionKind;14571458if (isa<sema::BlockScopeInfo>(CurFn))1459FunctionKind = Block;1460else if (isa<sema::LambdaScopeInfo>(CurFn))1461FunctionKind = Lambda;1462else if (isa<ObjCMethodDecl>(D))1463FunctionKind = Method;1464else1465FunctionKind = Function;14661467// Iterate through the sorted problems and emit warnings for each.1468for (const auto &P : UsesByStmt) {1469const Stmt *FirstRead = P.first;1470const WeakObjectProfileTy &Key = P.second->first;1471const WeakUseVector &Uses = P.second->second;14721473// For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy1474// may not contain enough information to determine that these are different1475// properties. We can only be 100% sure of a repeated use in certain cases,1476// and we adjust the diagnostic kind accordingly so that the less certain1477// case can be turned off if it is too noisy.1478unsigned DiagKind;1479if (Key.isExactProfile())1480DiagKind = diag::warn_arc_repeated_use_of_weak;1481else1482DiagKind = diag::warn_arc_possible_repeated_use_of_weak;14831484// Classify the weak object being accessed for better warning text.1485// This enum should stay in sync with the cases in1486// warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.1487enum {1488Variable,1489Property,1490ImplicitProperty,1491Ivar1492} ObjectKind;14931494const NamedDecl *KeyProp = Key.getProperty();1495if (isa<VarDecl>(KeyProp))1496ObjectKind = Variable;1497else if (isa<ObjCPropertyDecl>(KeyProp))1498ObjectKind = Property;1499else if (isa<ObjCMethodDecl>(KeyProp))1500ObjectKind = ImplicitProperty;1501else if (isa<ObjCIvarDecl>(KeyProp))1502ObjectKind = Ivar;1503else1504llvm_unreachable("Unexpected weak object kind!");15051506// Do not warn about IBOutlet weak property receivers being set to null1507// since they are typically only used from the main thread.1508if (const ObjCPropertyDecl *Prop = dyn_cast<ObjCPropertyDecl>(KeyProp))1509if (Prop->hasAttr<IBOutletAttr>())1510continue;15111512// Show the first time the object was read.1513S.Diag(FirstRead->getBeginLoc(), DiagKind)1514<< int(ObjectKind) << KeyProp << int(FunctionKind)1515<< FirstRead->getSourceRange();15161517// Print all the other accesses as notes.1518for (const auto &Use : Uses) {1519if (Use.getUseExpr() == FirstRead)1520continue;1521S.Diag(Use.getUseExpr()->getBeginLoc(),1522diag::note_arc_weak_also_accessed_here)1523<< Use.getUseExpr()->getSourceRange();1524}1525}1526}15271528namespace clang {1529namespace {1530typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;1531typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;1532typedef std::list<DelayedDiag> DiagList;15331534struct SortDiagBySourceLocation {1535SourceManager &SM;1536SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}15371538bool operator()(const DelayedDiag &left, const DelayedDiag &right) {1539// Although this call will be slow, this is only called when outputting1540// multiple warnings.1541return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);1542}1543};1544} // anonymous namespace1545} // namespace clang15461547namespace {1548class UninitValsDiagReporter : public UninitVariablesHandler {1549Sema &S;1550typedef SmallVector<UninitUse, 2> UsesVec;1551typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;1552// Prefer using MapVector to DenseMap, so that iteration order will be1553// the same as insertion order. This is needed to obtain a deterministic1554// order of diagnostics when calling flushDiagnostics().1555typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;1556UsesMap uses;1557UsesMap constRefUses;15581559public:1560UninitValsDiagReporter(Sema &S) : S(S) {}1561~UninitValsDiagReporter() override { flushDiagnostics(); }15621563MappedType &getUses(UsesMap &um, const VarDecl *vd) {1564MappedType &V = um[vd];1565if (!V.getPointer())1566V.setPointer(new UsesVec());1567return V;1568}15691570void handleUseOfUninitVariable(const VarDecl *vd,1571const UninitUse &use) override {1572getUses(uses, vd).getPointer()->push_back(use);1573}15741575void handleConstRefUseOfUninitVariable(const VarDecl *vd,1576const UninitUse &use) override {1577getUses(constRefUses, vd).getPointer()->push_back(use);1578}15791580void handleSelfInit(const VarDecl *vd) override {1581getUses(uses, vd).setInt(true);1582getUses(constRefUses, vd).setInt(true);1583}15841585void flushDiagnostics() {1586for (const auto &P : uses) {1587const VarDecl *vd = P.first;1588const MappedType &V = P.second;15891590UsesVec *vec = V.getPointer();1591bool hasSelfInit = V.getInt();15921593// Specially handle the case where we have uses of an uninitialized1594// variable, but the root cause is an idiomatic self-init. We want1595// to report the diagnostic at the self-init since that is the root cause.1596if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))1597DiagnoseUninitializedUse(S, vd,1598UninitUse(vd->getInit()->IgnoreParenCasts(),1599/* isAlwaysUninit */ true),1600/* alwaysReportSelfInit */ true);1601else {1602// Sort the uses by their SourceLocations. While not strictly1603// guaranteed to produce them in line/column order, this will provide1604// a stable ordering.1605llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {1606// Prefer a more confident report over a less confident one.1607if (a.getKind() != b.getKind())1608return a.getKind() > b.getKind();1609return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();1610});16111612for (const auto &U : *vec) {1613// If we have self-init, downgrade all uses to 'may be uninitialized'.1614UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;16151616if (DiagnoseUninitializedUse(S, vd, Use))1617// Skip further diagnostics for this variable. We try to warn only1618// on the first point at which a variable is used uninitialized.1619break;1620}1621}16221623// Release the uses vector.1624delete vec;1625}16261627uses.clear();16281629// Flush all const reference uses diags.1630for (const auto &P : constRefUses) {1631const VarDecl *vd = P.first;1632const MappedType &V = P.second;16331634UsesVec *vec = V.getPointer();1635bool hasSelfInit = V.getInt();16361637if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))1638DiagnoseUninitializedUse(S, vd,1639UninitUse(vd->getInit()->IgnoreParenCasts(),1640/* isAlwaysUninit */ true),1641/* alwaysReportSelfInit */ true);1642else {1643for (const auto &U : *vec) {1644if (DiagnoseUninitializedConstRefUse(S, vd, U))1645break;1646}1647}16481649// Release the uses vector.1650delete vec;1651}16521653constRefUses.clear();1654}16551656private:1657static bool hasAlwaysUninitializedUse(const UsesVec* vec) {1658return llvm::any_of(*vec, [](const UninitUse &U) {1659return U.getKind() == UninitUse::Always ||1660U.getKind() == UninitUse::AfterCall ||1661U.getKind() == UninitUse::AfterDecl;1662});1663}1664};16651666/// Inter-procedural data for the called-once checker.1667class CalledOnceInterProceduralData {1668public:1669// Add the delayed warning for the given block.1670void addDelayedWarning(const BlockDecl *Block,1671PartialDiagnosticAt &&Warning) {1672DelayedBlockWarnings[Block].emplace_back(std::move(Warning));1673}1674// Report all of the warnings we've gathered for the given block.1675void flushWarnings(const BlockDecl *Block, Sema &S) {1676for (const PartialDiagnosticAt &Delayed : DelayedBlockWarnings[Block])1677S.Diag(Delayed.first, Delayed.second);16781679discardWarnings(Block);1680}1681// Discard all of the warnings we've gathered for the given block.1682void discardWarnings(const BlockDecl *Block) {1683DelayedBlockWarnings.erase(Block);1684}16851686private:1687using DelayedDiagnostics = SmallVector<PartialDiagnosticAt, 2>;1688llvm::DenseMap<const BlockDecl *, DelayedDiagnostics> DelayedBlockWarnings;1689};16901691class CalledOnceCheckReporter : public CalledOnceCheckHandler {1692public:1693CalledOnceCheckReporter(Sema &S, CalledOnceInterProceduralData &Data)1694: S(S), Data(Data) {}1695void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call,1696const Expr *PrevCall, bool IsCompletionHandler,1697bool Poised) override {1698auto DiagToReport = IsCompletionHandler1699? diag::warn_completion_handler_called_twice1700: diag::warn_called_once_gets_called_twice;1701S.Diag(Call->getBeginLoc(), DiagToReport) << Parameter;1702S.Diag(PrevCall->getBeginLoc(), diag::note_called_once_gets_called_twice)1703<< Poised;1704}17051706void handleNeverCalled(const ParmVarDecl *Parameter,1707bool IsCompletionHandler) override {1708auto DiagToReport = IsCompletionHandler1709? diag::warn_completion_handler_never_called1710: diag::warn_called_once_never_called;1711S.Diag(Parameter->getBeginLoc(), DiagToReport)1712<< Parameter << /* Captured */ false;1713}17141715void handleNeverCalled(const ParmVarDecl *Parameter, const Decl *Function,1716const Stmt *Where, NeverCalledReason Reason,1717bool IsCalledDirectly,1718bool IsCompletionHandler) override {1719auto DiagToReport = IsCompletionHandler1720? diag::warn_completion_handler_never_called_when1721: diag::warn_called_once_never_called_when;1722PartialDiagnosticAt Warning(Where->getBeginLoc(), S.PDiag(DiagToReport)1723<< Parameter1724<< IsCalledDirectly1725<< (unsigned)Reason);17261727if (const auto *Block = dyn_cast<BlockDecl>(Function)) {1728// We shouldn't report these warnings on blocks immediately1729Data.addDelayedWarning(Block, std::move(Warning));1730} else {1731S.Diag(Warning.first, Warning.second);1732}1733}17341735void handleCapturedNeverCalled(const ParmVarDecl *Parameter,1736const Decl *Where,1737bool IsCompletionHandler) override {1738auto DiagToReport = IsCompletionHandler1739? diag::warn_completion_handler_never_called1740: diag::warn_called_once_never_called;1741S.Diag(Where->getBeginLoc(), DiagToReport)1742<< Parameter << /* Captured */ true;1743}17441745void1746handleBlockThatIsGuaranteedToBeCalledOnce(const BlockDecl *Block) override {1747Data.flushWarnings(Block, S);1748}17491750void handleBlockWithNoGuarantees(const BlockDecl *Block) override {1751Data.discardWarnings(Block);1752}17531754private:1755Sema &S;1756CalledOnceInterProceduralData &Data;1757};17581759constexpr unsigned CalledOnceWarnings[] = {1760diag::warn_called_once_never_called,1761diag::warn_called_once_never_called_when,1762diag::warn_called_once_gets_called_twice};17631764constexpr unsigned CompletionHandlerWarnings[]{1765diag::warn_completion_handler_never_called,1766diag::warn_completion_handler_never_called_when,1767diag::warn_completion_handler_called_twice};17681769bool shouldAnalyzeCalledOnceImpl(llvm::ArrayRef<unsigned> DiagIDs,1770const DiagnosticsEngine &Diags,1771SourceLocation At) {1772return llvm::any_of(DiagIDs, [&Diags, At](unsigned DiagID) {1773return !Diags.isIgnored(DiagID, At);1774});1775}17761777bool shouldAnalyzeCalledOnceConventions(const DiagnosticsEngine &Diags,1778SourceLocation At) {1779return shouldAnalyzeCalledOnceImpl(CompletionHandlerWarnings, Diags, At);1780}17811782bool shouldAnalyzeCalledOnceParameters(const DiagnosticsEngine &Diags,1783SourceLocation At) {1784return shouldAnalyzeCalledOnceImpl(CalledOnceWarnings, Diags, At) ||1785shouldAnalyzeCalledOnceConventions(Diags, At);1786}1787} // anonymous namespace17881789//===----------------------------------------------------------------------===//1790// -Wthread-safety1791//===----------------------------------------------------------------------===//1792namespace clang {1793namespace threadSafety {1794namespace {1795class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {1796Sema &S;1797DiagList Warnings;1798SourceLocation FunLocation, FunEndLocation;17991800const FunctionDecl *CurrentFunction;1801bool Verbose;18021803OptionalNotes getNotes() const {1804if (Verbose && CurrentFunction) {1805PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),1806S.PDiag(diag::note_thread_warning_in_fun)1807<< CurrentFunction);1808return OptionalNotes(1, FNote);1809}1810return OptionalNotes();1811}18121813OptionalNotes getNotes(const PartialDiagnosticAt &Note) const {1814OptionalNotes ONS(1, Note);1815if (Verbose && CurrentFunction) {1816PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),1817S.PDiag(diag::note_thread_warning_in_fun)1818<< CurrentFunction);1819ONS.push_back(std::move(FNote));1820}1821return ONS;1822}18231824OptionalNotes getNotes(const PartialDiagnosticAt &Note1,1825const PartialDiagnosticAt &Note2) const {1826OptionalNotes ONS;1827ONS.push_back(Note1);1828ONS.push_back(Note2);1829if (Verbose && CurrentFunction) {1830PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),1831S.PDiag(diag::note_thread_warning_in_fun)1832<< CurrentFunction);1833ONS.push_back(std::move(FNote));1834}1835return ONS;1836}18371838OptionalNotes makeLockedHereNote(SourceLocation LocLocked, StringRef Kind) {1839return LocLocked.isValid()1840? getNotes(PartialDiagnosticAt(1841LocLocked, S.PDiag(diag::note_locked_here) << Kind))1842: getNotes();1843}18441845OptionalNotes makeUnlockedHereNote(SourceLocation LocUnlocked,1846StringRef Kind) {1847return LocUnlocked.isValid()1848? getNotes(PartialDiagnosticAt(1849LocUnlocked, S.PDiag(diag::note_unlocked_here) << Kind))1850: getNotes();1851}18521853public:1854ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL)1855: S(S), FunLocation(FL), FunEndLocation(FEL),1856CurrentFunction(nullptr), Verbose(false) {}18571858void setVerbose(bool b) { Verbose = b; }18591860/// Emit all buffered diagnostics in order of sourcelocation.1861/// We need to output diagnostics produced while iterating through1862/// the lockset in deterministic order, so this function orders diagnostics1863/// and outputs them.1864void emitDiagnostics() {1865Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));1866for (const auto &Diag : Warnings) {1867S.Diag(Diag.first.first, Diag.first.second);1868for (const auto &Note : Diag.second)1869S.Diag(Note.first, Note.second);1870}1871}18721873void handleInvalidLockExp(SourceLocation Loc) override {1874PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock)1875<< Loc);1876Warnings.emplace_back(std::move(Warning), getNotes());1877}18781879void handleUnmatchedUnlock(StringRef Kind, Name LockName, SourceLocation Loc,1880SourceLocation LocPreviousUnlock) override {1881if (Loc.isInvalid())1882Loc = FunLocation;1883PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_but_no_lock)1884<< Kind << LockName);1885Warnings.emplace_back(std::move(Warning),1886makeUnlockedHereNote(LocPreviousUnlock, Kind));1887}18881889void handleIncorrectUnlockKind(StringRef Kind, Name LockName,1890LockKind Expected, LockKind Received,1891SourceLocation LocLocked,1892SourceLocation LocUnlock) override {1893if (LocUnlock.isInvalid())1894LocUnlock = FunLocation;1895PartialDiagnosticAt Warning(1896LocUnlock, S.PDiag(diag::warn_unlock_kind_mismatch)1897<< Kind << LockName << Received << Expected);1898Warnings.emplace_back(std::move(Warning),1899makeLockedHereNote(LocLocked, Kind));1900}19011902void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation LocLocked,1903SourceLocation LocDoubleLock) override {1904if (LocDoubleLock.isInvalid())1905LocDoubleLock = FunLocation;1906PartialDiagnosticAt Warning(LocDoubleLock, S.PDiag(diag::warn_double_lock)1907<< Kind << LockName);1908Warnings.emplace_back(std::move(Warning),1909makeLockedHereNote(LocLocked, Kind));1910}19111912void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,1913SourceLocation LocLocked,1914SourceLocation LocEndOfScope,1915LockErrorKind LEK) override {1916unsigned DiagID = 0;1917switch (LEK) {1918case LEK_LockedSomePredecessors:1919DiagID = diag::warn_lock_some_predecessors;1920break;1921case LEK_LockedSomeLoopIterations:1922DiagID = diag::warn_expecting_lock_held_on_loop;1923break;1924case LEK_LockedAtEndOfFunction:1925DiagID = diag::warn_no_unlock;1926break;1927case LEK_NotLockedAtEndOfFunction:1928DiagID = diag::warn_expecting_locked;1929break;1930}1931if (LocEndOfScope.isInvalid())1932LocEndOfScope = FunEndLocation;19331934PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << Kind1935<< LockName);1936Warnings.emplace_back(std::move(Warning),1937makeLockedHereNote(LocLocked, Kind));1938}19391940void handleExclusiveAndShared(StringRef Kind, Name LockName,1941SourceLocation Loc1,1942SourceLocation Loc2) override {1943PartialDiagnosticAt Warning(Loc1,1944S.PDiag(diag::warn_lock_exclusive_and_shared)1945<< Kind << LockName);1946PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared)1947<< Kind << LockName);1948Warnings.emplace_back(std::move(Warning), getNotes(Note));1949}19501951void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,1952AccessKind AK, SourceLocation Loc) override {1953assert((POK == POK_VarAccess || POK == POK_VarDereference) &&1954"Only works for variables");1955unsigned DiagID = POK == POK_VarAccess?1956diag::warn_variable_requires_any_lock:1957diag::warn_var_deref_requires_any_lock;1958PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)1959<< D << getLockKindFromAccessKind(AK));1960Warnings.emplace_back(std::move(Warning), getNotes());1961}19621963void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,1964ProtectedOperationKind POK, Name LockName,1965LockKind LK, SourceLocation Loc,1966Name *PossibleMatch) override {1967unsigned DiagID = 0;1968if (PossibleMatch) {1969switch (POK) {1970case POK_VarAccess:1971DiagID = diag::warn_variable_requires_lock_precise;1972break;1973case POK_VarDereference:1974DiagID = diag::warn_var_deref_requires_lock_precise;1975break;1976case POK_FunctionCall:1977DiagID = diag::warn_fun_requires_lock_precise;1978break;1979case POK_PassByRef:1980DiagID = diag::warn_guarded_pass_by_reference;1981break;1982case POK_PtPassByRef:1983DiagID = diag::warn_pt_guarded_pass_by_reference;1984break;1985case POK_ReturnByRef:1986DiagID = diag::warn_guarded_return_by_reference;1987break;1988case POK_PtReturnByRef:1989DiagID = diag::warn_pt_guarded_return_by_reference;1990break;1991}1992PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind1993<< D1994<< LockName << LK);1995PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)1996<< *PossibleMatch);1997if (Verbose && POK == POK_VarAccess) {1998PartialDiagnosticAt VNote(D->getLocation(),1999S.PDiag(diag::note_guarded_by_declared_here)2000<< D->getDeclName());2001Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote));2002} else2003Warnings.emplace_back(std::move(Warning), getNotes(Note));2004} else {2005switch (POK) {2006case POK_VarAccess:2007DiagID = diag::warn_variable_requires_lock;2008break;2009case POK_VarDereference:2010DiagID = diag::warn_var_deref_requires_lock;2011break;2012case POK_FunctionCall:2013DiagID = diag::warn_fun_requires_lock;2014break;2015case POK_PassByRef:2016DiagID = diag::warn_guarded_pass_by_reference;2017break;2018case POK_PtPassByRef:2019DiagID = diag::warn_pt_guarded_pass_by_reference;2020break;2021case POK_ReturnByRef:2022DiagID = diag::warn_guarded_return_by_reference;2023break;2024case POK_PtReturnByRef:2025DiagID = diag::warn_pt_guarded_return_by_reference;2026break;2027}2028PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind2029<< D2030<< LockName << LK);2031if (Verbose && POK == POK_VarAccess) {2032PartialDiagnosticAt Note(D->getLocation(),2033S.PDiag(diag::note_guarded_by_declared_here));2034Warnings.emplace_back(std::move(Warning), getNotes(Note));2035} else2036Warnings.emplace_back(std::move(Warning), getNotes());2037}2038}20392040void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,2041SourceLocation Loc) override {2042PartialDiagnosticAt Warning(Loc,2043S.PDiag(diag::warn_acquire_requires_negative_cap)2044<< Kind << LockName << Neg);2045Warnings.emplace_back(std::move(Warning), getNotes());2046}20472048void handleNegativeNotHeld(const NamedDecl *D, Name LockName,2049SourceLocation Loc) override {2050PartialDiagnosticAt Warning(2051Loc, S.PDiag(diag::warn_fun_requires_negative_cap) << D << LockName);2052Warnings.emplace_back(std::move(Warning), getNotes());2053}20542055void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,2056SourceLocation Loc) override {2057PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)2058<< Kind << FunName << LockName);2059Warnings.emplace_back(std::move(Warning), getNotes());2060}20612062void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,2063SourceLocation Loc) override {2064PartialDiagnosticAt Warning(Loc,2065S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);2066Warnings.emplace_back(std::move(Warning), getNotes());2067}20682069void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override {2070PartialDiagnosticAt Warning(Loc,2071S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name);2072Warnings.emplace_back(std::move(Warning), getNotes());2073}20742075void enterFunction(const FunctionDecl* FD) override {2076CurrentFunction = FD;2077}20782079void leaveFunction(const FunctionDecl* FD) override {2080CurrentFunction = nullptr;2081}2082};2083} // anonymous namespace2084} // namespace threadSafety2085} // namespace clang20862087//===----------------------------------------------------------------------===//2088// -Wconsumed2089//===----------------------------------------------------------------------===//20902091namespace clang {2092namespace consumed {2093namespace {2094class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase {20952096Sema &S;2097DiagList Warnings;20982099public:21002101ConsumedWarningsHandler(Sema &S) : S(S) {}21022103void emitDiagnostics() override {2104Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));2105for (const auto &Diag : Warnings) {2106S.Diag(Diag.first.first, Diag.first.second);2107for (const auto &Note : Diag.second)2108S.Diag(Note.first, Note.second);2109}2110}21112112void warnLoopStateMismatch(SourceLocation Loc,2113StringRef VariableName) override {2114PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) <<2115VariableName);21162117Warnings.emplace_back(std::move(Warning), OptionalNotes());2118}21192120void warnParamReturnTypestateMismatch(SourceLocation Loc,2121StringRef VariableName,2122StringRef ExpectedState,2123StringRef ObservedState) override {21242125PartialDiagnosticAt Warning(Loc, S.PDiag(2126diag::warn_param_return_typestate_mismatch) << VariableName <<2127ExpectedState << ObservedState);21282129Warnings.emplace_back(std::move(Warning), OptionalNotes());2130}21312132void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,2133StringRef ObservedState) override {21342135PartialDiagnosticAt Warning(Loc, S.PDiag(2136diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);21372138Warnings.emplace_back(std::move(Warning), OptionalNotes());2139}21402141void warnReturnTypestateForUnconsumableType(SourceLocation Loc,2142StringRef TypeName) override {2143PartialDiagnosticAt Warning(Loc, S.PDiag(2144diag::warn_return_typestate_for_unconsumable_type) << TypeName);21452146Warnings.emplace_back(std::move(Warning), OptionalNotes());2147}21482149void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,2150StringRef ObservedState) override {21512152PartialDiagnosticAt Warning(Loc, S.PDiag(2153diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);21542155Warnings.emplace_back(std::move(Warning), OptionalNotes());2156}21572158void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,2159SourceLocation Loc) override {21602161PartialDiagnosticAt Warning(Loc, S.PDiag(2162diag::warn_use_of_temp_in_invalid_state) << MethodName << State);21632164Warnings.emplace_back(std::move(Warning), OptionalNotes());2165}21662167void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,2168StringRef State, SourceLocation Loc) override {21692170PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<2171MethodName << VariableName << State);21722173Warnings.emplace_back(std::move(Warning), OptionalNotes());2174}2175};2176} // anonymous namespace2177} // namespace consumed2178} // namespace clang21792180//===----------------------------------------------------------------------===//2181// Unsafe buffer usage analysis.2182//===----------------------------------------------------------------------===//21832184namespace {2185class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler {2186Sema &S;2187bool SuggestSuggestions; // Recommend -fsafe-buffer-usage-suggestions?21882189// Lists as a string the names of variables in `VarGroupForVD` except for `VD`2190// itself:2191std::string listVariableGroupAsString(2192const VarDecl *VD, const ArrayRef<const VarDecl *> &VarGroupForVD) const {2193if (VarGroupForVD.size() <= 1)2194return "";21952196std::vector<StringRef> VarNames;2197auto PutInQuotes = [](StringRef S) -> std::string {2198return "'" + S.str() + "'";2199};22002201for (auto *V : VarGroupForVD) {2202if (V == VD)2203continue;2204VarNames.push_back(V->getName());2205}2206if (VarNames.size() == 1) {2207return PutInQuotes(VarNames[0]);2208}2209if (VarNames.size() == 2) {2210return PutInQuotes(VarNames[0]) + " and " + PutInQuotes(VarNames[1]);2211}2212assert(VarGroupForVD.size() > 3);2213const unsigned N = VarNames.size() -22142; // need to print the last two names as "..., X, and Y"2215std::string AllVars = "";22162217for (unsigned I = 0; I < N; ++I)2218AllVars.append(PutInQuotes(VarNames[I]) + ", ");2219AllVars.append(PutInQuotes(VarNames[N]) + ", and " +2220PutInQuotes(VarNames[N + 1]));2221return AllVars;2222}22232224public:2225UnsafeBufferUsageReporter(Sema &S, bool SuggestSuggestions)2226: S(S), SuggestSuggestions(SuggestSuggestions) {}22272228void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl,2229ASTContext &Ctx) override {2230SourceLocation Loc;2231SourceRange Range;2232unsigned MsgParam = 0;2233if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Operation)) {2234Loc = ASE->getBase()->getExprLoc();2235Range = ASE->getBase()->getSourceRange();2236MsgParam = 2;2237} else if (const auto *BO = dyn_cast<BinaryOperator>(Operation)) {2238BinaryOperator::Opcode Op = BO->getOpcode();2239if (Op == BO_Add || Op == BO_AddAssign || Op == BO_Sub ||2240Op == BO_SubAssign) {2241if (BO->getRHS()->getType()->isIntegerType()) {2242Loc = BO->getLHS()->getExprLoc();2243Range = BO->getLHS()->getSourceRange();2244} else {2245Loc = BO->getRHS()->getExprLoc();2246Range = BO->getRHS()->getSourceRange();2247}2248MsgParam = 1;2249}2250} else if (const auto *UO = dyn_cast<UnaryOperator>(Operation)) {2251UnaryOperator::Opcode Op = UO->getOpcode();2252if (Op == UO_PreInc || Op == UO_PreDec || Op == UO_PostInc ||2253Op == UO_PostDec) {2254Loc = UO->getSubExpr()->getExprLoc();2255Range = UO->getSubExpr()->getSourceRange();2256MsgParam = 1;2257}2258} else {2259if (isa<CallExpr>(Operation) || isa<CXXConstructExpr>(Operation)) {2260// note_unsafe_buffer_operation doesn't have this mode yet.2261assert(!IsRelatedToDecl && "Not implemented yet!");2262MsgParam = 3;2263} else if (const auto *ECE = dyn_cast<ExplicitCastExpr>(Operation)) {2264QualType destType = ECE->getType();2265if (!isa<PointerType>(destType))2266return;22672268const uint64_t dSize =2269Ctx.getTypeSize(destType.getTypePtr()->getPointeeType());22702271QualType srcType = ECE->getSubExpr()->getType();2272const uint64_t sSize =2273Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType());2274if (sSize >= dSize)2275return;22762277MsgParam = 4;2278}2279Loc = Operation->getBeginLoc();2280Range = Operation->getSourceRange();2281}2282if (IsRelatedToDecl) {2283assert(!SuggestSuggestions &&2284"Variables blamed for unsafe buffer usage without suggestions!");2285S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range;2286} else {2287S.Diag(Loc, diag::warn_unsafe_buffer_operation) << MsgParam << Range;2288if (SuggestSuggestions) {2289S.Diag(Loc, diag::note_safe_buffer_usage_suggestions_disabled);2290}2291}2292}22932294void handleUnsafeOperationInContainer(const Stmt *Operation,2295bool IsRelatedToDecl,2296ASTContext &Ctx) override {2297SourceLocation Loc;2298SourceRange Range;2299unsigned MsgParam = 0;23002301// This function only handles SpanTwoParamConstructorGadget so far, which2302// always gives a CXXConstructExpr.2303const auto *CtorExpr = cast<CXXConstructExpr>(Operation);2304Loc = CtorExpr->getLocation();23052306S.Diag(Loc, diag::warn_unsafe_buffer_usage_in_container);2307if (IsRelatedToDecl) {2308assert(!SuggestSuggestions &&2309"Variables blamed for unsafe buffer usage without suggestions!");2310S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range;2311}2312}23132314void handleUnsafeVariableGroup(const VarDecl *Variable,2315const VariableGroupsManager &VarGrpMgr,2316FixItList &&Fixes, const Decl *D,2317const FixitStrategy &VarTargetTypes) override {2318assert(!SuggestSuggestions &&2319"Unsafe buffer usage fixits displayed without suggestions!");2320S.Diag(Variable->getLocation(), diag::warn_unsafe_buffer_variable)2321<< Variable << (Variable->getType()->isPointerType() ? 0 : 1)2322<< Variable->getSourceRange();2323if (!Fixes.empty()) {2324assert(isa<NamedDecl>(D) &&2325"Fix-its are generated only for `NamedDecl`s");2326const NamedDecl *ND = cast<NamedDecl>(D);2327bool BriefMsg = false;2328// If the variable group involves parameters, the diagnostic message will2329// NOT explain how the variables are grouped as the reason is non-trivial2330// and irrelavant to users' experience:2331const auto VarGroupForVD = VarGrpMgr.getGroupOfVar(Variable, &BriefMsg);2332unsigned FixItStrategy = 0;2333switch (VarTargetTypes.lookup(Variable)) {2334case clang::FixitStrategy::Kind::Span:2335FixItStrategy = 0;2336break;2337case clang::FixitStrategy::Kind::Array:2338FixItStrategy = 1;2339break;2340default:2341assert(false && "We support only std::span and std::array");2342};23432344const auto &FD =2345S.Diag(Variable->getLocation(),2346BriefMsg ? diag::note_unsafe_buffer_variable_fixit_together2347: diag::note_unsafe_buffer_variable_fixit_group);23482349FD << Variable << FixItStrategy;2350FD << listVariableGroupAsString(Variable, VarGroupForVD)2351<< (VarGroupForVD.size() > 1) << ND;2352for (const auto &F : Fixes) {2353FD << F;2354}2355}23562357#ifndef NDEBUG2358if (areDebugNotesRequested())2359for (const DebugNote &Note: DebugNotesByVar[Variable])2360S.Diag(Note.first, diag::note_safe_buffer_debug_mode) << Note.second;2361#endif2362}23632364bool isSafeBufferOptOut(const SourceLocation &Loc) const override {2365return S.PP.isSafeBufferOptOut(S.getSourceManager(), Loc);2366}23672368bool ignoreUnsafeBufferInContainer(const SourceLocation &Loc) const override {2369return S.Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container, Loc);2370}23712372// Returns the text representation of clang::unsafe_buffer_usage attribute.2373// `WSSuffix` holds customized "white-space"s, e.g., newline or whilespace2374// characters.2375std::string2376getUnsafeBufferUsageAttributeTextAt(SourceLocation Loc,2377StringRef WSSuffix = "") const override {2378Preprocessor &PP = S.getPreprocessor();2379TokenValue ClangUnsafeBufferUsageTokens[] = {2380tok::l_square,2381tok::l_square,2382PP.getIdentifierInfo("clang"),2383tok::coloncolon,2384PP.getIdentifierInfo("unsafe_buffer_usage"),2385tok::r_square,2386tok::r_square};23872388StringRef MacroName;23892390// The returned macro (it returns) is guaranteed not to be function-like:2391MacroName = PP.getLastMacroWithSpelling(Loc, ClangUnsafeBufferUsageTokens);2392if (MacroName.empty())2393MacroName = "[[clang::unsafe_buffer_usage]]";2394return MacroName.str() + WSSuffix.str();2395}2396};2397} // namespace23982399//===----------------------------------------------------------------------===//2400// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based2401// warnings on a function, method, or block.2402//===----------------------------------------------------------------------===//24032404sema::AnalysisBasedWarnings::Policy::Policy() {2405enableCheckFallThrough = 1;2406enableCheckUnreachable = 0;2407enableThreadSafetyAnalysis = 0;2408enableConsumedAnalysis = 0;2409}24102411/// InterProceduralData aims to be a storage of whatever data should be passed2412/// between analyses of different functions.2413///2414/// At the moment, its primary goal is to make the information gathered during2415/// the analysis of the blocks available during the analysis of the enclosing2416/// function. This is important due to the fact that blocks are analyzed before2417/// the enclosed function is even parsed fully, so it is not viable to access2418/// anything in the outer scope while analyzing the block. On the other hand,2419/// re-building CFG for blocks and re-analyzing them when we do have all the2420/// information (i.e. during the analysis of the enclosing function) seems to be2421/// ill-designed.2422class sema::AnalysisBasedWarnings::InterProceduralData {2423public:2424// It is important to analyze blocks within functions because it's a very2425// common pattern to capture completion handler parameters by blocks.2426CalledOnceInterProceduralData CalledOnceData;2427};24282429static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag) {2430return (unsigned)!D.isIgnored(diag, SourceLocation());2431}24322433sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)2434: S(s), IPData(std::make_unique<InterProceduralData>()),2435NumFunctionsAnalyzed(0), NumFunctionsWithBadCFGs(0), NumCFGBlocks(0),2436MaxCFGBlocksPerFunction(0), NumUninitAnalysisFunctions(0),2437NumUninitAnalysisVariables(0), MaxUninitAnalysisVariablesPerFunction(0),2438NumUninitAnalysisBlockVisits(0),2439MaxUninitAnalysisBlockVisitsPerFunction(0) {24402441using namespace diag;2442DiagnosticsEngine &D = S.getDiagnostics();24432444DefaultPolicy.enableCheckUnreachable =2445isEnabled(D, warn_unreachable) || isEnabled(D, warn_unreachable_break) ||2446isEnabled(D, warn_unreachable_return) ||2447isEnabled(D, warn_unreachable_loop_increment);24482449DefaultPolicy.enableThreadSafetyAnalysis = isEnabled(D, warn_double_lock);24502451DefaultPolicy.enableConsumedAnalysis =2452isEnabled(D, warn_use_in_invalid_state);2453}24542455// We need this here for unique_ptr with forward declared class.2456sema::AnalysisBasedWarnings::~AnalysisBasedWarnings() = default;24572458static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {2459for (const auto &D : fscope->PossiblyUnreachableDiags)2460S.Diag(D.Loc, D.PD);2461}24622463// An AST Visitor that calls a callback function on each callable DEFINITION2464// that is NOT in a dependent context:2465class CallableVisitor : public RecursiveASTVisitor<CallableVisitor> {2466private:2467llvm::function_ref<void(const Decl *)> Callback;24682469public:2470CallableVisitor(llvm::function_ref<void(const Decl *)> Callback)2471: Callback(Callback) {}24722473bool VisitFunctionDecl(FunctionDecl *Node) {2474if (cast<DeclContext>(Node)->isDependentContext())2475return true; // Not to analyze dependent decl2476// `FunctionDecl->hasBody()` returns true if the function has a body2477// somewhere defined. But we want to know if this `Node` has a body2478// child. So we use `doesThisDeclarationHaveABody`:2479if (Node->doesThisDeclarationHaveABody())2480Callback(Node);2481return true;2482}24832484bool VisitBlockDecl(BlockDecl *Node) {2485if (cast<DeclContext>(Node)->isDependentContext())2486return true; // Not to analyze dependent decl2487Callback(Node);2488return true;2489}24902491bool VisitObjCMethodDecl(ObjCMethodDecl *Node) {2492if (cast<DeclContext>(Node)->isDependentContext())2493return true; // Not to analyze dependent decl2494if (Node->hasBody())2495Callback(Node);2496return true;2497}24982499bool VisitLambdaExpr(LambdaExpr *Node) {2500return VisitFunctionDecl(Node->getCallOperator());2501}25022503bool shouldVisitTemplateInstantiations() const { return true; }2504bool shouldVisitImplicitCode() const { return false; }2505};25062507void clang::sema::AnalysisBasedWarnings::IssueWarnings(2508TranslationUnitDecl *TU) {2509if (!TU)2510return; // This is unexpected, give up quietly.25112512DiagnosticsEngine &Diags = S.getDiagnostics();25132514if (S.hasUncompilableErrorOccurred() || Diags.getIgnoreAllWarnings())2515// exit if having uncompilable errors or ignoring all warnings:2516return;25172518DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();25192520// UnsafeBufferUsage analysis settings.2521bool UnsafeBufferUsageCanEmitSuggestions = S.getLangOpts().CPlusPlus20;2522bool UnsafeBufferUsageShouldEmitSuggestions = // Should != Can.2523UnsafeBufferUsageCanEmitSuggestions &&2524DiagOpts.ShowSafeBufferUsageSuggestions;2525bool UnsafeBufferUsageShouldSuggestSuggestions =2526UnsafeBufferUsageCanEmitSuggestions &&2527!DiagOpts.ShowSafeBufferUsageSuggestions;2528UnsafeBufferUsageReporter R(S, UnsafeBufferUsageShouldSuggestSuggestions);25292530// The Callback function that performs analyses:2531auto CallAnalyzers = [&](const Decl *Node) -> void {2532// Perform unsafe buffer usage analysis:2533if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation,2534Node->getBeginLoc()) ||2535!Diags.isIgnored(diag::warn_unsafe_buffer_variable,2536Node->getBeginLoc()) ||2537!Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container,2538Node->getBeginLoc())) {2539clang::checkUnsafeBufferUsage(Node, R,2540UnsafeBufferUsageShouldEmitSuggestions);2541}25422543// More analysis ...2544};2545// Emit per-function analysis-based warnings that require the whole-TU2546// reasoning. Check if any of them is enabled at all before scanning the AST:2547if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation, SourceLocation()) ||2548!Diags.isIgnored(diag::warn_unsafe_buffer_variable, SourceLocation()) ||2549!Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container,2550SourceLocation())) {2551CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU);2552}2553}25542555void clang::sema::AnalysisBasedWarnings::IssueWarnings(2556sema::AnalysisBasedWarnings::Policy P, sema::FunctionScopeInfo *fscope,2557const Decl *D, QualType BlockType) {25582559// We avoid doing analysis-based warnings when there are errors for2560// two reasons:2561// (1) The CFGs often can't be constructed (if the body is invalid), so2562// don't bother trying.2563// (2) The code already has problems; running the analysis just takes more2564// time.2565DiagnosticsEngine &Diags = S.getDiagnostics();25662567// Do not do any analysis if we are going to just ignore them.2568if (Diags.getIgnoreAllWarnings() ||2569(Diags.getSuppressSystemWarnings() &&2570S.SourceMgr.isInSystemHeader(D->getLocation())))2571return;25722573// For code in dependent contexts, we'll do this at instantiation time.2574if (cast<DeclContext>(D)->isDependentContext())2575return;25762577if (S.hasUncompilableErrorOccurred()) {2578// Flush out any possibly unreachable diagnostics.2579flushDiagnostics(S, fscope);2580return;2581}25822583const Stmt *Body = D->getBody();2584assert(Body);25852586// Construct the analysis context with the specified CFG build options.2587AnalysisDeclContext AC(/* AnalysisDeclContextManager */ nullptr, D);25882589// Don't generate EH edges for CallExprs as we'd like to avoid the n^22590// explosion for destructors that can result and the compile time hit.2591AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true;2592AC.getCFGBuildOptions().AddEHEdges = false;2593AC.getCFGBuildOptions().AddInitializers = true;2594AC.getCFGBuildOptions().AddImplicitDtors = true;2595AC.getCFGBuildOptions().AddTemporaryDtors = true;2596AC.getCFGBuildOptions().AddCXXNewAllocator = false;2597AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true;25982599// Force that certain expressions appear as CFGElements in the CFG. This2600// is used to speed up various analyses.2601// FIXME: This isn't the right factoring. This is here for initial2602// prototyping, but we need a way for analyses to say what expressions they2603// expect to always be CFGElements and then fill in the BuildOptions2604// appropriately. This is essentially a layering violation.2605if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||2606P.enableConsumedAnalysis) {2607// Unreachable code analysis and thread safety require a linearized CFG.2608AC.getCFGBuildOptions().setAllAlwaysAdd();2609}2610else {2611AC.getCFGBuildOptions()2612.setAlwaysAdd(Stmt::BinaryOperatorClass)2613.setAlwaysAdd(Stmt::CompoundAssignOperatorClass)2614.setAlwaysAdd(Stmt::BlockExprClass)2615.setAlwaysAdd(Stmt::CStyleCastExprClass)2616.setAlwaysAdd(Stmt::DeclRefExprClass)2617.setAlwaysAdd(Stmt::ImplicitCastExprClass)2618.setAlwaysAdd(Stmt::UnaryOperatorClass);2619}26202621// Install the logical handler.2622std::optional<LogicalErrorHandler> LEH;2623if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {2624LEH.emplace(S);2625AC.getCFGBuildOptions().Observer = &*LEH;2626}26272628// Emit delayed diagnostics.2629if (!fscope->PossiblyUnreachableDiags.empty()) {2630bool analyzed = false;26312632// Register the expressions with the CFGBuilder.2633for (const auto &D : fscope->PossiblyUnreachableDiags) {2634for (const Stmt *S : D.Stmts)2635AC.registerForcedBlockExpression(S);2636}26372638if (AC.getCFG()) {2639analyzed = true;2640for (const auto &D : fscope->PossiblyUnreachableDiags) {2641bool AllReachable = true;2642for (const Stmt *S : D.Stmts) {2643const CFGBlock *block = AC.getBlockForRegisteredExpression(S);2644CFGReverseBlockReachabilityAnalysis *cra =2645AC.getCFGReachablityAnalysis();2646// FIXME: We should be able to assert that block is non-null, but2647// the CFG analysis can skip potentially-evaluated expressions in2648// edge cases; see test/Sema/vla-2.c.2649if (block && cra) {2650// Can this block be reached from the entrance?2651if (!cra->isReachable(&AC.getCFG()->getEntry(), block)) {2652AllReachable = false;2653break;2654}2655}2656// If we cannot map to a basic block, assume the statement is2657// reachable.2658}26592660if (AllReachable)2661S.Diag(D.Loc, D.PD);2662}2663}26642665if (!analyzed)2666flushDiagnostics(S, fscope);2667}26682669// Warning: check missing 'return'2670if (P.enableCheckFallThrough) {2671const CheckFallThroughDiagnostics &CD =2672(isa<BlockDecl>(D)2673? CheckFallThroughDiagnostics::MakeForBlock()2674: (isa<CXXMethodDecl>(D) &&2675cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&2676cast<CXXMethodDecl>(D)->getParent()->isLambda())2677? CheckFallThroughDiagnostics::MakeForLambda()2678: (fscope->isCoroutine()2679? CheckFallThroughDiagnostics::MakeForCoroutine(D)2680: CheckFallThroughDiagnostics::MakeForFunction(D)));2681CheckFallThroughForBody(S, D, Body, BlockType, CD, AC, fscope);2682}26832684// Warning: check for unreachable code2685if (P.enableCheckUnreachable) {2686// Only check for unreachable code on non-template instantiations.2687// Different template instantiations can effectively change the control-flow2688// and it is very difficult to prove that a snippet of code in a template2689// is unreachable for all instantiations.2690bool isTemplateInstantiation = false;2691if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))2692isTemplateInstantiation = Function->isTemplateInstantiation();2693if (!isTemplateInstantiation)2694CheckUnreachable(S, AC);2695}26962697// Check for thread safety violations2698if (P.enableThreadSafetyAnalysis) {2699SourceLocation FL = AC.getDecl()->getLocation();2700SourceLocation FEL = AC.getDecl()->getEndLoc();2701threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);2702if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getBeginLoc()))2703Reporter.setIssueBetaWarnings(true);2704if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getBeginLoc()))2705Reporter.setVerbose(true);27062707threadSafety::runThreadSafetyAnalysis(AC, Reporter,2708&S.ThreadSafetyDeclCache);2709Reporter.emitDiagnostics();2710}27112712// Check for violations of consumed properties.2713if (P.enableConsumedAnalysis) {2714consumed::ConsumedWarningsHandler WarningHandler(S);2715consumed::ConsumedAnalyzer Analyzer(WarningHandler);2716Analyzer.run(AC);2717}27182719if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||2720!Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||2721!Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc()) ||2722!Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc())) {2723if (CFG *cfg = AC.getCFG()) {2724UninitValsDiagReporter reporter(S);2725UninitVariablesAnalysisStats stats;2726std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats));2727runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,2728reporter, stats);27292730if (S.CollectStats && stats.NumVariablesAnalyzed > 0) {2731++NumUninitAnalysisFunctions;2732NumUninitAnalysisVariables += stats.NumVariablesAnalyzed;2733NumUninitAnalysisBlockVisits += stats.NumBlockVisits;2734MaxUninitAnalysisVariablesPerFunction =2735std::max(MaxUninitAnalysisVariablesPerFunction,2736stats.NumVariablesAnalyzed);2737MaxUninitAnalysisBlockVisitsPerFunction =2738std::max(MaxUninitAnalysisBlockVisitsPerFunction,2739stats.NumBlockVisits);2740}2741}2742}27432744// Check for violations of "called once" parameter properties.2745if (S.getLangOpts().ObjC && !S.getLangOpts().CPlusPlus &&2746shouldAnalyzeCalledOnceParameters(Diags, D->getBeginLoc())) {2747if (AC.getCFG()) {2748CalledOnceCheckReporter Reporter(S, IPData->CalledOnceData);2749checkCalledOnceParameters(2750AC, Reporter,2751shouldAnalyzeCalledOnceConventions(Diags, D->getBeginLoc()));2752}2753}27542755bool FallThroughDiagFull =2756!Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc());2757bool FallThroughDiagPerFunction = !Diags.isIgnored(2758diag::warn_unannotated_fallthrough_per_function, D->getBeginLoc());2759if (FallThroughDiagFull || FallThroughDiagPerFunction ||2760fscope->HasFallthroughStmt) {2761DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);2762}27632764if (S.getLangOpts().ObjCWeak &&2765!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getBeginLoc()))2766diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());276727682769// Check for infinite self-recursion in functions2770if (!Diags.isIgnored(diag::warn_infinite_recursive_function,2771D->getBeginLoc())) {2772if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {2773checkRecursiveFunction(S, FD, Body, AC);2774}2775}27762777// Check for throw out of non-throwing function.2778if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getBeginLoc()))2779if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))2780if (S.getLangOpts().CPlusPlus && !fscope->isCoroutine() && isNoexcept(FD))2781checkThrowInNonThrowingFunc(S, FD, AC);27822783// If none of the previous checks caused a CFG build, trigger one here2784// for the logical error handler.2785if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {2786AC.getCFG();2787}27882789// Collect statistics about the CFG if it was built.2790if (S.CollectStats && AC.isCFGBuilt()) {2791++NumFunctionsAnalyzed;2792if (CFG *cfg = AC.getCFG()) {2793// If we successfully built a CFG for this context, record some more2794// detail information about it.2795NumCFGBlocks += cfg->getNumBlockIDs();2796MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,2797cfg->getNumBlockIDs());2798} else {2799++NumFunctionsWithBadCFGs;2800}2801}2802}28032804void clang::sema::AnalysisBasedWarnings::PrintStats() const {2805llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";28062807unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;2808unsigned AvgCFGBlocksPerFunction =2809!NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;2810llvm::errs() << NumFunctionsAnalyzed << " functions analyzed ("2811<< NumFunctionsWithBadCFGs << " w/o CFGs).\n"2812<< " " << NumCFGBlocks << " CFG blocks built.\n"2813<< " " << AvgCFGBlocksPerFunction2814<< " average CFG blocks per function.\n"2815<< " " << MaxCFGBlocksPerFunction2816<< " max CFG blocks per function.\n";28172818unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 02819: NumUninitAnalysisVariables/NumUninitAnalysisFunctions;2820unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 02821: NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;2822llvm::errs() << NumUninitAnalysisFunctions2823<< " functions analyzed for uninitialiazed variables\n"2824<< " " << NumUninitAnalysisVariables << " variables analyzed.\n"2825<< " " << AvgUninitVariablesPerFunction2826<< " average variables per function.\n"2827<< " " << MaxUninitAnalysisVariablesPerFunction2828<< " max variables per function.\n"2829<< " " << NumUninitAnalysisBlockVisits << " block visits.\n"2830<< " " << AvgUninitBlockVisitsPerFunction2831<< " average block visits per function.\n"2832<< " " << MaxUninitAnalysisBlockVisitsPerFunction2833<< " max block visits per function.\n";2834}283528362837