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 {
151 << DiagRange << isAlwaysTrue;
155 bool isAlwaysTrue)
override {
161 << DiagRange << isAlwaysTrue;
175 for (
const auto &B : Block) {
189 isa<TemplateSpecializationType>(NNS->getAsType())) {
225 while (!Stack.empty()) {
246 unsigned next_ID = (*I)->getBlockID();
247 if (States[next_ID] < CurState) {
248 States[next_ID] = CurState;
292 const Type *ThrowType =
nullptr;
312 if (CaughtType == ThrowType)
317 if (CaughtAsRecordType && ThrowTypeAsRecordType)
318 return ThrowTypeAsRecordType->
isDerivedFrom(CaughtAsRecordType);
332 for (
const auto &B : Block) {
339 OpLoc = CE->getThrowLoc();
340 for (
const auto &
I : Block.succs()) {
341 if (!
I.isReachable())
343 if (
const auto *Terminator =
344 dyn_cast_or_null<CXXTryStmt>(
I->getTerminator()))
362 Stack.push_back(&BodyCFG->
getEntry());
363 while (!Stack.empty()) {
379 for (
const auto &
I : CurBlock->
succs())
380 if (
I.isReachable()) {
381 unsigned NextID =
I->getBlockID();
383 States[NextID] = CurState;
384 }
else if (States[NextID] < CurState) {
385 States[NextID] = CurState;
399 S.
Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
401 (isa<CXXDestructorDecl>(FD) ||
405 getAs<FunctionProtoType>())
407 << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
470 for (
const auto *B : *cfg) {
471 if (!live[B->getBlockID()]) {
472 if (B->pred_begin() == B->pred_end()) {
473 if (B->getTerminator() && isa<CXXTryStmt>(B->getTerminator()))
485 bool HasLiveReturn =
false;
486 bool HasFakeEdge =
false;
487 bool HasPlainEdge =
false;
488 bool HasAbnormalEdge =
false;
496 I = cfg->getExit().filtered_pred_start_end(FO);
I.hasMore(); ++
I) {
505 HasAbnormalEdge =
true;
514 for ( ; ri != re ; ++ri)
521 HasAbnormalEdge =
true;
531 if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
532 HasLiveReturn =
true;
535 if (isa<ObjCAtThrowStmt>(S)) {
539 if (isa<CXXThrowExpr>(S)) {
543 if (isa<MSAsmStmt>(S)) {
546 HasLiveReturn =
true;
549 if (isa<CXXTryStmt>(S)) {
550 HasAbnormalEdge =
true;
555 HasAbnormalEdge =
true;
566 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
576 struct CheckFallThroughDiagnostics {
577 unsigned diag_MaybeFallThrough_HasNoReturn;
578 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
579 unsigned diag_AlwaysFallThrough_HasNoReturn;
580 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
581 unsigned diag_NeverFallThroughOrReturn;
582 enum {
Function, Block, Lambda, Coroutine } funMode;
585 static CheckFallThroughDiagnostics MakeForFunction(
const Decl *Func) {
586 CheckFallThroughDiagnostics D;
588 D.diag_MaybeFallThrough_HasNoReturn =
589 diag::warn_falloff_noreturn_function;
590 D.diag_MaybeFallThrough_ReturnsNonVoid =
591 diag::warn_maybe_falloff_nonvoid_function;
592 D.diag_AlwaysFallThrough_HasNoReturn =
593 diag::warn_falloff_noreturn_function;
594 D.diag_AlwaysFallThrough_ReturnsNonVoid =
595 diag::warn_falloff_nonvoid_function;
599 bool isVirtualMethod =
false;
600 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
601 isVirtualMethod = Method->isVirtual();
605 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
606 isTemplateInstantiation =
Function->isTemplateInstantiation();
608 if (!isVirtualMethod && !isTemplateInstantiation)
609 D.diag_NeverFallThroughOrReturn =
610 diag::warn_suggest_noreturn_function;
612 D.diag_NeverFallThroughOrReturn = 0;
618 static CheckFallThroughDiagnostics MakeForCoroutine(
const Decl *Func) {
619 CheckFallThroughDiagnostics D;
621 D.diag_MaybeFallThrough_HasNoReturn = 0;
622 D.diag_MaybeFallThrough_ReturnsNonVoid =
623 diag::warn_maybe_falloff_nonvoid_coroutine;
624 D.diag_AlwaysFallThrough_HasNoReturn = 0;
625 D.diag_AlwaysFallThrough_ReturnsNonVoid =
626 diag::warn_falloff_nonvoid_coroutine;
627 D.funMode = Coroutine;
631 static CheckFallThroughDiagnostics MakeForBlock() {
632 CheckFallThroughDiagnostics D;
633 D.diag_MaybeFallThrough_HasNoReturn =
634 diag::err_noreturn_block_has_return_expr;
635 D.diag_MaybeFallThrough_ReturnsNonVoid =
636 diag::err_maybe_falloff_nonvoid_block;
637 D.diag_AlwaysFallThrough_HasNoReturn =
638 diag::err_noreturn_block_has_return_expr;
639 D.diag_AlwaysFallThrough_ReturnsNonVoid =
640 diag::err_falloff_nonvoid_block;
641 D.diag_NeverFallThroughOrReturn = 0;
646 static CheckFallThroughDiagnostics MakeForLambda() {
647 CheckFallThroughDiagnostics D;
648 D.diag_MaybeFallThrough_HasNoReturn =
649 diag::err_noreturn_lambda_has_return_expr;
650 D.diag_MaybeFallThrough_ReturnsNonVoid =
651 diag::warn_maybe_falloff_nonvoid_lambda;
652 D.diag_AlwaysFallThrough_HasNoReturn =
653 diag::err_noreturn_lambda_has_return_expr;
654 D.diag_AlwaysFallThrough_ReturnsNonVoid =
655 diag::warn_falloff_nonvoid_lambda;
656 D.diag_NeverFallThroughOrReturn = 0;
662 bool HasNoReturn)
const {
663 if (funMode == Function) {
664 return (ReturnsVoid ||
665 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function,
668 D.
isIgnored(diag::warn_noreturn_function_has_return_expr,
671 D.
isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
673 if (funMode == Coroutine) {
674 return (ReturnsVoid ||
675 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
676 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
681 return ReturnsVoid && !HasNoReturn;
693 const CheckFallThroughDiagnostics& CD,
696 bool ReturnsVoid =
false;
697 bool HasNoReturn =
false;
700 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
701 if (
const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
702 ReturnsVoid = CBody->getFallthroughHandler() !=
nullptr;
704 ReturnsVoid = FD->getReturnType()->isVoidType();
705 HasNoReturn = FD->isNoReturn();
707 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
708 ReturnsVoid = MD->getReturnType()->isVoidType();
709 HasNoReturn = MD->hasAttr<NoReturnAttr>();
711 else if (isa<BlockDecl>(D)) {
715 if (FT->getReturnType()->isVoidType())
717 if (FT->getNoReturnAttr())
725 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
741 EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
742 else if (!ReturnsVoid)
743 EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
747 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
748 else if (!ReturnsVoid)
749 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
752 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
753 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
754 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
755 }
else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
756 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
758 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
783 : Inherited(Context), FoundReference(
false), Needle(Needle) {}
785 void VisitExpr(
const Expr *E) {
790 Inherited::VisitExpr(E);
795 FoundReference =
true;
797 Inherited::VisitDeclRefExpr(E);
800 bool doesContainReference()
const {
return FoundReference; }
808 S.
Diag(VD->
getLocation(), diag::note_block_var_fixit_add_initialization)
829 S.
Diag(Loc, diag::note_var_fixit_add_initialization) << VD->
getDeclName()
837 const Stmt *Else,
bool CondVal,
863 bool IsCapturedByBlock) {
864 bool Diagnosed =
false;
897 const Stmt *Term =
I->Terminator;
907 int RemoveDiagKind = -1;
908 const char *FixitStr =
909 S.
getLangOpts().CPlusPlus ? (
I->Output ?
"true" :
"false")
910 : (
I->Output ?
"1" :
"0");
913 switch (Term ? Term->
getStmtClass() : Stmt::DeclStmtClass) {
920 case Stmt::IfStmtClass: {
921 const IfStmt *IS = cast<IfStmt>(Term);
927 I->Output, Fixit1, Fixit2);
930 case Stmt::ConditionalOperatorClass: {
937 I->Output, Fixit1, Fixit2);
940 case Stmt::BinaryOperatorClass: {
948 if ((BO->
getOpcode() == BO_LAnd &&
I->Output) ||
960 case Stmt::WhileStmtClass:
963 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
967 case Stmt::ForStmtClass:
970 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
977 case Stmt::CXXForRangeStmtClass:
978 if (
I->Output == 1) {
986 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
990 case Stmt::DoStmtClass:
993 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
999 case Stmt::CaseStmtClass:
1002 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
1004 case Stmt::DefaultStmtClass:
1007 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
1011 S.
Diag(Range.
getBegin(), diag::warn_sometimes_uninit_var)
1012 << VD->
getDeclName() << IsCapturedByBlock << DiagKind
1013 << Str <<
I->Output << Range;
1014 S.
Diag(User->getLocStart(), diag::note_uninit_var_use)
1015 << IsCapturedByBlock << User->getSourceRange();
1016 if (RemoveDiagKind != -1)
1018 << RemoveDiagKind << Str <<
I->Output << Fixit1 << Fixit2;
1036 bool alwaysReportSelfInit =
false) {
1050 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
1053 ContainsReference CR(S.
Context, DRE);
1054 CR.Visit(Initializer);
1055 if (CR.doesContainReference()) {
1056 S.
Diag(DRE->getLocStart(),
1057 diag::warn_uninit_self_reference_in_init)
1068 diag::warn_uninit_byref_blockvar_captured_by_block)
1087 FallthroughMapper(
Sema &
S)
1088 : FoundSwitchStatements(
false),
1092 bool foundSwitchStatements()
const {
return FoundSwitchStatements; }
1095 bool Found = FallthroughStmts.erase(Stmt);
1100 typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;
1102 const AttrStmts &getFallthroughStmts()
const {
1103 return FallthroughStmts;
1106 void fillReachableBlocks(
CFG *Cfg) {
1107 assert(ReachableBlocks.empty() &&
"ReachableBlocks already filled");
1108 std::deque<const CFGBlock *> BlockQueue;
1110 ReachableBlocks.insert(&Cfg->
getEntry());
1111 BlockQueue.push_back(&Cfg->
getEntry());
1116 for (
const auto *B : *Cfg) {
1117 const Stmt *L = B->getLabel();
1118 if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1119 BlockQueue.push_back(B);
1122 while (!BlockQueue.empty()) {
1124 BlockQueue.pop_front();
1128 if (*
I && ReachableBlocks.insert(*I).second)
1129 BlockQueue.push_back(*
I);
1134 bool checkFallThroughIntoBlock(
const CFGBlock &B,
int &AnnotatedCnt,
1135 bool IsTemplateInstantiation) {
1136 assert(!ReachableBlocks.empty() &&
"ReachableBlocks empty");
1138 int UnannotatedCnt = 0;
1142 while (!BlockQueue.empty()) {
1144 BlockQueue.pop_front();
1148 if (Term && isa<SwitchStmt>(Term))
1159 if (!ReachableBlocks.count(P)) {
1161 ElemEnd = P->
rend();
1162 ElemIt != ElemEnd; ++ElemIt) {
1164 if (
const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1168 if (!IsTemplateInstantiation)
1169 S.
Diag(AS->getLocStart(),
1170 diag::warn_fallthrough_attr_unreachable);
1171 markFallthroughVisited(AS);
1191 markFallthroughVisited(AS);
1199 std::back_inserter(BlockQueue));
1205 return !!UnannotatedCnt;
1209 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1212 if (asFallThroughAttr(S))
1213 FallthroughStmts.insert(S);
1218 FoundSwitchStatements =
true;
1224 bool TraverseDecl(
Decl *D) {
return true; }
1227 bool TraverseLambdaBody(
LambdaExpr *LE) {
return true; }
1232 if (
const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1233 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1244 ElemIt != ElemEnd; ++ElemIt) {
1246 return CS->getStmt();
1258 bool FoundSwitchStatements;
1259 AttrStmts FallthroughStmts;
1261 llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
1268 tok::l_square, tok::l_square,
1270 tok::r_square, tok::r_square
1276 tok::r_square, tok::r_square
1279 bool PreferClangAttr = !PP.
getLangOpts().CPlusPlus1z;
1281 StringRef MacroName;
1282 if (PreferClangAttr)
1284 if (MacroName.empty())
1286 if (MacroName.empty() && !PreferClangAttr)
1288 if (MacroName.empty())
1289 MacroName = PreferClangAttr ?
"[[clang::fallthrough]]" :
"[[fallthrough]]";
1307 FallthroughMapper FM(S);
1308 FM.TraverseStmt(AC.
getBody());
1310 if (!FM.foundSwitchStatements())
1313 if (PerFunction && FM.getFallthroughStmts().empty())
1321 FM.fillReachableBlocks(Cfg);
1323 for (
const CFGBlock *B : llvm::reverse(*Cfg)) {
1326 if (!Label || !isa<SwitchCase>(Label))
1331 bool IsTemplateInstantiation =
false;
1333 IsTemplateInstantiation = Function->isTemplateInstantiation();
1334 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1335 IsTemplateInstantiation))
1339 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1340 : diag::warn_unannotated_fallthrough);
1342 if (!AnnotatedCnt) {
1353 if (!(B->
empty() && Term && isa<BreakStmt>(Term))) {
1357 TextToInsert +=
"; ";
1358 S.
Diag(L, diag::note_insert_fallthrough_fixit) <<
1359 AnnotationSpelling <<
1363 S.
Diag(L, diag::note_insert_break_fixit) <<
1368 for (
const auto *F : FM.getFallthroughStmts())
1369 S.
Diag(F->getLocStart(), diag::err_fallthrough_attr_invalid_placement);
1378 case Stmt::ForStmtClass:
1379 case Stmt::WhileStmtClass:
1380 case Stmt::CXXForRangeStmtClass:
1381 case Stmt::ObjCForCollectionStmtClass:
1383 case Stmt::DoStmtClass: {
1384 const Expr *Cond = cast<DoStmt>(
S)->getCond();
1388 return Val.getBoolValue();
1405 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1414 for (WeakObjectUseMap::const_iterator
I = WeakMap.begin(), E = WeakMap.end();
1416 const WeakUseVector &Uses =
I->second;
1419 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1420 for ( ; UI != UE; ++UI) {
1433 if (UI == Uses.begin()) {
1434 WeakUseVector::const_iterator UI2 = UI;
1435 for (++UI2; UI2 != UE; ++UI2)
1436 if (UI2->isUnsafe())
1440 if (!
isInLoop(Ctx, PM, UI->getUseExpr()))
1443 const WeakObjectProfileTy &Profile =
I->first;
1444 if (!Profile.isExactProfile())
1449 Base = Profile.getProperty();
1450 assert(Base &&
"A profile always has a base or property.");
1452 if (
const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1453 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1458 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(),
I));
1461 if (UsesByStmt.empty())
1466 std::sort(UsesByStmt.begin(), UsesByStmt.end(),
1467 [&
SM](
const StmtUsesPair &LHS,
const StmtUsesPair &RHS) {
1469 RHS.first->getLocStart());
1484 if (isa<sema::BlockScopeInfo>(CurFn))
1485 FunctionKind = Block;
1486 else if (isa<sema::LambdaScopeInfo>(CurFn))
1487 FunctionKind = Lambda;
1488 else if (isa<ObjCMethodDecl>(D))
1489 FunctionKind = Method;
1491 FunctionKind = Function;
1494 for (
const auto &P : UsesByStmt) {
1495 const Stmt *FirstRead = P.first;
1496 const WeakObjectProfileTy &Key = P.second->first;
1497 const WeakUseVector &Uses = P.second->second;
1505 if (Key.isExactProfile())
1506 DiagKind = diag::warn_arc_repeated_use_of_weak;
1508 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1520 const NamedDecl *KeyProp = Key.getProperty();
1521 if (isa<VarDecl>(KeyProp))
1522 ObjectKind = Variable;
1523 else if (isa<ObjCPropertyDecl>(KeyProp))
1525 else if (isa<ObjCMethodDecl>(KeyProp))
1526 ObjectKind = ImplicitProperty;
1527 else if (isa<ObjCIvarDecl>(KeyProp))
1530 llvm_unreachable(
"Unexpected weak object kind!");
1535 if (Prop->hasAttr<IBOutletAttr>())
1540 <<
int(ObjectKind) << KeyProp << int(FunctionKind)
1544 for (
const auto &Use : Uses) {
1545 if (Use.getUseExpr() == FirstRead)
1547 S.
Diag(Use.getUseExpr()->getLocStart(),
1548 diag::note_arc_weak_also_accessed_here)
1549 << Use.getUseExpr()->getSourceRange();
1558 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1562 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1566 UninitValsDiagReporter(
Sema &S) : S(S) {}
1569 MappedType &getUses(
const VarDecl *vd) {
1570 MappedType &V = uses[vd];
1571 if (!V.getPointer())
1572 V.setPointer(
new UsesVec());
1576 void handleUseOfUninitVariable(
const VarDecl *vd,
1578 getUses(vd).getPointer()->push_back(use);
1581 void handleSelfInit(
const VarDecl *vd)
override {
1582 getUses(vd).setInt(
true);
1586 for (
const auto &P : uses) {
1588 const MappedType &V = P.second;
1590 UsesVec *vec = V.getPointer();
1591 bool hasSelfInit = V.getInt();
1596 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1605 std::sort(vec->begin(), vec->end(),
1608 if (a.
getKind() != b.getKind())
1609 return a.
getKind() > b.getKind();
1613 for (
const auto &U : *vec) {
1632 static bool hasAlwaysUninitializedUse(
const UsesVec* vec) {
1633 return std::any_of(vec->begin(), vec->end(), [](
const UninitUse &U) {
1645 typedef std::pair<PartialDiagnosticAt, OptionalNotes>
DelayedDiag;
1646 typedef std::list<DelayedDiag>
DiagList;
1648 struct SortDiagBySourceLocation {
1652 bool operator()(
const DelayedDiag &left,
const DelayedDiag &right) {
1665 namespace threadSafety {
1678 S.PDiag(diag::note_thread_warning_in_fun)
1689 S.PDiag(diag::note_thread_warning_in_fun)
1691 ONS.push_back(std::move(FNote));
1699 ONS.push_back(Note1);
1700 ONS.push_back(Note2);
1703 S.PDiag(diag::note_thread_warning_in_fun)
1705 ONS.push_back(std::move(FNote));
1711 void warnLockMismatch(
unsigned DiagID, StringRef
Kind,
Name LockName,
1718 Warnings.emplace_back(std::move(Warning), getNotes());
1726 void setVerbose(
bool b) {
Verbose = b; }
1732 void emitDiagnostics() {
1733 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
1735 S.Diag(
Diag.first.first,
Diag.first.second);
1736 for (
const auto &Note :
Diag.second)
1737 S.Diag(Note.first, Note.second);
1741 void handleInvalidLockExp(StringRef Kind,
SourceLocation Loc)
override {
1744 Warnings.emplace_back(std::move(Warning), getNotes());
1747 void handleUnmatchedUnlock(StringRef Kind,
Name LockName,
1749 warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc);
1752 void handleIncorrectUnlockKind(StringRef Kind,
Name LockName,
1758 << Kind << LockName << Received
1760 Warnings.emplace_back(std::move(Warning), getNotes());
1764 warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc);
1767 void handleMutexHeldEndOfScope(StringRef Kind,
Name LockName,
1771 unsigned DiagID = 0;
1774 DiagID = diag::warn_lock_some_predecessors;
1777 DiagID = diag::warn_expecting_lock_held_on_loop;
1780 DiagID = diag::warn_no_unlock;
1783 DiagID = diag::warn_expecting_locked;
1794 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1797 Warnings.emplace_back(std::move(Warning), getNotes());
1800 void handleExclusiveAndShared(StringRef Kind,
Name LockName,
1804 S.PDiag(diag::warn_lock_exclusive_and_shared)
1805 << Kind << LockName);
1807 << Kind << LockName);
1808 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1811 void handleNoMutexHeld(StringRef Kind,
const NamedDecl *D,
1815 "Only works for variables");
1817 diag::warn_variable_requires_any_lock:
1818 diag::warn_var_deref_requires_any_lock;
1821 Warnings.emplace_back(std::move(Warning), getNotes());
1824 void handleMutexNotHeld(StringRef Kind,
const NamedDecl *D,
1827 Name *PossibleMatch)
override {
1828 unsigned DiagID = 0;
1829 if (PossibleMatch) {
1832 DiagID = diag::warn_variable_requires_lock_precise;
1835 DiagID = diag::warn_var_deref_requires_lock_precise;
1838 DiagID = diag::warn_fun_requires_lock_precise;
1841 DiagID = diag::warn_guarded_pass_by_reference;
1844 DiagID = diag::warn_pt_guarded_pass_by_reference;
1854 S.PDiag(diag::note_guarded_by_declared_here)
1856 Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote));
1858 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1862 DiagID = diag::warn_variable_requires_lock;
1865 DiagID = diag::warn_var_deref_requires_lock;
1868 DiagID = diag::warn_fun_requires_lock;
1871 DiagID = diag::warn_guarded_pass_by_reference;
1874 DiagID = diag::warn_pt_guarded_pass_by_reference;
1882 S.PDiag(diag::note_guarded_by_declared_here)
1884 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1886 Warnings.emplace_back(std::move(Warning), getNotes());
1890 void handleNegativeNotHeld(StringRef Kind,
Name LockName,
Name Neg,
1893 S.PDiag(diag::warn_acquire_requires_negative_cap)
1894 << Kind << LockName << Neg);
1895 Warnings.emplace_back(std::move(Warning), getNotes());
1898 void handleFunExcludesLock(StringRef Kind,
Name FunName,
Name LockName,
1901 << Kind << FunName << LockName);
1902 Warnings.emplace_back(std::move(Warning), getNotes());
1905 void handleLockAcquiredBefore(StringRef Kind,
Name L1Name,
Name L2Name,
1908 S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
1909 Warnings.emplace_back(std::move(Warning), getNotes());
1914 S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
1915 Warnings.emplace_back(std::move(Warning), getNotes());
1935 namespace consumed {
1937 class ConsumedWarningsHandler :
public ConsumedWarningsHandlerBase {
1944 ConsumedWarningsHandler(
Sema &S) : S(S) {}
1946 void emitDiagnostics()
override {
1947 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
1948 for (
const auto &
Diag : Warnings) {
1949 S.Diag(
Diag.first.first,
Diag.first.second);
1950 for (
const auto &Note :
Diag.second)
1951 S.Diag(Note.first, Note.second);
1956 StringRef VariableName)
override {
1964 StringRef VariableName,
1965 StringRef ExpectedState,
1966 StringRef ObservedState)
override {
1969 diag::warn_param_return_typestate_mismatch) << VariableName <<
1970 ExpectedState << ObservedState);
1975 void warnParamTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1976 StringRef ObservedState)
override {
1979 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
1985 StringRef TypeName)
override {
1987 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
1992 void warnReturnTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1993 StringRef ObservedState)
override {
1996 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
2001 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef
State,
2005 diag::warn_use_of_temp_in_invalid_state) << MethodName <<
State);
2010 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
2014 MethodName << VariableName <<
State);
2029 enableCheckFallThrough = 1;
2030 enableCheckUnreachable = 0;
2031 enableThreadSafetyAnalysis = 0;
2032 enableConsumedAnalysis = 0;
2041 NumFunctionsAnalyzed(0),
2042 NumFunctionsWithBadCFGs(0),
2044 MaxCFGBlocksPerFunction(0),
2045 NumUninitAnalysisFunctions(0),
2046 NumUninitAnalysisVariables(0),
2047 MaxUninitAnalysisVariablesPerFunction(0),
2048 NumUninitAnalysisBlockVisits(0),
2049 MaxUninitAnalysisBlockVisitsPerFunction(0) {
2051 using namespace diag;
2054 DefaultPolicy.enableCheckUnreachable =
2057 isEnabled(D, warn_unreachable_return) ||
2058 isEnabled(D, warn_unreachable_loop_increment);
2060 DefaultPolicy.enableThreadSafetyAnalysis =
2063 DefaultPolicy.enableConsumedAnalysis =
2064 isEnabled(D, warn_use_in_invalid_state);
2069 S.
Diag(D.Loc, D.PD);
2092 if (cast<DeclContext>(D)->isDependentContext())
2101 const Stmt *Body = D->
getBody();
2123 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
2124 P.enableConsumedAnalysis) {
2141 std::unique_ptr<LogicalErrorHandler> LEH;
2142 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2144 LEH.reset(
new LogicalErrorHandler(S));
2150 bool analyzed =
false;
2161 bool processed =
false;
2172 S.Diag(D.Loc, D.PD);
2178 S.Diag(D.Loc, D.PD);
2188 if (P.enableCheckFallThrough) {
2189 const CheckFallThroughDiagnostics &CD =
2191 ? CheckFallThroughDiagnostics::MakeForBlock()
2192 : (isa<CXXMethodDecl>(D) &&
2193 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2194 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2195 ? CheckFallThroughDiagnostics::MakeForLambda()
2197 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2198 : CheckFallThroughDiagnostics::MakeForFunction(D)));
2203 if (P.enableCheckUnreachable) {
2208 bool isTemplateInstantiation =
false;
2209 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
2210 isTemplateInstantiation = Function->isTemplateInstantiation();
2211 if (!isTemplateInstantiation)
2216 if (P.enableThreadSafetyAnalysis) {
2219 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
2221 Reporter.setIssueBetaWarnings(
true);
2223 Reporter.setVerbose(
true);
2226 &S.ThreadSafetyDeclCache);
2227 Reporter.emitDiagnostics();
2231 if (P.enableConsumedAnalysis) {
2232 consumed::ConsumedWarningsHandler WarningHandler(S);
2241 UninitValsDiagReporter reporter(S);
2248 ++NumUninitAnalysisFunctions;
2251 MaxUninitAnalysisVariablesPerFunction =
2252 std::max(MaxUninitAnalysisVariablesPerFunction,
2254 MaxUninitAnalysisBlockVisitsPerFunction =
2255 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
2261 bool FallThroughDiagFull =
2263 bool FallThroughDiagPerFunction = !Diags.
isIgnored(
2264 diag::warn_unannotated_fallthrough_per_function, D->
getLocStart());
2265 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
2270 if (S.getLangOpts().ObjCWeak &&
2276 if (!Diags.
isIgnored(diag::warn_infinite_recursive_function,
2278 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2285 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2286 if (S.getLangOpts().CPlusPlus &&
isNoexcept(FD))
2291 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2298 ++NumFunctionsAnalyzed;
2302 NumCFGBlocks += cfg->getNumBlockIDs();
2303 MaxCFGBlocksPerFunction =
std::max(MaxCFGBlocksPerFunction,
2304 cfg->getNumBlockIDs());
2306 ++NumFunctionsWithBadCFGs;
2312 llvm::errs() <<
"\n*** Analysis Based Warnings Stats:\n";
2314 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
2315 unsigned AvgCFGBlocksPerFunction =
2316 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
2317 llvm::errs() << NumFunctionsAnalyzed <<
" functions analyzed ("
2318 << NumFunctionsWithBadCFGs <<
" w/o CFGs).\n"
2319 <<
" " << NumCFGBlocks <<
" CFG blocks built.\n"
2320 <<
" " << AvgCFGBlocksPerFunction
2321 <<
" average CFG blocks per function.\n"
2322 <<
" " << MaxCFGBlocksPerFunction
2323 <<
" max CFG blocks per function.\n";
2325 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
2326 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
2327 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
2328 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
2329 llvm::errs() << NumUninitAnalysisFunctions
2330 <<
" functions analyzed for uninitialiazed variables\n"
2331 <<
" " << NumUninitAnalysisVariables <<
" variables analyzed.\n"
2332 <<
" " << AvgUninitVariablesPerFunction
2333 <<
" average variables per function.\n"
2334 <<
" " << MaxUninitAnalysisVariablesPerFunction
2335 <<
" max variables per function.\n"
2336 <<
" " << NumUninitAnalysisBlockVisits <<
" block visits.\n"
2337 <<
" " << AvgUninitBlockVisitsPerFunction
2338 <<
" average block visits per function.\n"
2339 <<
" " << MaxUninitAnalysisBlockVisitsPerFunction
2340 <<
" max block visits per function.\n";
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
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...
SourceLocation getEnd() const
StmtClass getStmtClass() const
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Passing a guarded variable by reference.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
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.
ASTContext & getASTContext() const
A (possibly-)qualified type.
SourceLocation getBegin() const
static bool isThrowCaught(const CXXThrowExpr *Throw, const CXXCatchStmt *Catch)
bool HasFallthroughStmt
Whether there is a fallthrough statement in this function.
succ_iterator succ_begin()
const LangOptions & getLangOpts() const
Stmt - This represents one statement.
FunctionType - C99 6.7.5.3 - Function Declarators.
CXXCatchStmt * getHandler(unsigned i)
IfStmt - This represents an if/then/else.
Defines the SourceManager interface.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
static void diagnoseRepeatedUseOfWeak(Sema &S, const sema::FunctionScopeInfo *CurFn, const Decl *D, const ParentMap &PM)
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Decl - This represents one declaration (or definition), e.g.
Represents an attribute applied to a statement.
The base class of the type hierarchy.
The use is uninitialized whenever a certain branch is taken.
const Expr * getInit() const
AnalysisBasedWarnings(Sema &s)
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
void run(AnalysisDeclContext &AC)
Check a function's CFG for consumed violations.
const Stmt * getElse() const
SourceLocation getOperatorLoc() const
bool isBlockPointerType() 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)
branch_iterator branch_begin() const
Branches which inevitably result in the variable being used uninitialized.
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.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
const Expr * getCallee() const
unsigned succ_size() const
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.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs, typeofs, etc., as well as any qualifiers.
SourceLocation getLocStart() const LLVM_READONLY
TextDiagnosticBuffer::DiagList DiagList
LabelStmt - Represents a label, which has a substatement.
LockKind
This enum distinguishes between different kinds of lock actions.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool isReferenceType() const
std::pair< PartialDiagnosticAt, OptionalNotes > DelayedDiag
AnalysisDeclContext contains the context data for the function or method under analysis.
Expr * getImplicitObjectArgument() const
Retrieves the implicit object argument for the member call.
static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, bool PerFunction)
const LangOptions & getLangOpts() const
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
bool getAddEHEdges() const
getAddEHEdges - Return true iff we are adding exceptional edges from callExprs.
SmallVectorImpl< Branch >::const_iterator branch_iterator
const LangOptions & getLangOpts() const
bool AddCXXDefaultInitExprInCtors
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
static bool doesThrowEscapePath(CFGBlock Block, SourceLocation &OpLoc)
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)
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification, if any.
std::string getNameAsString() const
getNameAsString - Get a human-readable name for the declaration, even if it is one of the special kin...
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)...
const Decl * getDecl() const
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
detail::InMemoryDirectory::const_iterator I
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD)
const Expr * getUser() const
Get the expression containing the uninitialized use.
Passing a pt-guarded variable by reference.
ConditionalOperator - The ?: ternary operator.
Sema - This implements semantic analysis and AST building for C.
Expr * getFalseExpr() const
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...
CXXMethodDecl * getMethodDecl() const
Retrieves the declaration of the called method.
Handler class for thread safety warnings.
SourceLocation getLocEnd() const LLVM_READONLY
static StringRef getOpcodeStr(Opcode Op)
getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to...
CFGBlock - Represents a single basic block in a source-level CFG.
std::vector< bool > & Stack
static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, const Stmt *S)
Stmt * getBody() const
Get the body of the Declaration.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Dereferencing a variable (e.g. p in *p = 5;)
const Type * getTypePtrOrNull() const
Expr - This represents one expression.
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Defines the clang::Preprocessor interface.
CXXTryStmt - A C++ try block, including all handlers.
Stores token information for comparing actual tokens with predefined values.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
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.
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
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...
unsigned getBlockID() const
AccessKind
This enum distinguishes between different ways to access (read or write) a variable.
Making a function call (e.g. fool())
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
DiagnosticsEngine & getDiagnostics() const
A use of a variable, which might be uninitialized.
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...
TypeSourceInfo * getTypeSourceInfo() const
Expr * getTrueExpr() const
reverse_iterator rbegin()
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
static CharSourceRange getCharRange(SourceRange R)
bool getSuppressSystemWarnings() const
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
Stmt * getBody(const FunctionDecl *&Definition) const
getBody - Retrieve the body (definition) of the function.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
SourceLocation getLocStart() const LLVM_READONLY
bool hasNoReturnElement() const
CFGTerminator getTerminator()
Reading or writing a variable (e.g. x in x = 5;)
Stmt * getParent(Stmt *) const
Encodes a location in the source.
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc, const FunctionDecl *FD)
bool isValid() const
Return true if this is a valid SourceLocation object.
OverloadedOperatorKind getCXXOverloadedOperator() const
getCXXOverloadedOperator - If this name is the name of an overloadable operator in C++ (e...
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...
ASTContext & getASTContext() const LLVM_READONLY
ASTContext & getASTContext() const
bool PruneTriviallyFalseEdges
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.
const Stmt * getStmt() const
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
SourceLocation FunLocation
static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD, AnalysisDeclContext &AC)
Represents one property declaration in an Objective-C interface.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs. ...
SourceLocation getBegin() const
const T * castAs() const
Member-template castAs<specific type>.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
static bool isLogicalOp(Opcode Opc)
sema::FunctionScopeInfo * getCurFunction() const
BuildOptions & setAllAlwaysAdd()
The use is uninitialized the first time it is reached after we reach the variable's declaration...
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
QualType getType() const
Return the type wrapped by this type source info.
AdjacentBlocks::const_iterator const_succ_iterator
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...
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, const BlockExpr *blkExpr, const CheckFallThroughDiagnostics &CD, AnalysisDeclContext &AC)
CheckFallThroughForFunctionDef - Check that we don't fall off the end of a function that should retur...
pred_iterator pred_begin()
const Expr * getSubExpr() const
CFG::BuildOptions & getCFGBuildOptions()
Return the build options used to construct the CFG.
SourceLocation FunEndLocation
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
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...
llvm::SmallDenseMap< WeakObjectProfileTy, WeakUseVector, 8, WeakObjectProfileTy::DenseMapInfo > WeakObjectUseMap
Used to collect all uses of weak objects in a function body.
std::string getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const
Get a string to suggest for zero-initialization of a type.
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg)
SmallVector< PartialDiagnosticAt, 1 > OptionalNotes
const WeakObjectUseMap & getWeakObjectUses() const
unsigned getNumHandlers() const
QualType getCaughtType() const
Represents a simple identification of a weak object.
SourceLocation getLocStart() const LLVM_READONLY
detail::InMemoryDirectory::const_iterator E
A class that handles the analysis of uniqueness violations.
static bool hasThrowOutNonThrowingFunc(SourceLocation &OpLoc, CFG *BodyCFG)
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
static bool isNoexcept(const FunctionDecl *FD)
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
const Stmt * getThen() const
SwitchStmt - This represents a 'switch' stmt.
The standard open() call: int open(const char *path, int oflag, ...);.
Kind getKind() const
Get the kind of uninitialized use.
UnreachableKind
Classifications of unreachable code.
SourceManager & getSourceManager() const
const T * getAs() const
Member-template getAs<specific type>'.
QualType getCanonicalType() const
The use is always uninitialized.
Base for LValueReferenceType and RValueReferenceType.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
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)
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
QualType getPointeeType() const
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.
Represents a C++ struct/union/class.
CFGCallback defines methods that should be called when a logical operator error is found when buildin...
CXXCatchStmt - This represents a C++ catch block.
const Expr * getCond() const
CFGElement - 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...
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.
static bool isThrowCaughtByHandlers(const CXXThrowExpr *CE, const CXXTryStmt *TryStmt)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
void registerForcedBlockExpression(const Stmt *stmt)
A reference to a declared variable, function, enum, etc.
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
const FunctionDecl * CurrentFunction
unsigned NumVariablesAnalyzed
ParentMap & getParentMap()
A trivial tuple used to represent a source range.
SourceLocation getLocation() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
NamedDecl - This represents a decl with a name.
bool hasUncompilableErrorOccurred() const
Errors that actually prevent compilation, not those that are upgraded from a warning by -Werror...
unsigned getNumBlockIDs() const
getNumBlockIDs - Returns the total number of BlockIDs allocated (which start at 0).
SourceLocation getLocStart() const LLVM_READONLY
branch_iterator branch_end() const
static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block)
This class handles loading and caching of source files into memory.
Preprocessor & getPreprocessor() const
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
bool isPointerType() const