39 #include "llvm/ADT/BitVector.h" 40 #include "llvm/ADT/MapVector.h" 41 #include "llvm/ADT/SmallString.h" 42 #include "llvm/ADT/SmallVector.h" 43 #include "llvm/ADT/StringRef.h" 44 #include "llvm/Support/Casting.h" 49 using namespace clang;
61 UnreachableCodeHandler(
Sema &s) : S(s) {}
70 if (PreviousSilenceableCondVal.
isValid() &&
72 PreviousSilenceableCondVal == SilenceableCondVal)
74 PreviousSilenceableCondVal = SilenceableCondVal;
76 unsigned diag = diag::warn_unreachable;
79 diag = diag::warn_unreachable_break;
82 diag = diag::warn_unreachable_return;
85 diag = diag::warn_unreachable_loop_increment;
91 S.
Diag(L, diag) << R1 << R2;
98 S.
Diag(Open, diag::note_unreachable_silence)
119 UnreachableCodeHandler UC(S);
131 static bool HasMacroID(
const Expr *E) {
137 if (
const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
138 if (HasMacroID(SubExpr))
144 void compareAlwaysTrue(
const BinaryOperator *B,
bool isAlwaysTrue)
override {
149 S.
Diag(B->
getExprLoc(), diag::warn_tautological_overlap_comparison)
150 << DiagRange << isAlwaysTrue;
154 bool isAlwaysTrue)
override {
160 << DiagRange << isAlwaysTrue;
174 for (
const auto &B : Block) {
188 isa<TemplateSpecializationType>(NNS->getAsType())) {
204 llvm::SmallPtrSet<CFGBlock *, 16> Visited;
207 bool foundRecursion =
false;
212 WorkList.push_back(&cfg->
getEntry());
214 while (!WorkList.empty()) {
215 CFGBlock *Block = WorkList.pop_back_val();
219 if (!Visited.insert(SuccBlock).second)
223 if (ExitID == SuccBlock->getBlockID())
228 foundRecursion =
true;
232 WorkList.push_back(SuccBlock);
236 return foundRecursion;
272 Stack.push_back(&ThrowBlock);
275 while (!Stack.empty()) {
276 CFGBlock &UnwindBlock = *Stack.back();
279 for (
auto &Succ : UnwindBlock.
succs()) {
280 if (!Succ.isReachable() || Queued[Succ->getBlockID()])
287 dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
288 QualType Caught = Catch->getCaughtType();
295 Stack.push_back(Succ);
296 Queued[Succ->getBlockID()] =
true;
310 if (!Reachable[B->getBlockID()])
316 if (
auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
326 S.
Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
328 (isa<CXXDestructorDecl>(FD) ||
332 getAs<FunctionProtoType>())
334 << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
357 if (FPT->isNothrow() || FD->
hasAttr<NoThrowAttr>())
398 for (
const auto *B : *cfg) {
399 if (!live[B->getBlockID()]) {
400 if (B->pred_begin() == B->pred_end()) {
401 const Stmt *Term = B->getTerminatorStmt();
402 if (Term && isa<CXXTryStmt>(Term))
414 bool HasLiveReturn =
false;
415 bool HasFakeEdge =
false;
416 bool HasPlainEdge =
false;
417 bool HasAbnormalEdge =
false;
425 cfg->getExit().filtered_pred_start_end(FO);
435 HasAbnormalEdge =
true;
444 for ( ; ri != re ; ++ri)
451 if (Term && isa<CXXTryStmt>(Term)) {
452 HasAbnormalEdge =
true;
462 if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
463 HasLiveReturn =
true;
466 if (isa<ObjCAtThrowStmt>(S)) {
470 if (isa<CXXThrowExpr>(S)) {
474 if (isa<MSAsmStmt>(S)) {
477 HasLiveReturn =
true;
480 if (isa<CXXTryStmt>(S)) {
481 HasAbnormalEdge =
true;
486 HasAbnormalEdge =
true;
497 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
507 struct CheckFallThroughDiagnostics {
508 unsigned diag_MaybeFallThrough_HasNoReturn;
509 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
510 unsigned diag_AlwaysFallThrough_HasNoReturn;
511 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
512 unsigned diag_NeverFallThroughOrReturn;
513 enum { Function, Block, Lambda, Coroutine } funMode;
516 static CheckFallThroughDiagnostics MakeForFunction(
const Decl *Func) {
517 CheckFallThroughDiagnostics D;
519 D.diag_MaybeFallThrough_HasNoReturn =
520 diag::warn_falloff_noreturn_function;
521 D.diag_MaybeFallThrough_ReturnsNonVoid =
522 diag::warn_maybe_falloff_nonvoid_function;
523 D.diag_AlwaysFallThrough_HasNoReturn =
524 diag::warn_falloff_noreturn_function;
525 D.diag_AlwaysFallThrough_ReturnsNonVoid =
526 diag::warn_falloff_nonvoid_function;
530 bool isVirtualMethod =
false;
531 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
532 isVirtualMethod = Method->isVirtual();
536 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
537 isTemplateInstantiation = Function->isTemplateInstantiation();
539 if (!isVirtualMethod && !isTemplateInstantiation)
540 D.diag_NeverFallThroughOrReturn =
541 diag::warn_suggest_noreturn_function;
543 D.diag_NeverFallThroughOrReturn = 0;
545 D.funMode = Function;
549 static CheckFallThroughDiagnostics MakeForCoroutine(
const Decl *Func) {
550 CheckFallThroughDiagnostics D;
552 D.diag_MaybeFallThrough_HasNoReturn = 0;
553 D.diag_MaybeFallThrough_ReturnsNonVoid =
554 diag::warn_maybe_falloff_nonvoid_coroutine;
555 D.diag_AlwaysFallThrough_HasNoReturn = 0;
556 D.diag_AlwaysFallThrough_ReturnsNonVoid =
557 diag::warn_falloff_nonvoid_coroutine;
558 D.funMode = Coroutine;
562 static CheckFallThroughDiagnostics MakeForBlock() {
563 CheckFallThroughDiagnostics D;
564 D.diag_MaybeFallThrough_HasNoReturn =
565 diag::err_noreturn_block_has_return_expr;
566 D.diag_MaybeFallThrough_ReturnsNonVoid =
567 diag::err_maybe_falloff_nonvoid_block;
568 D.diag_AlwaysFallThrough_HasNoReturn =
569 diag::err_noreturn_block_has_return_expr;
570 D.diag_AlwaysFallThrough_ReturnsNonVoid =
571 diag::err_falloff_nonvoid_block;
572 D.diag_NeverFallThroughOrReturn = 0;
577 static CheckFallThroughDiagnostics MakeForLambda() {
578 CheckFallThroughDiagnostics D;
579 D.diag_MaybeFallThrough_HasNoReturn =
580 diag::err_noreturn_lambda_has_return_expr;
581 D.diag_MaybeFallThrough_ReturnsNonVoid =
582 diag::warn_maybe_falloff_nonvoid_lambda;
583 D.diag_AlwaysFallThrough_HasNoReturn =
584 diag::err_noreturn_lambda_has_return_expr;
585 D.diag_AlwaysFallThrough_ReturnsNonVoid =
586 diag::warn_falloff_nonvoid_lambda;
587 D.diag_NeverFallThroughOrReturn = 0;
593 bool HasNoReturn)
const {
594 if (funMode == Function) {
595 return (ReturnsVoid ||
596 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function,
599 D.
isIgnored(diag::warn_noreturn_function_has_return_expr,
602 D.
isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
604 if (funMode == Coroutine) {
605 return (ReturnsVoid ||
606 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
607 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
612 return ReturnsVoid && !HasNoReturn;
624 const CheckFallThroughDiagnostics &CD,
628 bool ReturnsVoid =
false;
629 bool HasNoReturn =
false;
632 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
633 if (
const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
634 ReturnsVoid = CBody->getFallthroughHandler() !=
nullptr;
636 ReturnsVoid = FD->getReturnType()->isVoidType();
637 HasNoReturn = FD->isNoReturn();
639 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
640 ReturnsVoid = MD->getReturnType()->isVoidType();
641 HasNoReturn = MD->hasAttr<NoReturnAttr>();
643 else if (isa<BlockDecl>(D)) {
646 if (FT->getReturnType()->isVoidType())
648 if (FT->getNoReturnAttr())
656 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
677 EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
678 else if (!ReturnsVoid)
679 EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
683 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
684 else if (!ReturnsVoid)
685 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
688 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
689 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
690 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
691 }
else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
692 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
694 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
719 : Inherited(Context), FoundReference(
false), Needle(Needle) {}
721 void VisitExpr(
const Expr *E) {
726 Inherited::VisitExpr(E);
731 FoundReference =
true;
733 Inherited::VisitDeclRefExpr(E);
736 bool doesContainReference()
const {
return FoundReference; }
744 S.
Diag(VD->
getLocation(), diag::note_block_var_fixit_add_initialization)
765 S.
Diag(Loc, diag::note_var_fixit_add_initialization) << VD->
getDeclName()
773 const Stmt *Else,
bool CondVal,
797 bool IsCapturedByBlock) {
798 bool Diagnosed =
false;
831 const Stmt *Term = I->Terminator;
841 int RemoveDiagKind = -1;
842 const char *FixitStr =
843 S.
getLangOpts().CPlusPlus ? (I->Output ?
"true" :
"false")
844 : (I->Output ?
"1" :
"0");
847 switch (Term ? Term->
getStmtClass() : Stmt::DeclStmtClass) {
854 case Stmt::IfStmtClass: {
855 const IfStmt *IS = cast<IfStmt>(Term);
861 I->Output, Fixit1, Fixit2);
864 case Stmt::ConditionalOperatorClass: {
871 I->Output, Fixit1, Fixit2);
874 case Stmt::BinaryOperatorClass: {
882 if ((BO->
getOpcode() == BO_LAnd && I->Output) ||
883 (BO->
getOpcode() == BO_LOr && !I->Output))
894 case Stmt::WhileStmtClass:
897 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
901 case Stmt::ForStmtClass:
904 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
911 case Stmt::CXXForRangeStmtClass:
912 if (I->Output == 1) {
920 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
924 case Stmt::DoStmtClass:
927 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
933 case Stmt::CaseStmtClass:
936 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
938 case Stmt::DefaultStmtClass:
941 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
945 S.
Diag(Range.
getBegin(), diag::warn_sometimes_uninit_var)
946 << VD->
getDeclName() << IsCapturedByBlock << DiagKind
947 << Str << I->Output << Range;
948 S.
Diag(User->getBeginLoc(), diag::note_uninit_var_use)
949 << IsCapturedByBlock << User->getSourceRange();
950 if (RemoveDiagKind != -1)
952 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
970 bool alwaysReportSelfInit =
false) {
984 if (!alwaysReportSelfInit && DRE ==
Initializer->IgnoreParenImpCasts())
987 ContainsReference CR(S.
Context, DRE);
989 if (CR.doesContainReference()) {
990 S.
Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
1001 diag::warn_uninit_byref_blockvar_captured_by_block)
1021 FallthroughMapper(
Sema &S)
1022 : FoundSwitchStatements(
false),
1026 bool foundSwitchStatements()
const {
return FoundSwitchStatements; }
1029 bool Found = FallthroughStmts.erase(Stmt);
1034 typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;
1036 const AttrStmts &getFallthroughStmts()
const {
1037 return FallthroughStmts;
1040 void fillReachableBlocks(
CFG *Cfg) {
1041 assert(ReachableBlocks.empty() &&
"ReachableBlocks already filled");
1042 std::deque<const CFGBlock *> BlockQueue;
1044 ReachableBlocks.insert(&Cfg->
getEntry());
1045 BlockQueue.push_back(&Cfg->
getEntry());
1050 for (
const auto *B : *Cfg) {
1051 const Stmt *L = B->getLabel();
1052 if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1053 BlockQueue.push_back(B);
1056 while (!BlockQueue.empty()) {
1058 BlockQueue.pop_front();
1062 if (*I && ReachableBlocks.insert(*I).second)
1063 BlockQueue.push_back(*I);
1068 bool checkFallThroughIntoBlock(
const CFGBlock &B,
int &AnnotatedCnt,
1069 bool IsTemplateInstantiation) {
1070 assert(!ReachableBlocks.empty() &&
"ReachableBlocks empty");
1072 int UnannotatedCnt = 0;
1076 while (!BlockQueue.empty()) {
1078 BlockQueue.pop_front();
1082 if (Term && isa<SwitchStmt>(Term))
1093 if (!ReachableBlocks.count(P)) {
1095 ElemEnd = P->
rend();
1096 ElemIt != ElemEnd; ++ElemIt) {
1098 if (
const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1102 if (!IsTemplateInstantiation)
1103 S.
Diag(AS->getBeginLoc(),
1104 diag::warn_fallthrough_attr_unreachable);
1105 markFallthroughVisited(AS);
1125 markFallthroughVisited(AS);
1133 std::back_inserter(BlockQueue));
1139 return !!UnannotatedCnt;
1143 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1146 if (asFallThroughAttr(S))
1147 FallthroughStmts.insert(S);
1152 FoundSwitchStatements =
true;
1158 bool TraverseDecl(
Decl *D) {
return true; }
1164 TraverseLambdaCapture(LE, &std::get<0>(
C), std::get<1>(
C));
1171 if (
const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1172 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1183 ElemIt != ElemEnd; ++ElemIt) {
1185 return CS->getStmt();
1191 if (!isa<SwitchCase>(SW->getSubStmt()))
1192 return SW->getSubStmt();
1197 bool FoundSwitchStatements;
1198 AttrStmts FallthroughStmts;
1200 llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
1207 tok::l_square, tok::l_square,
1209 tok::r_square, tok::r_square
1215 tok::r_square, tok::r_square
1218 bool PreferClangAttr = !PP.
getLangOpts().CPlusPlus17;
1220 StringRef MacroName;
1221 if (PreferClangAttr)
1223 if (MacroName.empty())
1225 if (MacroName.empty() && !PreferClangAttr)
1227 if (MacroName.empty())
1228 MacroName = PreferClangAttr ?
"[[clang::fallthrough]]" :
"[[fallthrough]]";
1245 FallthroughMapper FM(S);
1246 FM.TraverseStmt(AC.
getBody());
1248 if (!FM.foundSwitchStatements())
1251 if (PerFunction && FM.getFallthroughStmts().empty())
1259 FM.fillReachableBlocks(Cfg);
1261 for (
const CFGBlock *B : llvm::reverse(*Cfg)) {
1264 if (!Label || !isa<SwitchCase>(Label))
1269 bool IsTemplateInstantiation =
false;
1271 IsTemplateInstantiation = Function->isTemplateInstantiation();
1272 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1273 IsTemplateInstantiation))
1277 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1278 : diag::warn_unannotated_fallthrough);
1280 if (!AnnotatedCnt) {
1285 const Stmt *Term = B->getTerminatorStmt();
1287 while (B->empty() && !Term && B->succ_size() == 1) {
1288 B = *B->succ_begin();
1289 Term = B->getTerminatorStmt();
1291 if (!(B->empty() && Term && isa<BreakStmt>(Term))) {
1295 TextToInsert +=
"; ";
1296 S.
Diag(L, diag::note_insert_fallthrough_fixit) <<
1297 AnnotationSpelling <<
1301 S.
Diag(L, diag::note_insert_break_fixit) <<
1306 for (
const auto *F : FM.getFallthroughStmts())
1307 S.
Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);
1316 case Stmt::ForStmtClass:
1317 case Stmt::WhileStmtClass:
1318 case Stmt::CXXForRangeStmtClass:
1319 case Stmt::ObjCForCollectionStmtClass:
1321 case Stmt::DoStmtClass: {
1323 if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))
1325 return Result.
Val.
getInt().getBoolValue();
1342 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1351 for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
1353 const WeakUseVector &Uses = I->second;
1356 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1357 for ( ; UI != UE; ++UI) {
1370 if (UI == Uses.begin()) {
1371 WeakUseVector::const_iterator UI2 = UI;
1372 for (++UI2; UI2 != UE; ++UI2)
1373 if (UI2->isUnsafe())
1377 if (!
isInLoop(Ctx, PM, UI->getUseExpr()))
1380 const WeakObjectProfileTy &Profile = I->first;
1381 if (!Profile.isExactProfile())
1386 Base = Profile.getProperty();
1387 assert(Base &&
"A profile always has a base or property.");
1389 if (
const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1390 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1395 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
1398 if (UsesByStmt.empty())
1403 llvm::sort(UsesByStmt,
1404 [&SM](
const StmtUsesPair &LHS,
const StmtUsesPair &RHS) {
1406 RHS.first->getBeginLoc());
1421 if (isa<sema::BlockScopeInfo>(CurFn))
1422 FunctionKind = Block;
1423 else if (isa<sema::LambdaScopeInfo>(CurFn))
1424 FunctionKind = Lambda;
1425 else if (isa<ObjCMethodDecl>(D))
1426 FunctionKind = Method;
1428 FunctionKind = Function;
1431 for (
const auto &
P : UsesByStmt) {
1432 const Stmt *FirstRead =
P.first;
1433 const WeakObjectProfileTy &Key =
P.second->first;
1434 const WeakUseVector &Uses =
P.second->second;
1442 if (Key.isExactProfile())
1443 DiagKind = diag::warn_arc_repeated_use_of_weak;
1445 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1457 const NamedDecl *KeyProp = Key.getProperty();
1458 if (isa<VarDecl>(KeyProp))
1459 ObjectKind = Variable;
1460 else if (isa<ObjCPropertyDecl>(KeyProp))
1462 else if (isa<ObjCMethodDecl>(KeyProp))
1463 ObjectKind = ImplicitProperty;
1464 else if (isa<ObjCIvarDecl>(KeyProp))
1467 llvm_unreachable(
"Unexpected weak object kind!");
1472 if (Prop->hasAttr<IBOutletAttr>())
1477 <<
int(ObjectKind) << KeyProp << int(FunctionKind)
1481 for (
const auto &Use : Uses) {
1482 if (Use.getUseExpr() == FirstRead)
1484 S.
Diag(Use.getUseExpr()->getBeginLoc(),
1485 diag::note_arc_weak_also_accessed_here)
1486 << Use.getUseExpr()->getSourceRange();
1495 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1499 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1503 UninitValsDiagReporter(
Sema &S) : S(S) {}
1506 MappedType &getUses(
const VarDecl *vd) {
1507 MappedType &
V = uses[vd];
1508 if (!V.getPointer())
1509 V.setPointer(
new UsesVec());
1513 void handleUseOfUninitVariable(
const VarDecl *vd,
1515 getUses(vd).getPointer()->push_back(use);
1518 void handleSelfInit(
const VarDecl *vd)
override {
1519 getUses(vd).setInt(
true);
1523 for (
const auto &
P : uses) {
1525 const MappedType &
V =
P.second;
1527 UsesVec *vec = V.getPointer();
1528 bool hasSelfInit = V.getInt();
1533 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1542 llvm::sort(vec->begin(), vec->end(),
1550 for (
const auto &U : *vec) {
1569 static bool hasAlwaysUninitializedUse(
const UsesVec* vec) {
1570 return std::any_of(vec->begin(), vec->end(), [](
const UninitUse &U) {
1582 typedef std::pair<PartialDiagnosticAt, OptionalNotes>
DelayedDiag;
1583 typedef std::list<DelayedDiag>
DiagList;
1585 struct SortDiagBySourceLocation {
1589 bool operator()(
const DelayedDiag &left,
const DelayedDiag &right) {
1602 namespace threadSafety {
1613 if (Verbose && CurrentFunction) {
1615 S.
PDiag(diag::note_thread_warning_in_fun)
1616 << CurrentFunction);
1624 if (Verbose && CurrentFunction) {
1626 S.
PDiag(diag::note_thread_warning_in_fun)
1627 << CurrentFunction);
1628 ONS.push_back(std::move(FNote));
1636 ONS.push_back(Note1);
1637 ONS.push_back(Note2);
1638 if (Verbose && CurrentFunction) {
1640 S.
PDiag(diag::note_thread_warning_in_fun)
1641 << CurrentFunction);
1642 ONS.push_back(std::move(FNote));
1650 LocLocked, S.
PDiag(diag::note_locked_here) <<
Kind))
1656 : S(S), FunLocation(FL), FunEndLocation(FEL),
1657 CurrentFunction(
nullptr), Verbose(
false) {}
1659 void setVerbose(
bool b) { Verbose =
b; }
1667 for (
const auto &
Diag : Warnings) {
1669 for (
const auto &Note :
Diag.second)
1670 S.
Diag(Note.first, Note.second);
1674 void handleInvalidLockExp(StringRef Kind,
SourceLocation Loc)
override {
1677 Warnings.emplace_back(std::move(
Warning), getNotes());
1680 void handleUnmatchedUnlock(StringRef Kind, Name LockName,
1685 << Kind << LockName);
1686 Warnings.emplace_back(std::move(
Warning), getNotes());
1689 void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
1694 LocUnlock = FunLocation;
1696 LocUnlock, S.
PDiag(diag::warn_unlock_kind_mismatch)
1697 << Kind << LockName << Received << Expected);
1698 Warnings.emplace_back(std::move(
Warning),
1699 makeLockedHereNote(LocLocked, Kind));
1702 void handleDoubleLock(StringRef Kind, Name LockName,
SourceLocation LocLocked,
1705 LocDoubleLock = FunLocation;
1707 << Kind << LockName);
1708 Warnings.emplace_back(std::move(
Warning),
1709 makeLockedHereNote(LocLocked, Kind));
1712 void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
1716 unsigned DiagID = 0;
1719 DiagID = diag::warn_lock_some_predecessors;
1722 DiagID = diag::warn_expecting_lock_held_on_loop;
1725 DiagID = diag::warn_no_unlock;
1728 DiagID = diag::warn_expecting_locked;
1732 LocEndOfScope = FunEndLocation;
1736 Warnings.emplace_back(std::move(
Warning),
1737 makeLockedHereNote(LocLocked, Kind));
1740 void handleExclusiveAndShared(StringRef Kind, Name LockName,
1744 S.
PDiag(diag::warn_lock_exclusive_and_shared)
1745 << Kind << LockName);
1747 << Kind << LockName);
1748 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1751 void handleNoMutexHeld(StringRef Kind,
const NamedDecl *D,
1755 "Only works for variables");
1757 diag::warn_variable_requires_any_lock:
1758 diag::warn_var_deref_requires_any_lock;
1761 Warnings.emplace_back(std::move(
Warning), getNotes());
1764 void handleMutexNotHeld(StringRef Kind,
const NamedDecl *D,
1767 Name *PossibleMatch)
override {
1768 unsigned DiagID = 0;
1769 if (PossibleMatch) {
1772 DiagID = diag::warn_variable_requires_lock_precise;
1775 DiagID = diag::warn_var_deref_requires_lock_precise;
1778 DiagID = diag::warn_fun_requires_lock_precise;
1781 DiagID = diag::warn_guarded_pass_by_reference;
1784 DiagID = diag::warn_pt_guarded_pass_by_reference;
1794 S.
PDiag(diag::note_guarded_by_declared_here)
1796 Warnings.emplace_back(std::move(
Warning), getNotes(Note, VNote));
1798 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1802 DiagID = diag::warn_variable_requires_lock;
1805 DiagID = diag::warn_var_deref_requires_lock;
1808 DiagID = diag::warn_fun_requires_lock;
1811 DiagID = diag::warn_guarded_pass_by_reference;
1814 DiagID = diag::warn_pt_guarded_pass_by_reference;
1822 S.
PDiag(diag::note_guarded_by_declared_here));
1823 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1825 Warnings.emplace_back(std::move(
Warning), getNotes());
1829 void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
1832 S.
PDiag(diag::warn_acquire_requires_negative_cap)
1833 << Kind << LockName << Neg);
1834 Warnings.emplace_back(std::move(
Warning), getNotes());
1837 void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
1840 << Kind << FunName << LockName);
1841 Warnings.emplace_back(std::move(
Warning), getNotes());
1844 void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
1847 S.
PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
1848 Warnings.emplace_back(std::move(
Warning), getNotes());
1851 void handleBeforeAfterCycle(Name L1Name,
SourceLocation Loc)
override {
1853 S.
PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
1854 Warnings.emplace_back(std::move(
Warning), getNotes());
1858 CurrentFunction = FD;
1862 CurrentFunction =
nullptr;
1874 namespace consumed {
1876 class ConsumedWarningsHandler :
public ConsumedWarningsHandlerBase {
1883 ConsumedWarningsHandler(
Sema &S) : S(S) {}
1887 for (
const auto &
Diag : Warnings) {
1889 for (
const auto &
Note :
Diag.second)
1895 StringRef VariableName)
override {
1903 StringRef VariableName,
1904 StringRef ExpectedState,
1905 StringRef ObservedState)
override {
1908 diag::warn_param_return_typestate_mismatch) << VariableName <<
1909 ExpectedState << ObservedState);
1914 void warnParamTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1915 StringRef ObservedState)
override {
1918 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
1924 StringRef TypeName)
override {
1926 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
1931 void warnReturnTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1932 StringRef ObservedState)
override {
1935 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
1940 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef
State,
1944 diag::warn_use_of_temp_in_invalid_state) << MethodName <<
State);
1949 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
1953 MethodName << VariableName <<
State);
1968 enableCheckFallThrough = 1;
1969 enableCheckUnreachable = 0;
1970 enableThreadSafetyAnalysis = 0;
1971 enableConsumedAnalysis = 0;
1980 NumFunctionsAnalyzed(0),
1981 NumFunctionsWithBadCFGs(0),
1983 MaxCFGBlocksPerFunction(0),
1984 NumUninitAnalysisFunctions(0),
1985 NumUninitAnalysisVariables(0),
1986 MaxUninitAnalysisVariablesPerFunction(0),
1987 NumUninitAnalysisBlockVisits(0),
1988 MaxUninitAnalysisBlockVisitsPerFunction(0) {
1990 using namespace diag;
1993 DefaultPolicy.enableCheckUnreachable =
1996 isEnabled(D, warn_unreachable_return) ||
1997 isEnabled(D, warn_unreachable_loop_increment);
1999 DefaultPolicy.enableThreadSafetyAnalysis =
2002 DefaultPolicy.enableConsumedAnalysis =
2003 isEnabled(D, warn_use_in_invalid_state);
2008 S.
Diag(D.Loc, D.PD);
2031 if (cast<DeclContext>(D)->isDependentContext())
2062 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
2063 P.enableConsumedAnalysis) {
2081 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2089 bool analyzed =
false;
2093 for (
const Stmt *S : D.Stmts)
2100 bool AllReachable =
true;
2101 for (
const Stmt *S : D.Stmts) {
2111 AllReachable =
false;
2120 S.Diag(D.Loc, D.PD);
2129 if (P.enableCheckFallThrough) {
2130 const CheckFallThroughDiagnostics &CD =
2132 ? CheckFallThroughDiagnostics::MakeForBlock()
2133 : (isa<CXXMethodDecl>(D) &&
2134 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2135 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2136 ? CheckFallThroughDiagnostics::MakeForLambda()
2138 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2139 : CheckFallThroughDiagnostics::MakeForFunction(D)));
2144 if (P.enableCheckUnreachable) {
2150 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
2151 isTemplateInstantiation = Function->isTemplateInstantiation();
2152 if (!isTemplateInstantiation)
2157 if (P.enableThreadSafetyAnalysis) {
2160 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
2162 Reporter.setIssueBetaWarnings(
true);
2164 Reporter.setVerbose(
true);
2168 Reporter.emitDiagnostics();
2172 if (P.enableConsumedAnalysis) {
2173 consumed::ConsumedWarningsHandler WarningHandler(S);
2182 UninitValsDiagReporter reporter(S);
2189 ++NumUninitAnalysisFunctions;
2192 MaxUninitAnalysisVariablesPerFunction =
2193 std::max(MaxUninitAnalysisVariablesPerFunction,
2195 MaxUninitAnalysisBlockVisitsPerFunction =
2196 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
2202 bool FallThroughDiagFull =
2204 bool FallThroughDiagPerFunction = !Diags.
isIgnored(
2205 diag::warn_unannotated_fallthrough_per_function, D->
getBeginLoc());
2206 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
2217 if (!Diags.
isIgnored(diag::warn_infinite_recursive_function,
2219 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2226 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2232 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2239 ++NumFunctionsAnalyzed;
2244 MaxCFGBlocksPerFunction =
std::max(MaxCFGBlocksPerFunction,
2245 cfg->getNumBlockIDs());
2247 ++NumFunctionsWithBadCFGs;
2253 llvm::errs() <<
"\n*** Analysis Based Warnings Stats:\n";
2255 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
2256 unsigned AvgCFGBlocksPerFunction =
2257 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
2258 llvm::errs() << NumFunctionsAnalyzed <<
" functions analyzed (" 2259 << NumFunctionsWithBadCFGs <<
" w/o CFGs).\n" 2260 <<
" " << NumCFGBlocks <<
" CFG blocks built.\n" 2261 <<
" " << AvgCFGBlocksPerFunction
2262 <<
" average CFG blocks per function.\n" 2263 <<
" " << MaxCFGBlocksPerFunction
2264 <<
" max CFG blocks per function.\n";
2266 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
2267 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
2268 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
2269 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
2270 llvm::errs() << NumUninitAnalysisFunctions
2271 <<
" functions analyzed for uninitialiazed variables\n" 2272 <<
" " << NumUninitAnalysisVariables <<
" variables analyzed.\n" 2273 <<
" " << AvgUninitVariablesPerFunction
2274 <<
" average variables per function.\n" 2275 <<
" " << MaxUninitAnalysisVariablesPerFunction
2276 <<
" max variables per function.\n" 2277 <<
" " << NumUninitAnalysisBlockVisits <<
" block visits.\n" 2278 <<
" " << AvgUninitBlockVisitsPerFunction
2279 <<
" average block visits per function.\n" 2280 <<
" " << MaxUninitAnalysisBlockVisitsPerFunction
2281 <<
" max block visits per function.\n";
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...
Represents a function declaration or definition.
Passing a guarded variable by reference.
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.
A (possibly-)qualified type.
bool isBlockPointerType() const
SourceLocation getExprLoc() const
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
bool HasFallthroughStmt
Whether there is a fallthrough statement in this function.
const Expr * getSubExpr() const
const Stmt * getStmt() const
Stmt * getBody() const
Get the body of the Declaration.
succ_iterator succ_begin()
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Stmt - This represents one statement.
FunctionType - C99 6.7.5.3 - Function Declarators.
IfStmt - This represents an if/then/else.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Defines the SourceManager interface.
static void diagnoseRepeatedUseOfWeak(Sema &S, const sema::FunctionScopeInfo *CurFn, const Decl *D, const ParentMap &PM)
unsigned getBlockID() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Decl - This represents one declaration (or definition), e.g.
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
SourceLocation getBeginLoc() const LLVM_READONLY
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
Represents an attribute applied to a statement.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
bool getAddEHEdges() const
getAddEHEdges - Return true iff we are adding exceptional edges from callExprs.
const WeakObjectUseMap & getWeakObjectUses() const
The use is uninitialized whenever a certain branch is taken.
Stmt * getParent(Stmt *) const
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
AnalysisBasedWarnings(Sema &s)
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
SourceLocation getEndLoc() const LLVM_READONLY
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
bool getSuppressSystemWarnings() const
LockKind getLockKindFromAccessKind(AccessKind AK)
Helper function that returns a LockKind required for the given level of access.
unsigned IgnoreDefaultsWithCoveredEnums
static std::pair< const Stmt *, const CFGBlock * > getLastStmt(const ExplodedNode *Node)
ProtectedOperationKind
This enum distinguishes between different kinds of operations that may need to be protected by locks...
Retains information about a function, method, or block that is currently being parsed.
Represents a variable declaration or definition.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
ASTContext & getASTContext() const
const T * getAs() const
Member-template getAs<specific type>'.
ObjCMethodDecl - Represents an instance or class method declaration.
The use might be uninitialized.
Defines the Objective-C statement AST node classes.
A C++ throw-expression (C++ [except.throw]).
Defines the clang::Expr interface and subclasses for C++ expressions.
branch_iterator branch_end() const
LabelStmt - Represents a label, which has a substatement.
LockKind
This enum distinguishes between different kinds of lock actions.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Kind getKind() const
Get the kind of uninitialized use.
Expr * getFalseExpr() const
SourceLocation getBegin() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceLocation getBeginLoc() const LLVM_READONLY
branch_iterator branch_begin() const
Branches which inevitably result in the variable being used uninitialized.
AnalysisDeclContext contains the context data for the function or method under analysis.
threadSafety::BeforeSet * ThreadSafetyDeclCache
static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, bool PerFunction)
__DEVICE__ int max(int __a, int __b)
SourceLocation getBeginLoc() const LLVM_READONLY
const LangOptions & getLangOpts() const
AdjacentBlocks::const_iterator const_succ_iterator
TextDiagnosticBuffer::DiagList DiagList
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
APValue Val
Val - This is the value the expression can be folded to.
bool AddCXXDefaultInitExprInCtors
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
Concrete class used by the front-end to report problems and issues.
A builtin binary operation expression such as "x + y" or "x <= y".
static StringRef getFallthroughAttrSpelling(Preprocessor &PP, SourceLocation Loc)
SourceLocation getThrowLoc() const
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC)
CheckUnreachable - Check for unreachable code.
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC)...
__DEVICE__ void * memset(void *__a, int __b, size_t __c)
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
const LangOptions & getLangOpts() const
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification, if any.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD)
DiagnosticsEngine & getDiagnostics() const
Passing a pt-guarded variable by reference.
ConditionalOperator - The ?: ternary operator.
Sema - This implements semantic analysis and AST building for C.
Represents a prototype with parameter type info, e.g.
static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool alwaysReportSelfInit=false)
DiagnoseUninitializedUse – Helper function for diagnosing uses of an uninitialized variable...
Handler class for thread safety warnings.
static StringRef getOpcodeStr(Opcode Op)
getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to...
Represents a single basic block in a source-level CFG.
static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, const Stmt *S)
Dereferencing a variable (e.g. p in *p = 5;)
This represents one expression.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool hasUncompilableErrorOccurred() const
Errors that actually prevent compilation, not those that are upgraded from a warning by -Werror...
const T * castAs() const
Member-template castAs<specific type>.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Defines the clang::Preprocessor interface.
bool isCPUDispatchMultiVersion() const
True if this function is a multiversioned dispatch function as a part of the cpu_specific/cpu_dispatc...
Stores token information for comparing actual tokens with predefined values.
void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, AnalysisDeclContext &ac, UninitVariablesHandler &handler, UninitVariablesAnalysisStats &stats)
void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP, Callback &CB)
unsigned ScanReachableFromBlock(const CFGBlock *Start, llvm::BitVector &Reachable)
ScanReachableFromBlock - Mark all blocks reachable from Start.
std::pair< PartialDiagnosticAt, OptionalNotes > DelayedDiag
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
bool handlerCanCatch(QualType HandlerType, QualType ExceptionType)
AccessKind
This enum distinguishes between different ways to access (read or write) a variable.
SourceLocation getEnd() const
Making a function call (e.g. fool())
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Preprocessor & getPreprocessor() const
A use of a variable, which might be uninitialized.
The result type of a method or function.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
A type, stored as a Type*.
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
reverse_iterator rbegin()
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
SourceLocation getEndLoc() const LLVM_READONLY
static CharSourceRange getCharRange(SourceRange R)
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
QualType getCanonicalType() const
Reading or writing a variable (e.g. x in x = 5;)
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
ASTContext & getASTContext() const
Encodes a location in the source.
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
static void visitReachableThrows(CFG *BodyCFG, llvm::function_ref< void(const CXXThrowExpr *, CFGBlock &)> Visit)
SourceLocation getOperatorLoc() const
SourceLocation getBeginLoc() const LLVM_READONLY
static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc, const FunctionDecl *FD)
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
bool isReachable(const CFGBlock *Src, const CFGBlock *Dst)
Returns true if the block 'Dst' can be reached from block 'Src'.
Represents a call to a member function that may be written either with member call syntax (e...
llvm::iterator_range< capture_init_iterator > capture_inits()
Retrieve the initialization expressions for this lambda's captures.
bool PruneTriviallyFalseEdges
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs. ...
Represents a static or instance method of a struct/union/class.
bool isCFGBuilt() const
Returns true if we have built a CFG for this analysis context.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
bool CollectStats
Flag indicating whether or not to collect detailed statistics.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
const Decl * getDecl() const
static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD, AnalysisDeclContext &AC)
Represents one property declaration in an Objective-C interface.
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
static bool isLogicalOp(Opcode Opc)
static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR, AnalysisManager &AM, const ObjCAutoreleaseWriteChecker *Checker)
BuildOptions & setAllAlwaysAdd()
The use is uninitialized the first time it is reached after we reach the variable's declaration...
std::string getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const
Get a string to suggest for zero-initialization of a type.
static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag)
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
bool getIgnoreAllWarnings() const
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...
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
pred_iterator pred_begin()
SmallVectorImpl< Branch >::const_iterator branch_iterator
Dataflow Directional Tag Classes.
CFG::BuildOptions & getCFGBuildOptions()
Return the build options used to construct the CFG.
bool isValid() const
Return true if this is a valid SourceLocation object.
EvalResult is a struct with detailed info about an evaluated expression.
void runThreadSafetyAnalysis(AnalysisDeclContext &AC, ThreadSafetyHandler &Handler, BeforeSet **Bset)
Check a function's CFG for thread-safety violations.
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 FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
const Expr * getInit() const
static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg)
StmtClass getStmtClass() const
Represents a simple identification of a weak object.
Stmt * getTerminatorStmt()
A class that handles the analysis of uniqueness violations.
bool hasObjCLifetime() const
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
static bool isNoexcept(const FunctionDecl *FD)
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
SwitchStmt - This represents a 'switch' stmt.
The standard open() call: int open(const char *path, int oflag, ...);.
UnreachableKind
Classifications of unreachable code.
const Expr * getUser() const
Get the expression containing the uninitialized use.
The use is always uninitialized.
TypeSourceInfo * getTypeSourceInfo() const
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 void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, const Stmt *Body, AnalysisDeclContext &AC)
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.
static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope)
bool hasNoReturnElement() const
SmallVector< PartialDiagnosticAt, 1 > OptionalNotes
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Defines the clang::SourceLocation class and associated facilities.
SmallVector< PossiblyUnreachableDiag, 4 > PossiblyUnreachableDiags
A list of PartialDiagnostics created but delayed within the current function scope.
CFGCallback defines methods that should be called when a logical operator error is found when buildin...
Expr * getTrueExpr() const
void run(AnalysisDeclContext &AC)
Check a function's CFG for consumed violations.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Represents a top-level expression in a basic block.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string...
capture_range captures() const
Retrieve this lambda's captures.
SourceManager & getSourceManager() const
static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC)
CheckFallThrough - Check that we don't fall off the end of a Statement that should return a value...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
The use is uninitialized the first time it is reached after the function is called.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
void registerForcedBlockExpression(const Stmt *stmt)
SourceLocation getBeginLoc() const LLVM_READONLY
llvm::SmallDenseMap< WeakObjectProfileTy, WeakUseVector, 8, WeakObjectProfileTy::DenseMapInfo > WeakObjectUseMap
Used to collect all uses of weak objects in a function body.
A reference to a declared variable, function, enum, etc.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
SourceManager & SourceMgr
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
unsigned NumVariablesAnalyzed
ParentMap & getParentMap()
A trivial tuple used to represent a source range.
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
This represents a decl that may have a name.
void IssueWarnings(Policy P, FunctionScopeInfo *fscope, const Decl *D, QualType BlockType)
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block)
This class handles loading and caching of source files into memory.
SourceLocation getLocation() const
QualType getType() const
Return the type wrapped by this type source info.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.