40 #include "llvm/ADT/BitVector.h" 41 #include "llvm/ADT/MapVector.h" 42 #include "llvm/ADT/SmallString.h" 43 #include "llvm/ADT/SmallVector.h" 44 #include "llvm/ADT/StringRef.h" 45 #include "llvm/Support/Casting.h" 50 using namespace clang;
62 UnreachableCodeHandler(
Sema &s) : S(s) {}
71 if (PreviousSilenceableCondVal.
isValid() &&
73 PreviousSilenceableCondVal == SilenceableCondVal)
75 PreviousSilenceableCondVal = SilenceableCondVal;
77 unsigned diag = diag::warn_unreachable;
80 diag = diag::warn_unreachable_break;
83 diag = diag::warn_unreachable_return;
86 diag = diag::warn_unreachable_loop_increment;
92 S.
Diag(L, diag) << R1 << R2;
99 S.
Diag(Open, diag::note_unreachable_silence)
120 UnreachableCodeHandler UC(S);
132 static bool HasMacroID(
const Expr *E) {
138 if (
const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
139 if (HasMacroID(SubExpr))
145 void compareAlwaysTrue(
const BinaryOperator *B,
bool isAlwaysTrue)
override {
150 S.
Diag(B->
getExprLoc(), diag::warn_tautological_overlap_comparison)
151 << DiagRange << isAlwaysTrue;
155 bool isAlwaysTrue)
override {
161 << DiagRange << isAlwaysTrue;
175 for (
const auto &B : Block) {
189 isa<TemplateSpecializationType>(NNS->getAsType())) {
205 llvm::SmallPtrSet<CFGBlock *, 16> Visited;
208 bool foundRecursion =
false;
213 WorkList.push_back(&cfg->
getEntry());
215 while (!WorkList.empty()) {
216 CFGBlock *Block = WorkList.pop_back_val();
220 if (!Visited.insert(SuccBlock).second)
224 if (ExitID == SuccBlock->getBlockID())
229 foundRecursion =
true;
233 WorkList.push_back(SuccBlock);
237 return foundRecursion;
269 Stack.push_back(&ThrowBlock);
272 while (!Stack.empty()) {
273 CFGBlock &UnwindBlock = *Stack.back();
276 for (
auto &Succ : UnwindBlock.
succs()) {
277 if (!Succ.isReachable() || Queued[Succ->getBlockID()])
284 dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
285 QualType Caught = Catch->getCaughtType();
292 Stack.push_back(Succ);
293 Queued[Succ->getBlockID()] =
true;
307 if (!Reachable[B->getBlockID()])
313 if (
auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
323 S.
Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
325 (isa<CXXDestructorDecl>(FD) ||
329 getAs<FunctionProtoType>())
331 << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
354 if (FPT->isNothrow() || FD->
hasAttr<NoThrowAttr>())
395 for (
const auto *B : *cfg) {
396 if (!live[B->getBlockID()]) {
397 if (B->pred_begin() == B->pred_end()) {
398 if (B->getTerminator() && isa<CXXTryStmt>(B->getTerminator()))
410 bool HasLiveReturn =
false;
411 bool HasFakeEdge =
false;
412 bool HasPlainEdge =
false;
413 bool HasAbnormalEdge =
false;
421 cfg->getExit().filtered_pred_start_end(FO);
431 HasAbnormalEdge =
true;
440 for ( ; ri != re ; ++ri)
447 HasAbnormalEdge =
true;
457 if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
458 HasLiveReturn =
true;
461 if (isa<ObjCAtThrowStmt>(S)) {
465 if (isa<CXXThrowExpr>(S)) {
469 if (isa<MSAsmStmt>(S)) {
472 HasLiveReturn =
true;
475 if (isa<CXXTryStmt>(S)) {
476 HasAbnormalEdge =
true;
481 HasAbnormalEdge =
true;
492 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
502 struct CheckFallThroughDiagnostics {
503 unsigned diag_MaybeFallThrough_HasNoReturn;
504 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
505 unsigned diag_AlwaysFallThrough_HasNoReturn;
506 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
507 unsigned diag_NeverFallThroughOrReturn;
508 enum { Function, Block, Lambda, Coroutine } funMode;
511 static CheckFallThroughDiagnostics MakeForFunction(
const Decl *Func) {
512 CheckFallThroughDiagnostics D;
514 D.diag_MaybeFallThrough_HasNoReturn =
515 diag::warn_falloff_noreturn_function;
516 D.diag_MaybeFallThrough_ReturnsNonVoid =
517 diag::warn_maybe_falloff_nonvoid_function;
518 D.diag_AlwaysFallThrough_HasNoReturn =
519 diag::warn_falloff_noreturn_function;
520 D.diag_AlwaysFallThrough_ReturnsNonVoid =
521 diag::warn_falloff_nonvoid_function;
525 bool isVirtualMethod =
false;
526 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
527 isVirtualMethod = Method->isVirtual();
531 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
532 isTemplateInstantiation = Function->isTemplateInstantiation();
534 if (!isVirtualMethod && !isTemplateInstantiation)
535 D.diag_NeverFallThroughOrReturn =
536 diag::warn_suggest_noreturn_function;
538 D.diag_NeverFallThroughOrReturn = 0;
540 D.funMode = Function;
544 static CheckFallThroughDiagnostics MakeForCoroutine(
const Decl *Func) {
545 CheckFallThroughDiagnostics D;
547 D.diag_MaybeFallThrough_HasNoReturn = 0;
548 D.diag_MaybeFallThrough_ReturnsNonVoid =
549 diag::warn_maybe_falloff_nonvoid_coroutine;
550 D.diag_AlwaysFallThrough_HasNoReturn = 0;
551 D.diag_AlwaysFallThrough_ReturnsNonVoid =
552 diag::warn_falloff_nonvoid_coroutine;
553 D.funMode = Coroutine;
557 static CheckFallThroughDiagnostics MakeForBlock() {
558 CheckFallThroughDiagnostics D;
559 D.diag_MaybeFallThrough_HasNoReturn =
560 diag::err_noreturn_block_has_return_expr;
561 D.diag_MaybeFallThrough_ReturnsNonVoid =
562 diag::err_maybe_falloff_nonvoid_block;
563 D.diag_AlwaysFallThrough_HasNoReturn =
564 diag::err_noreturn_block_has_return_expr;
565 D.diag_AlwaysFallThrough_ReturnsNonVoid =
566 diag::err_falloff_nonvoid_block;
567 D.diag_NeverFallThroughOrReturn = 0;
572 static CheckFallThroughDiagnostics MakeForLambda() {
573 CheckFallThroughDiagnostics D;
574 D.diag_MaybeFallThrough_HasNoReturn =
575 diag::err_noreturn_lambda_has_return_expr;
576 D.diag_MaybeFallThrough_ReturnsNonVoid =
577 diag::warn_maybe_falloff_nonvoid_lambda;
578 D.diag_AlwaysFallThrough_HasNoReturn =
579 diag::err_noreturn_lambda_has_return_expr;
580 D.diag_AlwaysFallThrough_ReturnsNonVoid =
581 diag::warn_falloff_nonvoid_lambda;
582 D.diag_NeverFallThroughOrReturn = 0;
588 bool HasNoReturn)
const {
589 if (funMode == Function) {
590 return (ReturnsVoid ||
591 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function,
594 D.
isIgnored(diag::warn_noreturn_function_has_return_expr,
597 D.
isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
599 if (funMode == Coroutine) {
600 return (ReturnsVoid ||
601 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
602 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
607 return ReturnsVoid && !HasNoReturn;
619 const CheckFallThroughDiagnostics &CD,
623 bool ReturnsVoid =
false;
624 bool HasNoReturn =
false;
627 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
628 if (
const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
629 ReturnsVoid = CBody->getFallthroughHandler() !=
nullptr;
631 ReturnsVoid = FD->getReturnType()->isVoidType();
632 HasNoReturn = FD->isNoReturn();
634 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
635 ReturnsVoid = MD->getReturnType()->isVoidType();
636 HasNoReturn = MD->hasAttr<NoReturnAttr>();
638 else if (isa<BlockDecl>(D)) {
642 if (FT->getReturnType()->isVoidType())
644 if (FT->getNoReturnAttr())
652 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
673 EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
674 else if (!ReturnsVoid)
675 EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
679 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
680 else if (!ReturnsVoid)
681 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
684 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
685 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
686 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
687 }
else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
688 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
690 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
715 : Inherited(Context), FoundReference(
false), Needle(Needle) {}
717 void VisitExpr(
const Expr *E) {
722 Inherited::VisitExpr(E);
727 FoundReference =
true;
729 Inherited::VisitDeclRefExpr(E);
732 bool doesContainReference()
const {
return FoundReference; }
740 S.
Diag(VD->
getLocation(), diag::note_block_var_fixit_add_initialization)
761 S.
Diag(Loc, diag::note_var_fixit_add_initialization) << VD->
getDeclName()
769 const Stmt *Else,
bool CondVal,
795 bool IsCapturedByBlock) {
796 bool Diagnosed =
false;
829 const Stmt *Term = I->Terminator;
839 int RemoveDiagKind = -1;
840 const char *FixitStr =
841 S.
getLangOpts().CPlusPlus ? (I->Output ?
"true" :
"false")
842 : (I->Output ?
"1" :
"0");
845 switch (Term ? Term->
getStmtClass() : Stmt::DeclStmtClass) {
852 case Stmt::IfStmtClass: {
853 const IfStmt *IS = cast<IfStmt>(Term);
859 I->Output, Fixit1, Fixit2);
862 case Stmt::ConditionalOperatorClass: {
869 I->Output, Fixit1, Fixit2);
872 case Stmt::BinaryOperatorClass: {
880 if ((BO->
getOpcode() == BO_LAnd && I->Output) ||
881 (BO->
getOpcode() == BO_LOr && !I->Output))
892 case Stmt::WhileStmtClass:
895 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
899 case Stmt::ForStmtClass:
902 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
909 case Stmt::CXXForRangeStmtClass:
910 if (I->Output == 1) {
918 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
922 case Stmt::DoStmtClass:
925 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
931 case Stmt::CaseStmtClass:
934 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
936 case Stmt::DefaultStmtClass:
939 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
943 S.
Diag(Range.
getBegin(), diag::warn_sometimes_uninit_var)
944 << VD->
getDeclName() << IsCapturedByBlock << DiagKind
945 << Str << I->Output << Range;
946 S.
Diag(User->getLocStart(), diag::note_uninit_var_use)
947 << IsCapturedByBlock << User->getSourceRange();
948 if (RemoveDiagKind != -1)
950 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
968 bool alwaysReportSelfInit =
false) {
982 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
985 ContainsReference CR(S.
Context, DRE);
986 CR.Visit(Initializer);
987 if (CR.doesContainReference()) {
988 S.
Diag(DRE->getLocStart(),
989 diag::warn_uninit_self_reference_in_init)
1000 diag::warn_uninit_byref_blockvar_captured_by_block)
1019 FallthroughMapper(
Sema &S)
1020 : FoundSwitchStatements(
false),
1024 bool foundSwitchStatements()
const {
return FoundSwitchStatements; }
1027 bool Found = FallthroughStmts.erase(Stmt);
1032 typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;
1034 const AttrStmts &getFallthroughStmts()
const {
1035 return FallthroughStmts;
1038 void fillReachableBlocks(
CFG *Cfg) {
1039 assert(ReachableBlocks.empty() &&
"ReachableBlocks already filled");
1040 std::deque<const CFGBlock *> BlockQueue;
1042 ReachableBlocks.insert(&Cfg->
getEntry());
1043 BlockQueue.push_back(&Cfg->
getEntry());
1048 for (
const auto *B : *Cfg) {
1049 const Stmt *L = B->getLabel();
1050 if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1051 BlockQueue.push_back(B);
1054 while (!BlockQueue.empty()) {
1056 BlockQueue.pop_front();
1060 if (*I && ReachableBlocks.insert(*I).second)
1061 BlockQueue.push_back(*I);
1066 bool checkFallThroughIntoBlock(
const CFGBlock &B,
int &AnnotatedCnt,
1067 bool IsTemplateInstantiation) {
1068 assert(!ReachableBlocks.empty() &&
"ReachableBlocks empty");
1070 int UnannotatedCnt = 0;
1074 while (!BlockQueue.empty()) {
1076 BlockQueue.pop_front();
1080 if (Term && isa<SwitchStmt>(Term))
1091 if (!ReachableBlocks.count(P)) {
1093 ElemEnd = P->
rend();
1094 ElemIt != ElemEnd; ++ElemIt) {
1096 if (
const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1100 if (!IsTemplateInstantiation)
1101 S.
Diag(AS->getLocStart(),
1102 diag::warn_fallthrough_attr_unreachable);
1103 markFallthroughVisited(AS);
1123 markFallthroughVisited(AS);
1131 std::back_inserter(BlockQueue));
1137 return !!UnannotatedCnt;
1141 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1144 if (asFallThroughAttr(S))
1145 FallthroughStmts.insert(S);
1150 FoundSwitchStatements =
true;
1156 bool TraverseDecl(
Decl *D) {
return true; }
1159 bool TraverseLambdaBody(
LambdaExpr *LE) {
return true; }
1164 if (
const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1165 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1176 ElemIt != ElemEnd; ++ElemIt) {
1178 return CS->getStmt();
1184 if (!isa<SwitchCase>(SW->getSubStmt()))
1185 return SW->getSubStmt();
1190 bool FoundSwitchStatements;
1191 AttrStmts FallthroughStmts;
1193 llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
1200 tok::l_square, tok::l_square,
1202 tok::r_square, tok::r_square
1208 tok::r_square, tok::r_square
1211 bool PreferClangAttr = !PP.
getLangOpts().CPlusPlus17;
1213 StringRef MacroName;
1214 if (PreferClangAttr)
1216 if (MacroName.empty())
1218 if (MacroName.empty() && !PreferClangAttr)
1220 if (MacroName.empty())
1221 MacroName = PreferClangAttr ?
"[[clang::fallthrough]]" :
"[[fallthrough]]";
1238 FallthroughMapper FM(S);
1239 FM.TraverseStmt(AC.
getBody());
1241 if (!FM.foundSwitchStatements())
1244 if (PerFunction && FM.getFallthroughStmts().empty())
1252 FM.fillReachableBlocks(Cfg);
1254 for (
const CFGBlock *B : llvm::reverse(*Cfg)) {
1257 if (!Label || !isa<SwitchCase>(Label))
1262 bool IsTemplateInstantiation =
false;
1264 IsTemplateInstantiation = Function->isTemplateInstantiation();
1265 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1266 IsTemplateInstantiation))
1270 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1271 : diag::warn_unannotated_fallthrough);
1273 if (!AnnotatedCnt) {
1278 const Stmt *Term = B->getTerminator();
1280 while (B->empty() && !Term && B->succ_size() == 1) {
1281 B = *B->succ_begin();
1282 Term = B->getTerminator();
1284 if (!(B->empty() && Term && isa<BreakStmt>(Term))) {
1288 TextToInsert +=
"; ";
1289 S.
Diag(L, diag::note_insert_fallthrough_fixit) <<
1290 AnnotationSpelling <<
1294 S.
Diag(L, diag::note_insert_break_fixit) <<
1299 for (
const auto *F : FM.getFallthroughStmts())
1300 S.
Diag(F->getLocStart(), diag::err_fallthrough_attr_invalid_placement);
1309 case Stmt::ForStmtClass:
1310 case Stmt::WhileStmtClass:
1311 case Stmt::CXXForRangeStmtClass:
1312 case Stmt::ObjCForCollectionStmtClass:
1314 case Stmt::DoStmtClass: {
1315 const Expr *Cond = cast<DoStmt>(S)->getCond();
1319 return Val.getBoolValue();
1336 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1345 for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
1347 const WeakUseVector &Uses = I->second;
1350 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1351 for ( ; UI != UE; ++UI) {
1364 if (UI == Uses.begin()) {
1365 WeakUseVector::const_iterator UI2 = UI;
1366 for (++UI2; UI2 != UE; ++UI2)
1367 if (UI2->isUnsafe())
1371 if (!
isInLoop(Ctx, PM, UI->getUseExpr()))
1374 const WeakObjectProfileTy &Profile = I->first;
1375 if (!Profile.isExactProfile())
1380 Base = Profile.getProperty();
1381 assert(Base &&
"A profile always has a base or property.");
1383 if (
const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1384 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1389 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
1392 if (UsesByStmt.empty())
1397 llvm::sort(UsesByStmt.begin(), UsesByStmt.end(),
1398 [&
SM](
const StmtUsesPair &LHS,
const StmtUsesPair &RHS) {
1400 RHS.first->getLocStart());
1415 if (isa<sema::BlockScopeInfo>(CurFn))
1416 FunctionKind = Block;
1417 else if (isa<sema::LambdaScopeInfo>(CurFn))
1418 FunctionKind = Lambda;
1419 else if (isa<ObjCMethodDecl>(D))
1420 FunctionKind = Method;
1422 FunctionKind = Function;
1425 for (
const auto &
P : UsesByStmt) {
1426 const Stmt *FirstRead =
P.first;
1427 const WeakObjectProfileTy &Key =
P.second->first;
1428 const WeakUseVector &Uses =
P.second->second;
1436 if (Key.isExactProfile())
1437 DiagKind = diag::warn_arc_repeated_use_of_weak;
1439 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1451 const NamedDecl *KeyProp = Key.getProperty();
1452 if (isa<VarDecl>(KeyProp))
1453 ObjectKind = Variable;
1454 else if (isa<ObjCPropertyDecl>(KeyProp))
1456 else if (isa<ObjCMethodDecl>(KeyProp))
1457 ObjectKind = ImplicitProperty;
1458 else if (isa<ObjCIvarDecl>(KeyProp))
1461 llvm_unreachable(
"Unexpected weak object kind!");
1466 if (Prop->hasAttr<IBOutletAttr>())
1471 <<
int(ObjectKind) << KeyProp << int(FunctionKind)
1475 for (
const auto &Use : Uses) {
1476 if (Use.getUseExpr() == FirstRead)
1478 S.
Diag(Use.getUseExpr()->getLocStart(),
1479 diag::note_arc_weak_also_accessed_here)
1480 << Use.getUseExpr()->getSourceRange();
1489 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1493 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1497 UninitValsDiagReporter(
Sema &S) : S(S) {}
1500 MappedType &getUses(
const VarDecl *vd) {
1501 MappedType &V = uses[vd];
1502 if (!V.getPointer())
1503 V.setPointer(
new UsesVec());
1507 void handleUseOfUninitVariable(
const VarDecl *vd,
1509 getUses(vd).getPointer()->push_back(use);
1512 void handleSelfInit(
const VarDecl *vd)
override {
1513 getUses(vd).setInt(
true);
1517 for (
const auto &
P : uses) {
1519 const MappedType &V =
P.second;
1521 UsesVec *vec = V.getPointer();
1522 bool hasSelfInit = V.getInt();
1527 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1536 llvm::sort(vec->begin(), vec->end(),
1539 if (a.
getKind() != b.getKind())
1540 return a.
getKind() > b.getKind();
1544 for (
const auto &U : *vec) {
1563 static bool hasAlwaysUninitializedUse(
const UsesVec* vec) {
1564 return std::any_of(vec->begin(), vec->end(), [](
const UninitUse &U) {
1576 typedef std::pair<PartialDiagnosticAt, OptionalNotes>
DelayedDiag;
1577 typedef std::list<DelayedDiag>
DiagList;
1579 struct SortDiagBySourceLocation {
1583 bool operator()(
const DelayedDiag &left,
const DelayedDiag &right) {
1596 namespace threadSafety {
1607 if (Verbose && CurrentFunction) {
1609 S.
PDiag(diag::note_thread_warning_in_fun)
1610 << CurrentFunction);
1618 if (Verbose && CurrentFunction) {
1620 S.
PDiag(diag::note_thread_warning_in_fun)
1621 << CurrentFunction);
1622 ONS.push_back(std::move(FNote));
1630 ONS.push_back(Note1);
1631 ONS.push_back(Note2);
1632 if (Verbose && CurrentFunction) {
1634 S.
PDiag(diag::note_thread_warning_in_fun)
1635 << CurrentFunction);
1636 ONS.push_back(std::move(FNote));
1642 void warnLockMismatch(
unsigned DiagID, StringRef
Kind, Name LockName,
1649 Warnings.emplace_back(std::move(
Warning), getNotes());
1654 : S(S), FunLocation(FL), FunEndLocation(FEL),
1655 CurrentFunction(
nullptr), Verbose(
false) {}
1657 void setVerbose(
bool b) { Verbose = b; }
1665 for (
const auto &
Diag : Warnings) {
1667 for (
const auto &Note :
Diag.second)
1668 S.
Diag(Note.first, Note.second);
1672 void handleInvalidLockExp(StringRef Kind,
SourceLocation Loc)
override {
1675 Warnings.emplace_back(std::move(
Warning), getNotes());
1678 void handleUnmatchedUnlock(StringRef Kind, Name LockName,
1680 warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc);
1683 void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
1689 << Kind << LockName << Received
1691 Warnings.emplace_back(std::move(
Warning), getNotes());
1694 void handleDoubleLock(StringRef Kind, Name LockName,
SourceLocation Loc)
override {
1695 warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc);
1698 void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
1702 unsigned DiagID = 0;
1705 DiagID = diag::warn_lock_some_predecessors;
1708 DiagID = diag::warn_expecting_lock_held_on_loop;
1711 DiagID = diag::warn_no_unlock;
1714 DiagID = diag::warn_expecting_locked;
1718 LocEndOfScope = FunEndLocation;
1725 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1728 Warnings.emplace_back(std::move(
Warning), getNotes());
1731 void handleExclusiveAndShared(StringRef Kind, Name LockName,
1735 S.
PDiag(diag::warn_lock_exclusive_and_shared)
1736 << Kind << LockName);
1738 << Kind << LockName);
1739 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1742 void handleNoMutexHeld(StringRef Kind,
const NamedDecl *D,
1746 "Only works for variables");
1748 diag::warn_variable_requires_any_lock:
1749 diag::warn_var_deref_requires_any_lock;
1752 Warnings.emplace_back(std::move(
Warning), getNotes());
1755 void handleMutexNotHeld(StringRef Kind,
const NamedDecl *D,
1758 Name *PossibleMatch)
override {
1759 unsigned DiagID = 0;
1760 if (PossibleMatch) {
1763 DiagID = diag::warn_variable_requires_lock_precise;
1766 DiagID = diag::warn_var_deref_requires_lock_precise;
1769 DiagID = diag::warn_fun_requires_lock_precise;
1772 DiagID = diag::warn_guarded_pass_by_reference;
1775 DiagID = diag::warn_pt_guarded_pass_by_reference;
1785 S.
PDiag(diag::note_guarded_by_declared_here)
1787 Warnings.emplace_back(std::move(
Warning), getNotes(Note, VNote));
1789 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1793 DiagID = diag::warn_variable_requires_lock;
1796 DiagID = diag::warn_var_deref_requires_lock;
1799 DiagID = diag::warn_fun_requires_lock;
1802 DiagID = diag::warn_guarded_pass_by_reference;
1805 DiagID = diag::warn_pt_guarded_pass_by_reference;
1813 S.
PDiag(diag::note_guarded_by_declared_here));
1814 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1816 Warnings.emplace_back(std::move(
Warning), getNotes());
1820 void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
1823 S.
PDiag(diag::warn_acquire_requires_negative_cap)
1824 << Kind << LockName << Neg);
1825 Warnings.emplace_back(std::move(
Warning), getNotes());
1828 void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
1831 << Kind << FunName << LockName);
1832 Warnings.emplace_back(std::move(
Warning), getNotes());
1835 void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
1838 S.
PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
1839 Warnings.emplace_back(std::move(
Warning), getNotes());
1842 void handleBeforeAfterCycle(Name L1Name,
SourceLocation Loc)
override {
1844 S.
PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
1845 Warnings.emplace_back(std::move(
Warning), getNotes());
1849 CurrentFunction = FD;
1853 CurrentFunction =
nullptr;
1865 namespace consumed {
1867 class ConsumedWarningsHandler :
public ConsumedWarningsHandlerBase {
1874 ConsumedWarningsHandler(
Sema &S) : S(S) {}
1878 for (
const auto &
Diag : Warnings) {
1880 for (
const auto &
Note :
Diag.second)
1886 StringRef VariableName)
override {
1894 StringRef VariableName,
1895 StringRef ExpectedState,
1896 StringRef ObservedState)
override {
1899 diag::warn_param_return_typestate_mismatch) << VariableName <<
1900 ExpectedState << ObservedState);
1905 void warnParamTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1906 StringRef ObservedState)
override {
1909 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
1915 StringRef TypeName)
override {
1917 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
1922 void warnReturnTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1923 StringRef ObservedState)
override {
1926 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
1931 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef
State,
1935 diag::warn_use_of_temp_in_invalid_state) << MethodName <<
State);
1940 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
1944 MethodName << VariableName <<
State);
1959 enableCheckFallThrough = 1;
1960 enableCheckUnreachable = 0;
1961 enableThreadSafetyAnalysis = 0;
1962 enableConsumedAnalysis = 0;
1971 NumFunctionsAnalyzed(0),
1972 NumFunctionsWithBadCFGs(0),
1974 MaxCFGBlocksPerFunction(0),
1975 NumUninitAnalysisFunctions(0),
1976 NumUninitAnalysisVariables(0),
1977 MaxUninitAnalysisVariablesPerFunction(0),
1978 NumUninitAnalysisBlockVisits(0),
1979 MaxUninitAnalysisBlockVisitsPerFunction(0) {
1981 using namespace diag;
1984 DefaultPolicy.enableCheckUnreachable =
1987 isEnabled(D, warn_unreachable_return) ||
1988 isEnabled(D, warn_unreachable_loop_increment);
1990 DefaultPolicy.enableThreadSafetyAnalysis =
1993 DefaultPolicy.enableConsumedAnalysis =
1994 isEnabled(D, warn_use_in_invalid_state);
1999 S.
Diag(D.Loc, D.PD);
2022 if (cast<DeclContext>(D)->isDependentContext())
2053 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
2054 P.enableConsumedAnalysis) {
2071 std::unique_ptr<LogicalErrorHandler> LEH;
2072 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2074 LEH.reset(
new LogicalErrorHandler(S));
2080 bool analyzed =
false;
2091 bool processed =
false;
2102 S.
Diag(D.Loc, D.PD);
2108 S.
Diag(D.Loc, D.PD);
2118 if (P.enableCheckFallThrough) {
2119 const CheckFallThroughDiagnostics &CD =
2121 ? CheckFallThroughDiagnostics::MakeForBlock()
2122 : (isa<CXXMethodDecl>(D) &&
2123 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2124 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2125 ? CheckFallThroughDiagnostics::MakeForLambda()
2127 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2128 : CheckFallThroughDiagnostics::MakeForFunction(D)));
2133 if (P.enableCheckUnreachable) {
2139 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
2140 isTemplateInstantiation = Function->isTemplateInstantiation();
2141 if (!isTemplateInstantiation)
2146 if (P.enableThreadSafetyAnalysis) {
2149 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
2151 Reporter.setIssueBetaWarnings(
true);
2153 Reporter.setVerbose(
true);
2157 Reporter.emitDiagnostics();
2161 if (P.enableConsumedAnalysis) {
2162 consumed::ConsumedWarningsHandler WarningHandler(S);
2171 UninitValsDiagReporter reporter(S);
2178 ++NumUninitAnalysisFunctions;
2181 MaxUninitAnalysisVariablesPerFunction =
2182 std::max(MaxUninitAnalysisVariablesPerFunction,
2184 MaxUninitAnalysisBlockVisitsPerFunction =
2185 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
2191 bool FallThroughDiagFull =
2193 bool FallThroughDiagPerFunction = !Diags.
isIgnored(
2194 diag::warn_unannotated_fallthrough_per_function, D->
getLocStart());
2195 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
2206 if (!Diags.
isIgnored(diag::warn_infinite_recursive_function,
2208 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2215 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2221 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2228 ++NumFunctionsAnalyzed;
2233 MaxCFGBlocksPerFunction =
std::max(MaxCFGBlocksPerFunction,
2234 cfg->getNumBlockIDs());
2236 ++NumFunctionsWithBadCFGs;
2242 llvm::errs() <<
"\n*** Analysis Based Warnings Stats:\n";
2244 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
2245 unsigned AvgCFGBlocksPerFunction =
2246 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
2247 llvm::errs() << NumFunctionsAnalyzed <<
" functions analyzed (" 2248 << NumFunctionsWithBadCFGs <<
" w/o CFGs).\n" 2249 <<
" " << NumCFGBlocks <<
" CFG blocks built.\n" 2250 <<
" " << AvgCFGBlocksPerFunction
2251 <<
" average CFG blocks per function.\n" 2252 <<
" " << MaxCFGBlocksPerFunction
2253 <<
" max CFG blocks per function.\n";
2255 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
2256 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
2257 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
2258 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
2259 llvm::errs() << NumUninitAnalysisFunctions
2260 <<
" functions analyzed for uninitialiazed variables\n" 2261 <<
" " << NumUninitAnalysisVariables <<
" variables analyzed.\n" 2262 <<
" " << AvgUninitVariablesPerFunction
2263 <<
" average variables per function.\n" 2264 <<
" " << MaxUninitAnalysisVariablesPerFunction
2265 <<
" max variables per function.\n" 2266 <<
" " << NumUninitAnalysisBlockVisits <<
" block visits.\n" 2267 <<
" " << AvgUninitBlockVisitsPerFunction
2268 <<
" average block visits per function.\n" 2269 <<
" " << MaxUninitAnalysisBlockVisitsPerFunction
2270 <<
" 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.
const Stmt * getElse() const
A (possibly-)qualified type.
bool isBlockPointerType() 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
Retrieves the implicit object argument for the member call.
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()
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.
SourceLocation getLocEnd() const LLVM_READONLY
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.
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
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.
SourceLocation getLocStart() const LLVM_READONLY
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 ...
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)
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.
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".
void IssueWarnings(Policy P, FunctionScopeInfo *fscope, const Decl *D, const BlockExpr *blkExpr)
static StringRef getFallthroughAttrSpelling(Preprocessor &PP, SourceLocation Loc)
SourceLocation getThrowLoc() const
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
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.
OverloadedOperatorKind getCXXOverloadedOperator() const
getCXXOverloadedOperator - If this name is the name of an overloadable operator in C++ (e...
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;)
Expr - 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>.
const Stmt * getThen() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
const Expr * getCallee() const
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
Retrieves the declaration of the called method.
Preprocessor & getPreprocessor() const
A use of a variable, which might be uninitialized.
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.
static CharSourceRange getCharRange(SourceRange R)
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
SourceLocation getLocStart() const LLVM_READONLY
CFGTerminator getTerminator()
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
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'.
SourceLocation getLocStart() const LLVM_READONLY
Represents a call to a member function that may be written either with member call syntax (e...
SourceLocation getLocStart() const LLVM_READONLY
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).
SourceLocation getLocEnd() const LLVM_READONLY
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
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.
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.
SourceLocation getLocStart() const LLVM_READONLY
A class that handles the analysis of uniqueness violations.
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
static bool isNoexcept(const FunctionDecl *FD)
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
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.
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, const BlockExpr *blkExpr, 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...
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.
SourceLocation getExprLoc() const LLVM_READONLY
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.
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...
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)
__DEVICE__ int max(int __a, int __b)
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()
const Expr * getCond() const
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.
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.