43#include "llvm/ADT/ArrayRef.h"
44#include "llvm/ADT/BitVector.h"
45#include "llvm/ADT/MapVector.h"
46#include "llvm/ADT/SmallString.h"
47#include "llvm/ADT/SmallVector.h"
48#include "llvm/ADT/StringRef.h"
49#include "llvm/Support/Casting.h"
67 UnreachableCodeHandler(
Sema &
s) : S(
s) {}
76 if (PreviousSilenceableCondVal.
isValid() &&
78 PreviousSilenceableCondVal == SilenceableCondVal)
80 PreviousSilenceableCondVal = SilenceableCondVal;
82 unsigned diag = diag::warn_unreachable;
85 diag = diag::warn_unreachable_break;
88 diag = diag::warn_unreachable_return;
91 diag = diag::warn_unreachable_loop_increment;
97 S.
Diag(L, diag) << R1 << R2;
100 if (
Open.isValid()) {
104 S.
Diag(
Open, diag::note_unreachable_silence)
125 UnreachableCodeHandler UC(S);
135 LogicalErrorHandler(
Sema &S) : S(S) {}
137 static bool HasMacroID(
const Expr *E) {
143 if (
const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
144 if (HasMacroID(SubExpr))
155 S.
Diag(B->
getExprLoc(), diag::warn_tautological_overlap_comparison)
156 << DiagRange << isAlwaysTrue;
160 bool isAlwaysTrue)
override {
166 << DiagRange << isAlwaysTrue;
174 S.
Diag(B->
getExprLoc(), diag::warn_comparison_bitwise_or) << DiagRange;
179 return !Diags.
isIgnored(diag::warn_tautological_overlap_comparison, Loc) ||
180 !Diags.
isIgnored(diag::warn_comparison_bitwise_or, Loc);
194 for (
const auto &B :
Block) {
208 isa<TemplateSpecializationType>(NNS->getAsType())) {
227 bool foundRecursion =
false;
232 WorkList.push_back(&cfg->
getEntry());
234 while (!WorkList.empty()) {
237 for (
auto I =
Block->succ_begin(), E =
Block->succ_end(); I != E; ++I) {
239 if (!Visited.insert(SuccBlock).second)
243 if (ExitID == SuccBlock->getBlockID())
248 foundRecursion =
true;
252 WorkList.push_back(SuccBlock);
256 return foundRecursion;
292 Stack.push_back(&ThrowBlock);
295 while (!Stack.empty()) {
296 CFGBlock &UnwindBlock = *Stack.back();
299 for (
auto &Succ : UnwindBlock.
succs()) {
300 if (!Succ.isReachable() || Queued[Succ->getBlockID()])
307 dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
308 QualType Caught = Catch->getCaughtType();
315 Stack.push_back(Succ);
316 Queued[Succ->getBlockID()] =
true;
330 if (!Reachable[B->getBlockID()])
333 std::optional<CFGStmt> S = E.getAs<
CFGStmt>();
336 if (
auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
346 S.
Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
348 (isa<CXXDestructorDecl>(FD) ||
352 getAs<FunctionProtoType>())
354 << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
377 if (FPT->isNothrow() || FD->
hasAttr<NoThrowAttr>())
418 for (
const auto *B : *cfg) {
419 if (!live[B->getBlockID()]) {
420 if (B->pred_begin() == B->pred_end()) {
421 const Stmt *Term = B->getTerminatorStmt();
422 if (Term && isa<CXXTryStmt>(Term))
434 bool HasLiveReturn =
false;
435 bool HasFakeEdge =
false;
436 bool HasPlainEdge =
false;
437 bool HasAbnormalEdge =
false;
455 HasAbnormalEdge =
true;
464 for ( ; ri != re ; ++ri)
471 if (Term && (isa<CXXTryStmt>(Term) || isa<ObjCAtTryStmt>(Term))) {
472 HasAbnormalEdge =
true;
482 if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
483 HasLiveReturn =
true;
486 if (isa<ObjCAtThrowStmt>(S)) {
490 if (isa<CXXThrowExpr>(S)) {
494 if (isa<MSAsmStmt>(S)) {
497 HasLiveReturn =
true;
500 if (isa<CXXTryStmt>(S)) {
501 HasAbnormalEdge =
true;
505 HasAbnormalEdge =
true;
516 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
526struct CheckFallThroughDiagnostics {
527 unsigned diag_MaybeFallThrough_HasNoReturn;
528 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
529 unsigned diag_AlwaysFallThrough_HasNoReturn;
530 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
531 unsigned diag_NeverFallThroughOrReturn;
535 static CheckFallThroughDiagnostics MakeForFunction(
const Decl *Func) {
536 CheckFallThroughDiagnostics D;
538 D.diag_MaybeFallThrough_HasNoReturn =
539 diag::warn_falloff_noreturn_function;
540 D.diag_MaybeFallThrough_ReturnsNonVoid =
541 diag::warn_maybe_falloff_nonvoid_function;
542 D.diag_AlwaysFallThrough_HasNoReturn =
543 diag::warn_falloff_noreturn_function;
544 D.diag_AlwaysFallThrough_ReturnsNonVoid =
545 diag::warn_falloff_nonvoid_function;
549 bool isVirtualMethod =
false;
550 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
551 isVirtualMethod = Method->isVirtual();
555 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
559 D.diag_NeverFallThroughOrReturn =
560 diag::warn_suggest_noreturn_function;
562 D.diag_NeverFallThroughOrReturn = 0;
568 static CheckFallThroughDiagnostics MakeForCoroutine(
const Decl *Func) {
569 CheckFallThroughDiagnostics D;
571 D.diag_MaybeFallThrough_HasNoReturn = 0;
572 D.diag_MaybeFallThrough_ReturnsNonVoid =
573 diag::warn_maybe_falloff_nonvoid_coroutine;
574 D.diag_AlwaysFallThrough_HasNoReturn = 0;
575 D.diag_AlwaysFallThrough_ReturnsNonVoid =
576 diag::warn_falloff_nonvoid_coroutine;
577 D.funMode = Coroutine;
581 static CheckFallThroughDiagnostics MakeForBlock() {
582 CheckFallThroughDiagnostics D;
583 D.diag_MaybeFallThrough_HasNoReturn =
584 diag::err_noreturn_block_has_return_expr;
585 D.diag_MaybeFallThrough_ReturnsNonVoid =
586 diag::err_maybe_falloff_nonvoid_block;
587 D.diag_AlwaysFallThrough_HasNoReturn =
588 diag::err_noreturn_block_has_return_expr;
589 D.diag_AlwaysFallThrough_ReturnsNonVoid =
590 diag::err_falloff_nonvoid_block;
591 D.diag_NeverFallThroughOrReturn = 0;
596 static CheckFallThroughDiagnostics MakeForLambda() {
597 CheckFallThroughDiagnostics D;
598 D.diag_MaybeFallThrough_HasNoReturn =
599 diag::err_noreturn_lambda_has_return_expr;
600 D.diag_MaybeFallThrough_ReturnsNonVoid =
601 diag::warn_maybe_falloff_nonvoid_lambda;
602 D.diag_AlwaysFallThrough_HasNoReturn =
603 diag::err_noreturn_lambda_has_return_expr;
604 D.diag_AlwaysFallThrough_ReturnsNonVoid =
605 diag::warn_falloff_nonvoid_lambda;
606 D.diag_NeverFallThroughOrReturn = 0;
612 bool HasNoReturn)
const {
613 if (funMode == Function) {
614 return (ReturnsVoid ||
615 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function,
618 D.
isIgnored(diag::warn_noreturn_function_has_return_expr,
621 D.
isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
623 if (funMode == Coroutine) {
624 return (ReturnsVoid ||
625 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
626 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
631 return ReturnsVoid && !HasNoReturn;
643 const CheckFallThroughDiagnostics &CD,
647 bool ReturnsVoid =
false;
648 bool HasNoReturn =
false;
651 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
652 if (
const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
653 ReturnsVoid = CBody->getFallthroughHandler() !=
nullptr;
655 ReturnsVoid = FD->getReturnType()->isVoidType();
656 HasNoReturn = FD->isNoReturn();
658 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
659 ReturnsVoid = MD->getReturnType()->isVoidType();
660 HasNoReturn = MD->hasAttr<NoReturnAttr>();
662 else if (isa<BlockDecl>(D)) {
665 if (FT->getReturnType()->isVoidType())
667 if (FT->getNoReturnAttr())
675 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
696 EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
697 else if (!ReturnsVoid)
698 EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
702 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
703 else if (!ReturnsVoid)
704 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
707 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
708 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
709 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
710 }
else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
711 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
713 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
738 : Inherited(Context), FoundReference(
false), Needle(Needle) {}
740 void VisitExpr(
const Expr *E) {
745 Inherited::VisitExpr(E);
750 FoundReference =
true;
755 bool doesContainReference()
const {
return FoundReference; }
763 S.
Diag(VD->
getLocation(), diag::note_block_var_fixit_add_initialization)
784 S.
Diag(Loc, diag::note_var_fixit_add_initialization) << VD->
getDeclName()
792 const Stmt *Else,
bool CondVal,
816 bool IsCapturedByBlock) {
817 bool Diagnosed =
false;
850 const Stmt *Term = I->Terminator;
860 int RemoveDiagKind = -1;
861 const char *FixitStr =
862 S.
getLangOpts().CPlusPlus ? (I->Output ?
"true" :
"false")
863 : (I->Output ?
"1" :
"0");
866 switch (Term ? Term->
getStmtClass() : Stmt::DeclStmtClass) {
873 case Stmt::IfStmtClass: {
874 const IfStmt *IS = cast<IfStmt>(Term);
880 I->Output, Fixit1, Fixit2);
883 case Stmt::ConditionalOperatorClass: {
890 I->Output, Fixit1, Fixit2);
893 case Stmt::BinaryOperatorClass: {
901 if ((BO->
getOpcode() == BO_LAnd && I->Output) ||
902 (BO->
getOpcode() == BO_LOr && !I->Output))
913 case Stmt::WhileStmtClass:
916 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
920 case Stmt::ForStmtClass:
923 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
930 case Stmt::CXXForRangeStmtClass:
931 if (I->Output == 1) {
939 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
943 case Stmt::DoStmtClass:
946 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
952 case Stmt::CaseStmtClass:
955 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
957 case Stmt::DefaultStmtClass:
960 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
964 S.
Diag(Range.getBegin(), diag::warn_sometimes_uninit_var)
965 << VD->
getDeclName() << IsCapturedByBlock << DiagKind
966 << Str << I->Output << Range;
969 if (RemoveDiagKind != -1)
971 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
997 bool alwaysReportSelfInit =
false) {
1011 if (!alwaysReportSelfInit && DRE ==
Initializer->IgnoreParenImpCasts())
1014 ContainsReference CR(S.
Context, DRE);
1016 if (CR.doesContainReference()) {
1017 S.
Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
1028 diag::warn_uninit_byref_blockvar_captured_by_block)
1048 FallthroughMapper(
Sema &S)
1049 : FoundSwitchStatements(
false),
1053 bool foundSwitchStatements()
const {
return FoundSwitchStatements; }
1056 bool Found = FallthroughStmts.erase(
Stmt);
1063 const AttrStmts &getFallthroughStmts()
const {
1064 return FallthroughStmts;
1067 void fillReachableBlocks(
CFG *Cfg) {
1068 assert(ReachableBlocks.empty() &&
"ReachableBlocks already filled");
1069 std::deque<const CFGBlock *> BlockQueue;
1071 ReachableBlocks.insert(&Cfg->
getEntry());
1072 BlockQueue.push_back(&Cfg->
getEntry());
1077 for (
const auto *B : *Cfg) {
1078 const Stmt *L = B->getLabel();
1079 if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1080 BlockQueue.push_back(B);
1083 while (!BlockQueue.empty()) {
1085 BlockQueue.pop_front();
1087 if (B && ReachableBlocks.insert(B).second)
1088 BlockQueue.push_back(B);
1093 bool checkFallThroughIntoBlock(
const CFGBlock &B,
int &AnnotatedCnt,
1094 bool IsTemplateInstantiation) {
1095 assert(!ReachableBlocks.empty() &&
"ReachableBlocks empty");
1097 int UnannotatedCnt = 0;
1101 while (!BlockQueue.empty()) {
1103 BlockQueue.pop_front();
1106 const Stmt *Term =
P->getTerminatorStmt();
1107 if (Term && isa<SwitchStmt>(Term))
1110 const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(
P->getLabel());
1114 const LabelStmt *L = dyn_cast_or_null<LabelStmt>(
P->getLabel());
1118 if (!ReachableBlocks.count(
P)) {
1119 for (
const CFGElement &Elem : llvm::reverse(*
P)) {
1120 if (std::optional<CFGStmt> CS = Elem.getAs<
CFGStmt>()) {
1121 if (
const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1125 if (!IsTemplateInstantiation)
1126 S.
Diag(AS->getBeginLoc(),
1127 diag::warn_unreachable_fallthrough_attr);
1128 markFallthroughVisited(AS);
1148 markFallthroughVisited(AS);
1155 std::copy(
P->pred_begin(),
P->pred_end(),
1156 std::back_inserter(BlockQueue));
1162 return !!UnannotatedCnt;
1169 if (asFallThroughAttr(S))
1170 FallthroughStmts.insert(S);
1175 FoundSwitchStatements =
true;
1186 for (
const auto C : zip(
LE->captures(),
LE->capture_inits()))
1194 if (
const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1195 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1204 for (
const CFGElement &Elem : llvm::reverse(B))
1205 if (std::optional<CFGStmt> CS = Elem.getAs<
CFGStmt>())
1206 return CS->getStmt();
1217 bool FoundSwitchStatements;
1218 AttrStmts FallthroughStmts;
1227 tok::l_square, tok::l_square,
1229 tok::r_square, tok::r_square
1235 tok::r_square, tok::r_square
1240 StringRef MacroName;
1241 if (PreferClangAttr)
1243 if (MacroName.empty())
1245 if (MacroName.empty() && !PreferClangAttr)
1247 if (MacroName.empty()) {
1248 if (!PreferClangAttr)
1249 MacroName =
"[[fallthrough]]";
1251 MacroName =
"[[clang::fallthrough]]";
1253 MacroName =
"__attribute__((fallthrough))";
1260 FallthroughMapper FM(S);
1261 FM.TraverseStmt(AC.
getBody());
1263 if (!FM.foundSwitchStatements())
1266 if (PerFunction && FM.getFallthroughStmts().empty())
1274 FM.fillReachableBlocks(Cfg);
1276 for (
const CFGBlock *B : llvm::reverse(*Cfg)) {
1279 if (!isa_and_nonnull<SwitchCase>(
Label))
1284 bool IsTemplateInstantiation =
false;
1286 IsTemplateInstantiation = Function->isTemplateInstantiation();
1287 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1288 IsTemplateInstantiation))
1292 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1293 : diag::warn_unannotated_fallthrough);
1295 if (!AnnotatedCnt) {
1306 if (!(B->
empty() && Term && isa<BreakStmt>(Term))) {
1310 TextToInsert +=
"; ";
1311 S.
Diag(L, diag::note_insert_fallthrough_fixit)
1312 << AnnotationSpelling
1315 S.
Diag(L, diag::note_insert_break_fixit)
1320 for (
const auto *F : FM.getFallthroughStmts())
1321 S.
Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);
1329 switch (S->getStmtClass()) {
1330 case Stmt::ForStmtClass:
1331 case Stmt::WhileStmtClass:
1332 case Stmt::CXXForRangeStmtClass:
1333 case Stmt::ObjCForCollectionStmtClass:
1335 case Stmt::DoStmtClass: {
1337 if (!cast<DoStmt>(S)->getCond()->
EvaluateAsInt(Result, Ctx))
1339 return Result.Val.getInt().getBoolValue();
1356 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1365 for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
1367 const WeakUseVector &Uses = I->second;
1370 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1371 for ( ; UI != UE; ++UI) {
1384 if (UI == Uses.begin()) {
1385 WeakUseVector::const_iterator UI2 = UI;
1386 for (++UI2; UI2 != UE; ++UI2)
1387 if (UI2->isUnsafe())
1391 if (!
isInLoop(Ctx, PM, UI->getUseExpr()))
1394 const WeakObjectProfileTy &Profile = I->first;
1395 if (!Profile.isExactProfile())
1400 Base = Profile.getProperty();
1401 assert(
Base &&
"A profile always has a base or property.");
1403 if (
const VarDecl *BaseVar = dyn_cast<VarDecl>(
Base))
1404 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(
Base))
1409 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
1412 if (UsesByStmt.empty())
1417 llvm::sort(UsesByStmt,
1418 [&
SM](
const StmtUsesPair &LHS,
const StmtUsesPair &RHS) {
1420 RHS.first->getBeginLoc());
1435 if (isa<sema::BlockScopeInfo>(CurFn))
1436 FunctionKind =
Block;
1437 else if (isa<sema::LambdaScopeInfo>(CurFn))
1438 FunctionKind = Lambda;
1439 else if (isa<ObjCMethodDecl>(D))
1440 FunctionKind = Method;
1442 FunctionKind = Function;
1445 for (
const auto &
P : UsesByStmt) {
1446 const Stmt *FirstRead =
P.first;
1447 const WeakObjectProfileTy &Key =
P.second->first;
1448 const WeakUseVector &Uses =
P.second->second;
1456 if (Key.isExactProfile())
1457 DiagKind = diag::warn_arc_repeated_use_of_weak;
1459 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1471 const NamedDecl *KeyProp = Key.getProperty();
1472 if (isa<VarDecl>(KeyProp))
1473 ObjectKind = Variable;
1474 else if (isa<ObjCPropertyDecl>(KeyProp))
1476 else if (isa<ObjCMethodDecl>(KeyProp))
1477 ObjectKind = ImplicitProperty;
1478 else if (isa<ObjCIvarDecl>(KeyProp))
1481 llvm_unreachable(
"Unexpected weak object kind!");
1486 if (Prop->hasAttr<IBOutletAttr>())
1491 <<
int(ObjectKind) << KeyProp <<
int(FunctionKind)
1495 for (
const auto &Use : Uses) {
1496 if (Use.getUseExpr() == FirstRead)
1498 S.
Diag(Use.getUseExpr()->getBeginLoc(),
1499 diag::note_arc_weak_also_accessed_here)
1500 << Use.getUseExpr()->getSourceRange();
1508typedef std::pair<PartialDiagnosticAt, OptionalNotes>
DelayedDiag;
1509typedef std::list<DelayedDiag>
DiagList;
1511struct SortDiagBySourceLocation {
1515 bool operator()(
const DelayedDiag &left,
const DelayedDiag &right) {
1518 return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
1528 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1532 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1534 UsesMap constRefUses;
1537 UninitValsDiagReporter(
Sema &S) : S(S) {}
1540 MappedType &getUses(UsesMap &um,
const VarDecl *vd) {
1541 MappedType &
V = um[vd];
1542 if (!
V.getPointer())
1543 V.setPointer(
new UsesVec());
1549 getUses(uses, vd).getPointer()->push_back(use);
1554 getUses(constRefUses, vd).getPointer()->push_back(use);
1558 getUses(uses, vd).setInt(
true);
1559 getUses(constRefUses, vd).setInt(
true);
1563 for (
const auto &
P : uses) {
1565 const MappedType &
V =
P.second;
1567 UsesVec *vec =
V.getPointer();
1568 bool hasSelfInit =
V.getInt();
1573 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1589 for (
const auto &
U : *vec) {
1607 for (
const auto &
P : constRefUses) {
1609 const MappedType &
V =
P.second;
1611 UsesVec *vec =
V.getPointer();
1612 bool hasSelfInit =
V.getInt();
1614 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1620 for (
const auto &
U : *vec) {
1630 constRefUses.clear();
1634 static bool hasAlwaysUninitializedUse(
const UsesVec* vec) {
1635 return llvm::any_of(*vec, [](
const UninitUse &
U) {
1644class CalledOnceInterProceduralData {
1649 DelayedBlockWarnings[
Block].emplace_back(std::move(
Warning));
1654 S.
Diag(Delayed.first, Delayed.second);
1656 discardWarnings(
Block);
1660 DelayedBlockWarnings.erase(
Block);
1665 llvm::DenseMap<const BlockDecl *, DelayedDiagnostics> DelayedBlockWarnings;
1670 CalledOnceCheckReporter(
Sema &S, CalledOnceInterProceduralData &Data)
1673 const Expr *PrevCall,
bool IsCompletionHandler,
1674 bool Poised)
override {
1675 auto DiagToReport = IsCompletionHandler
1676 ? diag::warn_completion_handler_called_twice
1677 : diag::warn_called_once_gets_called_twice;
1679 S.
Diag(PrevCall->
getBeginLoc(), diag::note_called_once_gets_called_twice)
1684 bool IsCompletionHandler)
override {
1685 auto DiagToReport = IsCompletionHandler
1686 ? diag::warn_completion_handler_never_called
1687 : diag::warn_called_once_never_called;
1694 bool IsCalledDirectly,
1695 bool IsCompletionHandler)
override {
1696 auto DiagToReport = IsCompletionHandler
1697 ? diag::warn_completion_handler_never_called_when
1698 : diag::warn_called_once_never_called_when;
1702 << (
unsigned)Reason);
1704 if (
const auto *
Block = dyn_cast<BlockDecl>(Function)) {
1714 bool IsCompletionHandler)
override {
1715 auto DiagToReport = IsCompletionHandler
1716 ? diag::warn_completion_handler_never_called
1717 : diag::warn_called_once_never_called;
1733 CalledOnceInterProceduralData &
Data;
1736constexpr unsigned CalledOnceWarnings[] = {
1737 diag::warn_called_once_never_called,
1738 diag::warn_called_once_never_called_when,
1739 diag::warn_called_once_gets_called_twice};
1741constexpr unsigned CompletionHandlerWarnings[]{
1742 diag::warn_completion_handler_never_called,
1743 diag::warn_completion_handler_never_called_when,
1744 diag::warn_completion_handler_called_twice};
1749 return llvm::any_of(DiagIDs, [&Diags, At](
unsigned DiagID) {
1756 return shouldAnalyzeCalledOnceImpl(CompletionHandlerWarnings, Diags, At);
1761 return shouldAnalyzeCalledOnceImpl(CalledOnceWarnings, Diags, At) ||
1762 shouldAnalyzeCalledOnceConventions(Diags, At);
1770namespace threadSafety {
1781 if (Verbose && CurrentFunction) {
1783 S.
PDiag(diag::note_thread_warning_in_fun)
1784 << CurrentFunction);
1792 if (Verbose && CurrentFunction) {
1794 S.
PDiag(diag::note_thread_warning_in_fun)
1795 << CurrentFunction);
1796 ONS.push_back(std::move(FNote));
1804 ONS.push_back(Note1);
1805 ONS.push_back(Note2);
1806 if (Verbose && CurrentFunction) {
1808 S.
PDiag(diag::note_thread_warning_in_fun)
1809 << CurrentFunction);
1810 ONS.push_back(std::move(FNote));
1818 LocLocked, S.
PDiag(diag::note_locked_here) << Kind))
1826 LocUnlocked, S.
PDiag(diag::note_unlocked_here) << Kind))
1832 : S(S), FunLocation(FL), FunEndLocation(FEL),
1833 CurrentFunction(nullptr), Verbose(
false) {}
1835 void setVerbose(
bool b) { Verbose =
b; }
1843 for (
const auto &
Diag : Warnings) {
1845 for (
const auto &
Note :
Diag.second)
1853 Warnings.emplace_back(std::move(
Warning), getNotes());
1856 void handleUnmatchedUnlock(StringRef Kind, Name LockName,
SourceLocation Loc,
1861 << Kind << LockName);
1862 Warnings.emplace_back(std::move(
Warning),
1863 makeUnlockedHereNote(LocPreviousUnlock, Kind));
1866 void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
1871 LocUnlock = FunLocation;
1873 LocUnlock, S.
PDiag(diag::warn_unlock_kind_mismatch)
1874 << Kind << LockName << Received <<
Expected);
1875 Warnings.emplace_back(std::move(
Warning),
1876 makeLockedHereNote(LocLocked, Kind));
1879 void handleDoubleLock(StringRef Kind, Name LockName,
SourceLocation LocLocked,
1882 LocDoubleLock = FunLocation;
1884 << Kind << LockName);
1885 Warnings.emplace_back(std::move(
Warning),
1886 makeLockedHereNote(LocLocked, Kind));
1889 void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
1893 unsigned DiagID = 0;
1896 DiagID = diag::warn_lock_some_predecessors;
1899 DiagID = diag::warn_expecting_lock_held_on_loop;
1902 DiagID = diag::warn_no_unlock;
1905 DiagID = diag::warn_expecting_locked;
1909 LocEndOfScope = FunEndLocation;
1913 Warnings.emplace_back(std::move(
Warning),
1914 makeLockedHereNote(LocLocked, Kind));
1917 void handleExclusiveAndShared(StringRef Kind, Name LockName,
1921 S.
PDiag(diag::warn_lock_exclusive_and_shared)
1922 << Kind << LockName);
1924 << Kind << LockName);
1925 Warnings.emplace_back(std::move(
Warning), getNotes(
Note));
1931 "Only works for variables");
1933 diag::warn_variable_requires_any_lock:
1934 diag::warn_var_deref_requires_any_lock;
1937 Warnings.emplace_back(std::move(
Warning), getNotes());
1940 void handleMutexNotHeld(StringRef Kind,
const NamedDecl *D,
1943 Name *PossibleMatch)
override {
1944 unsigned DiagID = 0;
1945 if (PossibleMatch) {
1948 DiagID = diag::warn_variable_requires_lock_precise;
1951 DiagID = diag::warn_var_deref_requires_lock_precise;
1954 DiagID = diag::warn_fun_requires_lock_precise;
1957 DiagID = diag::warn_guarded_pass_by_reference;
1960 DiagID = diag::warn_pt_guarded_pass_by_reference;
1970 S.
PDiag(diag::note_guarded_by_declared_here)
1972 Warnings.emplace_back(std::move(
Warning), getNotes(
Note, VNote));
1974 Warnings.emplace_back(std::move(
Warning), getNotes(
Note));
1978 DiagID = diag::warn_variable_requires_lock;
1981 DiagID = diag::warn_var_deref_requires_lock;
1984 DiagID = diag::warn_fun_requires_lock;
1987 DiagID = diag::warn_guarded_pass_by_reference;
1990 DiagID = diag::warn_pt_guarded_pass_by_reference;
1998 S.
PDiag(diag::note_guarded_by_declared_here));
1999 Warnings.emplace_back(std::move(
Warning), getNotes(
Note));
2001 Warnings.emplace_back(std::move(
Warning), getNotes());
2005 void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
2008 S.
PDiag(diag::warn_acquire_requires_negative_cap)
2009 << Kind << LockName << Neg);
2010 Warnings.emplace_back(std::move(
Warning), getNotes());
2013 void handleNegativeNotHeld(
const NamedDecl *D, Name LockName,
2016 Loc, S.
PDiag(diag::warn_fun_requires_negative_cap) << D << LockName);
2017 Warnings.emplace_back(std::move(
Warning), getNotes());
2020 void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
2023 << Kind << FunName << LockName);
2024 Warnings.emplace_back(std::move(
Warning), getNotes());
2027 void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
2030 S.
PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
2031 Warnings.emplace_back(std::move(
Warning), getNotes());
2034 void handleBeforeAfterCycle(Name L1Name,
SourceLocation Loc)
override {
2036 S.
PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
2037 Warnings.emplace_back(std::move(
Warning), getNotes());
2041 CurrentFunction = FD;
2045 CurrentFunction =
nullptr;
2059class ConsumedWarningsHandler :
public ConsumedWarningsHandlerBase {
2066 ConsumedWarningsHandler(
Sema &S) : S(S) {}
2070 for (
const auto &
Diag : Warnings) {
2072 for (
const auto &
Note :
Diag.second)
2078 StringRef VariableName)
override {
2086 StringRef VariableName,
2087 StringRef ExpectedState,
2088 StringRef ObservedState)
override {
2091 diag::warn_param_return_typestate_mismatch) << VariableName <<
2092 ExpectedState << ObservedState);
2097 void warnParamTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
2098 StringRef ObservedState)
override {
2101 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
2107 StringRef TypeName)
override {
2109 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
2114 void warnReturnTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
2115 StringRef ObservedState)
override {
2118 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
2123 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
2127 diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
2132 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
2136 MethodName << VariableName << State);
2154 UnsafeBufferUsageReporter(
Sema &S) : S(S) {}
2157 bool IsRelatedToDecl)
override {
2160 unsigned MsgParam = 0;
2161 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Operation)) {
2162 Loc = ASE->getBase()->getExprLoc();
2163 Range = ASE->getBase()->getSourceRange();
2165 }
else if (
const auto *BO = dyn_cast<BinaryOperator>(Operation)) {
2167 if (Op == BO_Add || Op == BO_AddAssign || Op == BO_Sub ||
2168 Op == BO_SubAssign) {
2169 if (BO->getRHS()->getType()->isIntegerType()) {
2170 Loc = BO->getLHS()->getExprLoc();
2171 Range = BO->getLHS()->getSourceRange();
2173 Loc = BO->getRHS()->getExprLoc();
2174 Range = BO->getRHS()->getSourceRange();
2178 }
else if (
const auto *UO = dyn_cast<UnaryOperator>(Operation)) {
2180 if (Op == UO_PreInc || Op == UO_PreDec || Op == UO_PostInc ||
2182 Loc = UO->getSubExpr()->getExprLoc();
2183 Range = UO->getSubExpr()->getSourceRange();
2187 if (isa<CallExpr>(Operation)) {
2193 if (IsRelatedToDecl)
2194 S.
Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam <<
Range;
2196 S.
Diag(Loc, diag::warn_unsafe_buffer_operation) << MsgParam <<
Range;
2201 FixItList &&Fixes)
override {
2203 S.
Diag(
Variable->getLocation(), diag::warn_unsafe_buffer_variable);
2205 D << (
Variable->getType()->isPointerType() ? 0 : 1);
2207 for (
const auto &F : Fixes)
2219 enableCheckFallThrough = 1;
2220 enableCheckUnreachable = 0;
2221 enableThreadSafetyAnalysis = 0;
2222 enableConsumedAnalysis = 0;
2249 NumFunctionsAnalyzed(0), NumFunctionsWithBadCFGs(0), NumCFGBlocks(0),
2250 MaxCFGBlocksPerFunction(0), NumUninitAnalysisFunctions(0),
2251 NumUninitAnalysisVariables(0), MaxUninitAnalysisVariablesPerFunction(0),
2252 NumUninitAnalysisBlockVisits(0),
2253 MaxUninitAnalysisBlockVisitsPerFunction(0) {
2255 using namespace diag;
2258 DefaultPolicy.enableCheckUnreachable =
2260 isEnabled(D, warn_unreachable_return) ||
2261 isEnabled(D, warn_unreachable_loop_increment);
2263 DefaultPolicy.enableThreadSafetyAnalysis =
isEnabled(D, warn_double_lock);
2265 DefaultPolicy.enableConsumedAnalysis =
2266 isEnabled(D, warn_use_in_invalid_state);
2274 S.
Diag(D.Loc, D.PD);
2296 if (cast<DeclContext>(D)->isDependentContext())
2327 if (
P.enableCheckUnreachable ||
P.enableThreadSafetyAnalysis ||
2328 P.enableConsumedAnalysis) {
2344 std::optional<LogicalErrorHandler> LEH;
2345 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->
getBeginLoc())) {
2352 bool analyzed =
false;
2356 for (
const Stmt *S : D.Stmts)
2363 bool AllReachable =
true;
2364 for (
const Stmt *S : D.Stmts) {
2374 AllReachable =
false;
2383 S.
Diag(D.Loc, D.PD);
2392 if (
P.enableCheckFallThrough) {
2393 const CheckFallThroughDiagnostics &CD =
2395 ? CheckFallThroughDiagnostics::MakeForBlock()
2396 : (isa<CXXMethodDecl>(D) &&
2397 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2398 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2399 ? CheckFallThroughDiagnostics::MakeForLambda()
2401 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2402 : CheckFallThroughDiagnostics::MakeForFunction(D)));
2407 if (
P.enableCheckUnreachable) {
2413 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
2420 if (
P.enableThreadSafetyAnalysis) {
2423 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
2425 Reporter.setIssueBetaWarnings(
true);
2427 Reporter.setVerbose(
true);
2431 Reporter.emitDiagnostics();
2435 if (
P.enableConsumedAnalysis) {
2436 consumed::ConsumedWarningsHandler WarningHandler(S);
2446 UninitValsDiagReporter reporter(S);
2453 ++NumUninitAnalysisFunctions;
2456 MaxUninitAnalysisVariablesPerFunction =
2457 std::max(MaxUninitAnalysisVariablesPerFunction,
2459 MaxUninitAnalysisBlockVisitsPerFunction =
2460 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
2468 shouldAnalyzeCalledOnceParameters(Diags, D->
getBeginLoc())) {
2470 CalledOnceCheckReporter Reporter(S, IPData->CalledOnceData);
2473 shouldAnalyzeCalledOnceConventions(Diags, D->
getBeginLoc()));
2477 bool FallThroughDiagFull =
2479 bool FallThroughDiagPerFunction = !Diags.
isIgnored(
2480 diag::warn_unannotated_fallthrough_per_function, D->
getBeginLoc());
2481 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
2492 if (!Diags.
isIgnored(diag::warn_infinite_recursive_function,
2494 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2501 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2508 UnsafeBufferUsageReporter R(S);
2514 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->
getBeginLoc())) {
2520 ++NumFunctionsAnalyzed;
2525 MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,
2526 cfg->getNumBlockIDs());
2528 ++NumFunctionsWithBadCFGs;
2534 llvm::errs() <<
"\n*** Analysis Based Warnings Stats:\n";
2536 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
2537 unsigned AvgCFGBlocksPerFunction =
2538 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
2539 llvm::errs() << NumFunctionsAnalyzed <<
" functions analyzed ("
2540 << NumFunctionsWithBadCFGs <<
" w/o CFGs).\n"
2541 <<
" " << NumCFGBlocks <<
" CFG blocks built.\n"
2542 <<
" " << AvgCFGBlocksPerFunction
2543 <<
" average CFG blocks per function.\n"
2544 <<
" " << MaxCFGBlocksPerFunction
2545 <<
" max CFG blocks per function.\n";
2547 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
2548 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
2549 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
2550 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
2551 llvm::errs() << NumUninitAnalysisFunctions
2552 <<
" functions analyzed for uninitialiazed variables\n"
2553 <<
" " << NumUninitAnalysisVariables <<
" variables analyzed.\n"
2554 <<
" " << AvgUninitVariablesPerFunction
2555 <<
" average variables per function.\n"
2556 <<
" " << MaxUninitAnalysisVariablesPerFunction
2557 <<
" max variables per function.\n"
2558 <<
" " << NumUninitAnalysisBlockVisits <<
" block visits.\n"
2559 <<
" " << AvgUninitBlockVisitsPerFunction
2560 <<
" average block visits per function.\n"
2561 <<
" " << MaxUninitAnalysisBlockVisitsPerFunction
2562 <<
" max block visits per function.\n";
static void visitReachableThrows(CFG *BodyCFG, llvm::function_ref< void(const CXXThrowExpr *, CFGBlock &)> Visit)
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD)
static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, const Stmt *S)
static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC)
CheckFallThrough - Check that we don't fall off the end of a Statement that should return a value.
static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope)
static void diagnoseRepeatedUseOfWeak(Sema &S, const sema::FunctionScopeInfo *CurFn, const Decl *D, const ParentMap &PM)
static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc, const FunctionDecl *FD)
static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, bool PerFunction)
static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD, AnalysisDeclContext &AC)
static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, const Stmt *Else, bool CondVal, FixItHint &Fixit1, FixItHint &Fixit2)
Create a fixit to remove an if-like statement, on the assumption that its condition is CondVal.
static StringRef getFallthroughAttrSpelling(Preprocessor &PP, SourceLocation Loc)
static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag)
static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool alwaysReportSelfInit=false)
DiagnoseUninitializedUse – Helper function for diagnosing uses of an uninitialized variable.
static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block)
static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock, CFG *Body)
Determine whether an exception thrown by E, unwinding from ThrowBlock, can reach ExitBlock.
static bool isNoexcept(const FunctionDecl *FD)
static bool DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD, const UninitUse &Use)
Diagnose uninitialized const reference usages.
static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool IsCapturedByBlock)
DiagUninitUse – Helper function to produce a diagnostic for an uninitialized use of a variable.
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC)
CheckUnreachable - Check for unreachable code.
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, QualType BlockType, const CheckFallThroughDiagnostics &CD, AnalysisDeclContext &AC, sema::FunctionScopeInfo *FSI)
CheckFallThroughForBody - Check that we don't fall off the end of a function that should return a val...
@ NeverFallThroughOrReturn
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, const Stmt *Body, AnalysisDeclContext &AC)
static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg)
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult, const ASTContext &Ctx, Expr::SideEffectsKind AllowSideEffects, EvalInfo &Info)
static std::pair< const Stmt *, const CFGBlock * > getLastStmt(const ExplodedNode *Node)
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR, AnalysisManager &AM, const ObjCAutoreleaseWriteChecker *Checker)
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines the Objective-C statement AST node classes.
@ Open
The standard open() call: int open(const char *path, int oflag, ...);.
TextDiagnosticBuffer::DiagList DiagList
__device__ __2f16 float bool s
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
AnalysisDeclContext contains the context data for the function, method or block under analysis.
void registerForcedBlockExpression(const Stmt *stmt)
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
ParentMap & getParentMap()
const Decl * getDecl() const
bool getAddEHEdges() const
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
CFG::BuildOptions & getCFGBuildOptions()
Represents an attribute applied to a statement.
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isLogicalOp(Opcode Opc)
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getOperatorLoc() const
SourceLocation getExprLoc() const
static StringRef getOpcodeStr(Opcode Op)
getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to,...
Represents a block literal declaration, which is like an unnamed FunctionDecl.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
SourceLocation getBeginLoc() const LLVM_READONLY
unsigned IgnoreDefaultsWithCoveredEnums
Represents a single basic block in a source-level CFG.
filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const
reverse_iterator rbegin()
bool hasNoReturnElement() const
succ_iterator succ_begin()
Stmt * getTerminatorStmt()
pred_iterator pred_begin()
unsigned getBlockID() const
unsigned succ_size() const
CFGCallback defines methods that should be called when a logical operator error is found when buildin...
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
virtual void compareBitwiseOr(const BinaryOperator *B)
Represents a top-level expression in a basic block.
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
bool isReachable(const CFGBlock *Src, const CFGBlock *Dst)
Returns true if the block 'Dst' can be reached from block 'Src'.
const Stmt * getStmt() const
bool PruneTriviallyFalseEdges
bool AddCXXDefaultInitExprInCtors
BuildOptions & setAllAlwaysAdd()
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Represents a call to a member function that may be written either with member call syntax (e....
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Represents a static or instance method of a struct/union/class.
A C++ throw-expression (C++ [except.throw]).
const Expr * getSubExpr() const
SourceLocation getThrowLoc() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
virtual void handleBlockThatIsGuaranteedToBeCalledOnce(const BlockDecl *Block)
Called when the block is guaranteed to be called exactly once.
virtual void handleBlockWithNoGuarantees(const BlockDecl *Block)
Called when the block has no guarantees about how many times it can get called.
virtual void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call, const Expr *PrevCall, bool IsCompletionHandler, bool Poised)
Called when parameter is called twice.
virtual void handleNeverCalled(const ParmVarDecl *Parameter, bool IsCompletionHandler)
Called when parameter is not called at all.
virtual void handleCapturedNeverCalled(const ParmVarDecl *Parameter, const Decl *Where, bool IsCompletionHandler)
Called when captured parameter is not called at all.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getBegin() const
ConditionalOperator - The ?: ternary operator.
Expr * getFalseExpr() const
Expr * getTrueExpr() const
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getEndLoc() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
SourceLocation getBeginLoc() const LLVM_READONLY
TypeSourceInfo * getTypeSourceInfo() const
Concrete class used by the front-end to report problems and issues.
bool getIgnoreAllWarnings() const
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
bool getSuppressSystemWarnings() const
void VisitDeclRefExpr(PTR(DeclRefExpr) E)
This represents one expression.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification,...
@ TK_MemberSpecialization
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
bool isCPUDispatchMultiVersion() const
True if this function is a multiversioned dispatch function as a part of the cpu_specific/cpu_dispatc...
Represents a prototype with parameter type info, e.g.
FunctionType - C99 6.7.5.3 - Function Declarators.
IfStmt - This represents an if/then/else.
LabelStmt - Represents a label, which has a substatement.
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
This represents a decl that may have a name.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
@ TypeSpec
A type, stored as a Type*.
ObjCMethodDecl - Represents an instance or class method declaration.
Represents one property declaration in an Objective-C interface.
Stmt * getParent(Stmt *) const
Represents a parameter to a function.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
const LangOptions & getLangOpts() const
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getCanonicalType() const
bool hasObjCLifetime() const
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, Expr *Init)
Recursively visit a lambda capture.
bool shouldWalkTypesOfTypeLocs() const
Return whether this visitor should recurse into the types of TypeLocs.
Sema - This implements semantic analysis and AST building for C.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Preprocessor & getPreprocessor() const
DiagnosticsEngine & getDiagnostics() const
ASTContext & getASTContext() const
std::string getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const
Get a string to suggest for zero-initialization of a type.
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
const LangOptions & getLangOpts() const
threadSafety::BeforeSet * ThreadSafetyDeclCache
bool CollectStats
Flag indicating whether or not to collect detailed statistics.
SourceManager & getSourceManager() const
bool handlerCanCatch(QualType HandlerType, QualType ExceptionType)
bool hasUncompilableErrorOccurred() const
Whether uncompilable error has occurred.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
SourceManager & SourceMgr
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
SwitchStmt - This represents a 'switch' stmt.
Stores token information for comparing actual tokens with predefined values.
QualType getType() const
Return the type wrapped by this type source info.
bool isBlockPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const T * getAs() const
Member-template getAs<specific type>'.
A use of a variable, which might be uninitialized.
const Expr * getUser() const
Get the expression containing the uninitialized use.
SmallVectorImpl< Branch >::const_iterator branch_iterator
branch_iterator branch_end() const
branch_iterator branch_begin() const
Branches which inevitably result in the variable being used uninitialized.
@ Always
The use is always uninitialized.
@ AfterDecl
The use is uninitialized the first time it is reached after we reach the variable's declaration.
@ Maybe
The use might be uninitialized.
@ AfterCall
The use is uninitialized the first time it is reached after the function is called.
@ Sometimes
The use is uninitialized whenever a certain branch is taken.
Kind getKind() const
Get the kind of uninitialized use.
virtual void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use)
Called when the uninitialized variable is used at the given expression.
virtual void handleSelfInit(const VarDecl *vd)
Called when the uninitialized variable analysis detects the idiom 'int x = x'.
virtual void handleConstRefUseOfUninitVariable(const VarDecl *vd, const UninitUse &use)
Called when the uninitialized variable is used as const refernce argument.
The interface that lets the caller handle unsafe buffer usage analysis results by overriding this cla...
virtual void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl)=0
Invoked when an unsafe operation over raw pointers is found.
virtual void handleFixableVariable(const VarDecl *Variable, FixItList &&List)=0
Invoked when a fix is suggested against a variable.
Represents a variable declaration or definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
const Expr * getInit() const
A class that handles the analysis of uniqueness violations.
void run(AnalysisDeclContext &AC)
Check a function's CFG for consumed violations.
virtual void HandleUnreachable(UnreachableKind UK, SourceLocation L, SourceRange ConditionVal, SourceRange R1, SourceRange R2)=0
void IssueWarnings(Policy P, FunctionScopeInfo *fscope, const Decl *D, QualType BlockType)
AnalysisBasedWarnings(Sema &s)
Represents a simple identification of a weak object.
Retains information about a function, method, or block that is currently being parsed.
llvm::SmallDenseMap< WeakObjectProfileTy, WeakUseVector, 8, WeakObjectProfileTy::DenseMapInfo > WeakObjectUseMap
Used to collect all uses of weak objects in a function body.
bool HasFallthroughStmt
Whether there is a fallthrough statement in this function.
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
SmallVector< PossiblyUnreachableDiag, 4 > PossiblyUnreachableDiags
A list of PartialDiagnostics created but delayed within the current function scope.
const WeakObjectUseMap & getWeakObjectUses() const
Handler class for thread safety warnings.
InterProceduralData aims to be a storage of whatever data should be passed between analyses of differ...
CalledOnceInterProceduralData CalledOnceData
SmallVector< PartialDiagnosticAt, 1 > OptionalNotes
std::pair< PartialDiagnosticAt, OptionalNotes > DelayedDiag
uint32_t Variable
Boolean variables are represented as positive integers.
bool LE(InterpState &S, CodePtr OpPC)
bool Call(InterpState &S, CodePtr &PC, const Function *Func)
void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP, Callback &CB)
unsigned ScanReachableFromBlock(const CFGBlock *Start, llvm::BitVector &Reachable)
ScanReachableFromBlock - Mark all blocks reachable from Start.
UnreachableKind
Classifications of unreachable code.
LockKind getLockKindFromAccessKind(AccessKind AK)
Helper function that returns a LockKind required for the given level of access.
@ LEK_NotLockedAtEndOfFunction
@ LEK_LockedSomePredecessors
@ LEK_LockedAtEndOfFunction
@ LEK_LockedSomeLoopIterations
LockKind
This enum distinguishes between different kinds of lock actions.
void runThreadSafetyAnalysis(AnalysisDeclContext &AC, ThreadSafetyHandler &Handler, BeforeSet **Bset)
Check a function's CFG for thread-safety violations.
ProtectedOperationKind
This enum distinguishes between different kinds of operations that may need to be protected by locks.
@ POK_PtPassByRef
Passing a pt-guarded variable by reference.
@ POK_VarDereference
Dereferencing a variable (e.g. p in *p = 5;)
@ POK_PassByRef
Passing a guarded variable by reference.
@ POK_VarAccess
Reading or writing a variable (e.g. x in x = 5;)
@ POK_FunctionCall
Making a function call (e.g. fool())
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
@ C
Languages that the frontend can parse and compile.
@ Property
The type of a property.
@ Parameter
The parameter type of a method or function.
void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, AnalysisDeclContext &ac, UninitVariablesHandler &handler, UninitVariablesAnalysisStats &stats)
void checkCalledOnceParameters(AnalysisDeclContext &AC, CalledOnceCheckHandler &Handler, bool CheckConventionalParameters)
Check given CFG for 'called once' parameter violations.
void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler)
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
EvalResult is a struct with detailed info about an evaluated expression.
unsigned NumVariablesAnalyzed