40 #include "llvm/ADT/ArrayRef.h"
41 #include "llvm/ADT/BitVector.h"
42 #include "llvm/ADT/FoldingSet.h"
43 #include "llvm/ADT/ImmutableMap.h"
44 #include "llvm/ADT/MapVector.h"
45 #include "llvm/ADT/PostOrderIterator.h"
46 #include "llvm/ADT/SmallString.h"
47 #include "llvm/ADT/SmallVector.h"
48 #include "llvm/ADT/StringRef.h"
49 #include "llvm/Support/Casting.h"
55 using namespace clang;
65 UnreachableCodeHandler(
Sema &s) :
S(s) {}
72 unsigned diag = diag::warn_unreachable;
75 diag = diag::warn_unreachable_break;
78 diag = diag::warn_unreachable_return;
81 diag = diag::warn_unreachable_loop_increment;
87 S.
Diag(L, diag) << R1 << R2;
94 S.
Diag(Open, diag::note_unreachable_silence)
115 UnreachableCodeHandler UC(S);
127 static bool HasMacroID(
const Expr *
E) {
132 for (
const Stmt *SubStmt : E->children())
133 if (
const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
134 if (HasMacroID(SubExpr))
140 void compareAlwaysTrue(
const BinaryOperator *B,
bool isAlwaysTrue)
override {
146 << DiagRange << isAlwaysTrue;
150 bool isAlwaysTrue)
override {
156 << DiagRange << isAlwaysTrue;
170 for (
const auto &B : Block) {
184 isa<TemplateSpecializationType>(NNS->getAsType())) {
220 while (!Stack.empty()) {
241 unsigned next_ID = (*I)->getBlockID();
242 if (States[next_ID] < CurState) {
243 States[next_ID] = CurState;
273 S.
Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
312 for (
const auto *B : *cfg) {
313 if (!live[B->getBlockID()]) {
314 if (B->pred_begin() == B->pred_end()) {
315 if (B->getTerminator() && isa<CXXTryStmt>(B->getTerminator()))
327 bool HasLiveReturn =
false;
328 bool HasFakeEdge =
false;
329 bool HasPlainEdge =
false;
330 bool HasAbnormalEdge =
false;
338 I = cfg->getExit().filtered_pred_start_end(FO);
I.hasMore(); ++
I) {
347 HasAbnormalEdge =
true;
356 for ( ; ri != re ; ++ri)
363 HasAbnormalEdge =
true;
373 if (isa<ReturnStmt>(S)) {
374 HasLiveReturn =
true;
377 if (isa<ObjCAtThrowStmt>(S)) {
381 if (isa<CXXThrowExpr>(S)) {
385 if (isa<MSAsmStmt>(S)) {
388 HasLiveReturn =
true;
391 if (isa<CXXTryStmt>(S)) {
392 HasAbnormalEdge =
true;
397 HasAbnormalEdge =
true;
408 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
418 struct CheckFallThroughDiagnostics {
419 unsigned diag_MaybeFallThrough_HasNoReturn;
420 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
421 unsigned diag_AlwaysFallThrough_HasNoReturn;
422 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
423 unsigned diag_NeverFallThroughOrReturn;
424 enum {
Function, Block, Lambda } funMode;
427 static CheckFallThroughDiagnostics MakeForFunction(
const Decl *Func) {
428 CheckFallThroughDiagnostics D;
429 D.FuncLoc = Func->getLocation();
430 D.diag_MaybeFallThrough_HasNoReturn =
431 diag::warn_falloff_noreturn_function;
432 D.diag_MaybeFallThrough_ReturnsNonVoid =
433 diag::warn_maybe_falloff_nonvoid_function;
434 D.diag_AlwaysFallThrough_HasNoReturn =
435 diag::warn_falloff_noreturn_function;
436 D.diag_AlwaysFallThrough_ReturnsNonVoid =
437 diag::warn_falloff_nonvoid_function;
441 bool isVirtualMethod =
false;
442 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
443 isVirtualMethod = Method->isVirtual();
447 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
448 isTemplateInstantiation =
Function->isTemplateInstantiation();
450 if (!isVirtualMethod && !isTemplateInstantiation)
451 D.diag_NeverFallThroughOrReturn =
452 diag::warn_suggest_noreturn_function;
454 D.diag_NeverFallThroughOrReturn = 0;
460 static CheckFallThroughDiagnostics MakeForBlock() {
461 CheckFallThroughDiagnostics D;
462 D.diag_MaybeFallThrough_HasNoReturn =
463 diag::err_noreturn_block_has_return_expr;
464 D.diag_MaybeFallThrough_ReturnsNonVoid =
465 diag::err_maybe_falloff_nonvoid_block;
466 D.diag_AlwaysFallThrough_HasNoReturn =
467 diag::err_noreturn_block_has_return_expr;
468 D.diag_AlwaysFallThrough_ReturnsNonVoid =
469 diag::err_falloff_nonvoid_block;
470 D.diag_NeverFallThroughOrReturn = 0;
475 static CheckFallThroughDiagnostics MakeForLambda() {
476 CheckFallThroughDiagnostics D;
477 D.diag_MaybeFallThrough_HasNoReturn =
478 diag::err_noreturn_lambda_has_return_expr;
479 D.diag_MaybeFallThrough_ReturnsNonVoid =
480 diag::warn_maybe_falloff_nonvoid_lambda;
481 D.diag_AlwaysFallThrough_HasNoReturn =
482 diag::err_noreturn_lambda_has_return_expr;
483 D.diag_AlwaysFallThrough_ReturnsNonVoid =
484 diag::warn_falloff_nonvoid_lambda;
485 D.diag_NeverFallThroughOrReturn = 0;
491 bool HasNoReturn)
const {
492 if (funMode == Function) {
493 return (ReturnsVoid ||
494 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function,
497 D.
isIgnored(diag::warn_noreturn_function_has_return_expr,
500 D.
isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
504 return ReturnsVoid && !HasNoReturn;
516 const CheckFallThroughDiagnostics& CD,
519 bool ReturnsVoid =
false;
520 bool HasNoReturn =
false;
522 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
523 ReturnsVoid = FD->getReturnType()->isVoidType();
524 HasNoReturn = FD->isNoReturn();
526 else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
527 ReturnsVoid = MD->getReturnType()->isVoidType();
528 HasNoReturn = MD->hasAttr<NoReturnAttr>();
530 else if (isa<BlockDecl>(D)) {
534 if (FT->getReturnType()->isVoidType())
536 if (FT->getNoReturnAttr())
544 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
547 SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd();
555 S.
Diag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
556 else if (!ReturnsVoid)
557 S.
Diag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
561 S.
Diag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
562 else if (!ReturnsVoid)
563 S.
Diag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
566 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
567 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
568 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
569 }
else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
570 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
572 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
597 : Inherited(Context), FoundReference(
false), Needle(Needle) {}
599 void VisitExpr(
const Expr *E) {
604 Inherited::VisitExpr(E);
609 FoundReference =
true;
611 Inherited::VisitDeclRefExpr(E);
614 bool doesContainReference()
const {
return FoundReference; }
621 !VD->hasAttr<BlocksAttr>()) {
622 S.
Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization)
633 if (VD->getLocEnd().isMacroID())
643 S.
Diag(Loc, diag::note_var_fixit_add_initialization) << VD->
getDeclName()
651 const Stmt *Else,
bool CondVal,
657 Then->getLocStart()));
668 Else->getLocStart()));
677 bool IsCapturedByBlock) {
678 bool Diagnosed =
false;
682 S.
Diag(Use.
getUser()->getLocStart(), diag::warn_uninit_var)
684 << Use.
getUser()->getSourceRange();
689 S.
Diag(VD->getLocation(), diag::warn_sometimes_uninit_var)
692 << const_cast<DeclContext*>(VD->getLexicalDeclContext())
694 S.
Diag(Use.
getUser()->getLocStart(), diag::note_uninit_var_use)
695 << IsCapturedByBlock << Use.
getUser()->getSourceRange();
711 const Stmt *Term =
I->Terminator;
721 int RemoveDiagKind = -1;
722 const char *FixitStr =
723 S.
getLangOpts().CPlusPlus ? (
I->Output ?
"true" :
"false")
724 : (
I->Output ?
"1" :
"0");
727 switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) {
734 case Stmt::IfStmtClass: {
735 const IfStmt *IS = cast<IfStmt>(Term);
738 Range = IS->
getCond()->getSourceRange();
741 I->Output, Fixit1, Fixit2);
744 case Stmt::ConditionalOperatorClass: {
748 Range = CO->
getCond()->getSourceRange();
751 I->Output, Fixit1, Fixit2);
754 case Stmt::BinaryOperatorClass: {
760 Range = BO->
getLHS()->getSourceRange();
762 if ((BO->
getOpcode() == BO_LAnd &&
I->Output) ||
774 case Stmt::WhileStmtClass:
777 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
781 case Stmt::ForStmtClass:
784 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
791 case Stmt::CXXForRangeStmtClass:
792 if (
I->Output == 1) {
800 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
804 case Stmt::DoStmtClass:
807 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
813 case Stmt::CaseStmtClass:
816 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
818 case Stmt::DefaultStmtClass:
821 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
825 S.
Diag(Range.
getBegin(), diag::warn_sometimes_uninit_var)
826 << VD->
getDeclName() << IsCapturedByBlock << DiagKind
827 << Str <<
I->Output << Range;
828 S.
Diag(User->getLocStart(), diag::note_uninit_var_use)
829 << IsCapturedByBlock << User->getSourceRange();
830 if (RemoveDiagKind != -1)
832 << RemoveDiagKind << Str <<
I->Output << Fixit1 << Fixit2;
838 S.
Diag(Use.
getUser()->getLocStart(), diag::warn_maybe_uninit_var)
840 << Use.
getUser()->getSourceRange();
850 bool alwaysReportSelfInit =
false) {
864 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
867 ContainsReference CR(S.
Context, DRE);
868 CR.Visit(Initializer);
869 if (CR.doesContainReference()) {
870 S.
Diag(DRE->getLocStart(),
871 diag::warn_uninit_self_reference_in_init)
882 diag::warn_uninit_byref_blockvar_captured_by_block)
901 FallthroughMapper(
Sema &
S)
902 : FoundSwitchStatements(
false),
906 bool foundSwitchStatements()
const {
return FoundSwitchStatements; }
909 bool Found = FallthroughStmts.erase(Stmt);
914 typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;
916 const AttrStmts &getFallthroughStmts()
const {
917 return FallthroughStmts;
920 void fillReachableBlocks(
CFG *Cfg) {
921 assert(ReachableBlocks.empty() &&
"ReachableBlocks already filled");
922 std::deque<const CFGBlock *> BlockQueue;
924 ReachableBlocks.insert(&Cfg->
getEntry());
925 BlockQueue.push_back(&Cfg->
getEntry());
930 for (
const auto *B : *Cfg) {
931 const Stmt *L = B->getLabel();
932 if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
933 BlockQueue.push_back(B);
936 while (!BlockQueue.empty()) {
938 BlockQueue.pop_front();
942 if (*
I && ReachableBlocks.insert(*I).second)
943 BlockQueue.push_back(*
I);
948 bool checkFallThroughIntoBlock(
const CFGBlock &B,
int &AnnotatedCnt) {
949 assert(!ReachableBlocks.empty() &&
"ReachableBlocks empty");
951 int UnannotatedCnt = 0;
955 while (!BlockQueue.empty()) {
957 BlockQueue.pop_front();
961 if (Term && isa<SwitchStmt>(Term))
972 if (!ReachableBlocks.count(P)) {
975 ElemIt != ElemEnd; ++ElemIt) {
977 if (
const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
978 S.
Diag(AS->getLocStart(),
979 diag::warn_fallthrough_attr_unreachable);
980 markFallthroughVisited(AS);
1000 markFallthroughVisited(AS);
1008 std::back_inserter(BlockQueue));
1014 return !!UnannotatedCnt;
1018 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1021 if (asFallThroughAttr(S))
1022 FallthroughStmts.insert(S);
1027 FoundSwitchStatements =
true;
1033 bool TraverseDecl(
Decl *D) {
return true; }
1036 bool TraverseLambdaBody(
LambdaExpr *LE) {
return true; }
1041 if (
const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1042 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1053 ElemIt != ElemEnd; ++ElemIt) {
1055 return CS->getStmt();
1067 bool FoundSwitchStatements;
1068 AttrStmts FallthroughStmts;
1070 llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
1077 tok::l_square, tok::l_square,
1079 tok::r_square, tok::r_square
1085 tok::r_square, tok::r_square
1088 bool PreferClangAttr = !PP.
getLangOpts().CPlusPlus1z;
1090 StringRef MacroName;
1091 if (PreferClangAttr)
1093 if (MacroName.empty())
1095 if (MacroName.empty() && !PreferClangAttr)
1097 if (MacroName.empty())
1098 MacroName = PreferClangAttr ?
"[[clang::fallthrough]]" :
"[[fallthrough]]";
1116 FallthroughMapper FM(S);
1117 FM.TraverseStmt(AC.
getBody());
1119 if (!FM.foundSwitchStatements())
1122 if (PerFunction && FM.getFallthroughStmts().empty())
1130 FM.fillReachableBlocks(Cfg);
1132 for (
const CFGBlock *B : llvm::reverse(*Cfg)) {
1135 if (!Label || !isa<SwitchCase>(Label))
1140 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt))
1143 S.
Diag(Label->getLocStart(),
1144 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1145 : diag::warn_unannotated_fallthrough);
1147 if (!AnnotatedCnt) {
1158 if (!(B->
empty() && Term && isa<BreakStmt>(Term))) {
1162 TextToInsert +=
"; ";
1163 S.
Diag(L, diag::note_insert_fallthrough_fixit) <<
1164 AnnotationSpelling <<
1168 S.
Diag(L, diag::note_insert_break_fixit) <<
1173 for (
const auto *F : FM.getFallthroughStmts())
1174 S.
Diag(F->getLocStart(), diag::err_fallthrough_attr_invalid_placement);
1182 switch (S->getStmtClass()) {
1183 case Stmt::ForStmtClass:
1184 case Stmt::WhileStmtClass:
1185 case Stmt::CXXForRangeStmtClass:
1186 case Stmt::ObjCForCollectionStmtClass:
1188 case Stmt::DoStmtClass: {
1189 const Expr *Cond = cast<DoStmt>(
S)->getCond();
1193 return Val.getBoolValue();
1210 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1219 for (WeakObjectUseMap::const_iterator
I = WeakMap.begin(), E = WeakMap.end();
1221 const WeakUseVector &Uses =
I->second;
1224 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1225 for ( ; UI != UE; ++UI) {
1238 if (UI == Uses.begin()) {
1239 WeakUseVector::const_iterator UI2 = UI;
1240 for (++UI2; UI2 != UE; ++UI2)
1241 if (UI2->isUnsafe())
1245 if (!
isInLoop(Ctx, PM, UI->getUseExpr()))
1248 const WeakObjectProfileTy &
Profile =
I->first;
1249 if (!Profile.isExactProfile())
1254 Base = Profile.getProperty();
1255 assert(Base &&
"A profile always has a base or property.");
1257 if (
const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1258 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1263 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(),
I));
1266 if (UsesByStmt.empty())
1271 std::sort(UsesByStmt.begin(), UsesByStmt.end(),
1272 [&
SM](
const StmtUsesPair &LHS,
const StmtUsesPair &RHS) {
1274 RHS.first->getLocStart());
1289 if (isa<sema::BlockScopeInfo>(CurFn))
1290 FunctionKind = Block;
1291 else if (isa<sema::LambdaScopeInfo>(CurFn))
1292 FunctionKind = Lambda;
1293 else if (isa<ObjCMethodDecl>(D))
1294 FunctionKind = Method;
1296 FunctionKind = Function;
1299 for (
const auto &P : UsesByStmt) {
1300 const Stmt *FirstRead = P.first;
1301 const WeakObjectProfileTy &Key = P.second->first;
1302 const WeakUseVector &Uses = P.second->second;
1310 if (Key.isExactProfile())
1311 DiagKind = diag::warn_arc_repeated_use_of_weak;
1313 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1325 const NamedDecl *KeyProp = Key.getProperty();
1326 if (isa<VarDecl>(KeyProp))
1327 ObjectKind = Variable;
1328 else if (isa<ObjCPropertyDecl>(KeyProp))
1330 else if (isa<ObjCMethodDecl>(KeyProp))
1331 ObjectKind = ImplicitProperty;
1332 else if (isa<ObjCIvarDecl>(KeyProp))
1335 llvm_unreachable(
"Unexpected weak object kind!");
1340 if (Prop->hasAttr<IBOutletAttr>())
1344 S.
Diag(FirstRead->getLocStart(), DiagKind)
1345 <<
int(ObjectKind) << KeyProp << int(FunctionKind)
1346 << FirstRead->getSourceRange();
1349 for (
const auto &Use : Uses) {
1350 if (Use.getUseExpr() == FirstRead)
1352 S.
Diag(Use.getUseExpr()->getLocStart(),
1353 diag::note_arc_weak_also_accessed_here)
1354 << Use.getUseExpr()->getSourceRange();
1363 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1367 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1371 UninitValsDiagReporter(
Sema &S) : S(S) {}
1374 MappedType &getUses(
const VarDecl *vd) {
1375 MappedType &V = uses[vd];
1376 if (!V.getPointer())
1377 V.setPointer(
new UsesVec());
1381 void handleUseOfUninitVariable(
const VarDecl *vd,
1383 getUses(vd).getPointer()->push_back(use);
1386 void handleSelfInit(
const VarDecl *vd)
override {
1387 getUses(vd).setInt(
true);
1391 for (
const auto &P : uses) {
1393 const MappedType &V = P.second;
1395 UsesVec *vec = V.getPointer();
1396 bool hasSelfInit = V.getInt();
1401 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1410 std::sort(vec->begin(), vec->end(),
1413 if (a.
getKind() != b.getKind())
1414 return a.
getKind() > b.getKind();
1415 return a.
getUser()->getLocStart() < b.getUser()->getLocStart();
1418 for (
const auto &U : *vec) {
1437 static bool hasAlwaysUninitializedUse(
const UsesVec* vec) {
1438 return std::any_of(vec->begin(), vec->end(), [](
const UninitUse &U) {
1450 typedef std::pair<PartialDiagnosticAt, OptionalNotes>
DelayedDiag;
1451 typedef std::list<DelayedDiag>
DiagList;
1453 struct SortDiagBySourceLocation {
1457 bool operator()(
const DelayedDiag &left,
const DelayedDiag &right) {
1470 namespace threadSafety {
1483 S.PDiag(diag::note_thread_warning_in_fun)
1494 S.PDiag(diag::note_thread_warning_in_fun)
1496 ONS.push_back(std::move(FNote));
1504 ONS.push_back(Note1);
1505 ONS.push_back(Note2);
1508 S.PDiag(diag::note_thread_warning_in_fun)
1510 ONS.push_back(std::move(FNote));
1516 void warnLockMismatch(
unsigned DiagID, StringRef
Kind,
Name LockName,
1523 Warnings.emplace_back(std::move(Warning), getNotes());
1531 void setVerbose(
bool b) {
Verbose = b; }
1537 void emitDiagnostics() {
1538 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
1540 S.Diag(
Diag.first.first,
Diag.first.second);
1541 for (
const auto &Note :
Diag.second)
1542 S.Diag(Note.first, Note.second);
1546 void handleInvalidLockExp(StringRef Kind,
SourceLocation Loc)
override {
1549 Warnings.emplace_back(std::move(Warning), getNotes());
1552 void handleUnmatchedUnlock(StringRef Kind,
Name LockName,
1554 warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc);
1557 void handleIncorrectUnlockKind(StringRef Kind,
Name LockName,
1563 << Kind << LockName << Received
1565 Warnings.emplace_back(std::move(Warning), getNotes());
1569 warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc);
1572 void handleMutexHeldEndOfScope(StringRef Kind,
Name LockName,
1576 unsigned DiagID = 0;
1579 DiagID = diag::warn_lock_some_predecessors;
1582 DiagID = diag::warn_expecting_lock_held_on_loop;
1585 DiagID = diag::warn_no_unlock;
1588 DiagID = diag::warn_expecting_locked;
1599 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1602 Warnings.emplace_back(std::move(Warning), getNotes());
1605 void handleExclusiveAndShared(StringRef Kind,
Name LockName,
1609 S.PDiag(diag::warn_lock_exclusive_and_shared)
1610 << Kind << LockName);
1612 << Kind << LockName);
1613 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1616 void handleNoMutexHeld(StringRef Kind,
const NamedDecl *D,
1620 "Only works for variables");
1622 diag::warn_variable_requires_any_lock:
1623 diag::warn_var_deref_requires_any_lock;
1626 Warnings.emplace_back(std::move(Warning), getNotes());
1629 void handleMutexNotHeld(StringRef Kind,
const NamedDecl *D,
1632 Name *PossibleMatch)
override {
1633 unsigned DiagID = 0;
1634 if (PossibleMatch) {
1637 DiagID = diag::warn_variable_requires_lock_precise;
1640 DiagID = diag::warn_var_deref_requires_lock_precise;
1643 DiagID = diag::warn_fun_requires_lock_precise;
1646 DiagID = diag::warn_guarded_pass_by_reference;
1649 DiagID = diag::warn_pt_guarded_pass_by_reference;
1659 S.PDiag(diag::note_guarded_by_declared_here)
1661 Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote));
1663 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1667 DiagID = diag::warn_variable_requires_lock;
1670 DiagID = diag::warn_var_deref_requires_lock;
1673 DiagID = diag::warn_fun_requires_lock;
1676 DiagID = diag::warn_guarded_pass_by_reference;
1679 DiagID = diag::warn_pt_guarded_pass_by_reference;
1687 S.PDiag(diag::note_guarded_by_declared_here)
1689 Warnings.emplace_back(std::move(Warning), getNotes(Note));
1691 Warnings.emplace_back(std::move(Warning), getNotes());
1695 void handleNegativeNotHeld(StringRef Kind,
Name LockName,
Name Neg,
1698 S.PDiag(diag::warn_acquire_requires_negative_cap)
1699 << Kind << LockName << Neg);
1700 Warnings.emplace_back(std::move(Warning), getNotes());
1703 void handleFunExcludesLock(StringRef Kind,
Name FunName,
Name LockName,
1706 << Kind << FunName << LockName);
1707 Warnings.emplace_back(std::move(Warning), getNotes());
1710 void handleLockAcquiredBefore(StringRef Kind,
Name L1Name,
Name L2Name,
1713 S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
1714 Warnings.emplace_back(std::move(Warning), getNotes());
1719 S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
1720 Warnings.emplace_back(std::move(Warning), getNotes());
1740 namespace consumed {
1742 class ConsumedWarningsHandler :
public ConsumedWarningsHandlerBase {
1749 ConsumedWarningsHandler(
Sema &S) : S(S) {}
1751 void emitDiagnostics()
override {
1752 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
1753 for (
const auto &
Diag : Warnings) {
1754 S.Diag(
Diag.first.first,
Diag.first.second);
1755 for (
const auto &Note :
Diag.second)
1756 S.Diag(Note.first, Note.second);
1761 StringRef VariableName)
override {
1769 StringRef VariableName,
1770 StringRef ExpectedState,
1771 StringRef ObservedState)
override {
1774 diag::warn_param_return_typestate_mismatch) << VariableName <<
1775 ExpectedState << ObservedState);
1780 void warnParamTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1781 StringRef ObservedState)
override {
1784 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
1790 StringRef TypeName)
override {
1792 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
1797 void warnReturnTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1798 StringRef ObservedState)
override {
1801 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
1806 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef
State,
1810 diag::warn_use_of_temp_in_invalid_state) << MethodName <<
State);
1815 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
1819 MethodName << VariableName <<
State);
1834 enableCheckFallThrough = 1;
1835 enableCheckUnreachable = 0;
1836 enableThreadSafetyAnalysis = 0;
1837 enableConsumedAnalysis = 0;
1846 NumFunctionsAnalyzed(0),
1847 NumFunctionsWithBadCFGs(0),
1849 MaxCFGBlocksPerFunction(0),
1850 NumUninitAnalysisFunctions(0),
1851 NumUninitAnalysisVariables(0),
1852 MaxUninitAnalysisVariablesPerFunction(0),
1853 NumUninitAnalysisBlockVisits(0),
1854 MaxUninitAnalysisBlockVisitsPerFunction(0) {
1856 using namespace diag;
1859 DefaultPolicy.enableCheckUnreachable =
1862 isEnabled(D, warn_unreachable_return) ||
1863 isEnabled(D, warn_unreachable_loop_increment);
1865 DefaultPolicy.enableThreadSafetyAnalysis =
1868 DefaultPolicy.enableConsumedAnalysis =
1869 isEnabled(D, warn_use_in_invalid_state);
1874 S.
Diag(D.Loc, D.PD);
1893 S.SourceMgr.isInSystemHeader(D->getLocation()))
1897 if (cast<DeclContext>(D)->isDependentContext())
1906 const Stmt *Body = D->getBody();
1928 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
1929 P.enableConsumedAnalysis) {
1946 std::unique_ptr<LogicalErrorHandler> LEH;
1947 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
1948 D->getLocStart())) {
1949 LEH.reset(
new LogicalErrorHandler(S));
1955 bool analyzed =
false;
1966 bool processed =
false;
1977 S.Diag(D.Loc, D.PD);
1983 S.Diag(D.Loc, D.PD);
1993 if (P.enableCheckFallThrough) {
1994 const CheckFallThroughDiagnostics &CD =
1995 (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
1996 : (isa<CXXMethodDecl>(D) &&
1997 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
1998 cast<CXXMethodDecl>(D)->getParent()->isLambda())
1999 ? CheckFallThroughDiagnostics::MakeForLambda()
2000 : CheckFallThroughDiagnostics::MakeForFunction(D));
2005 if (P.enableCheckUnreachable) {
2010 bool isTemplateInstantiation =
false;
2011 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
2012 isTemplateInstantiation = Function->isTemplateInstantiation();
2013 if (!isTemplateInstantiation)
2018 if (P.enableThreadSafetyAnalysis) {
2021 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
2022 if (!Diags.
isIgnored(diag::warn_thread_safety_beta, D->getLocStart()))
2023 Reporter.setIssueBetaWarnings(
true);
2024 if (!Diags.
isIgnored(diag::warn_thread_safety_verbose, D->getLocStart()))
2025 Reporter.setVerbose(
true);
2028 &S.ThreadSafetyDeclCache);
2029 Reporter.emitDiagnostics();
2033 if (P.enableConsumedAnalysis) {
2034 consumed::ConsumedWarningsHandler WarningHandler(S);
2039 if (!Diags.
isIgnored(diag::warn_uninit_var, D->getLocStart()) ||
2040 !Diags.
isIgnored(diag::warn_sometimes_uninit_var, D->getLocStart()) ||
2041 !Diags.
isIgnored(diag::warn_maybe_uninit_var, D->getLocStart())) {
2043 UninitValsDiagReporter reporter(S);
2050 ++NumUninitAnalysisFunctions;
2053 MaxUninitAnalysisVariablesPerFunction =
2054 std::max(MaxUninitAnalysisVariablesPerFunction,
2056 MaxUninitAnalysisBlockVisitsPerFunction =
2057 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
2063 bool FallThroughDiagFull =
2064 !Diags.
isIgnored(diag::warn_unannotated_fallthrough, D->getLocStart());
2065 bool FallThroughDiagPerFunction = !Diags.
isIgnored(
2066 diag::warn_unannotated_fallthrough_per_function, D->getLocStart());
2067 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
2072 if (S.getLangOpts().ObjCWeak &&
2073 !Diags.
isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart()))
2078 if (!Diags.
isIgnored(diag::warn_infinite_recursive_function,
2079 D->getLocStart())) {
2080 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2087 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2088 D->getLocStart())) {
2094 ++NumFunctionsAnalyzed;
2098 NumCFGBlocks += cfg->getNumBlockIDs();
2099 MaxCFGBlocksPerFunction =
std::max(MaxCFGBlocksPerFunction,
2100 cfg->getNumBlockIDs());
2102 ++NumFunctionsWithBadCFGs;
2108 llvm::errs() <<
"\n*** Analysis Based Warnings Stats:\n";
2110 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
2111 unsigned AvgCFGBlocksPerFunction =
2112 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
2113 llvm::errs() << NumFunctionsAnalyzed <<
" functions analyzed ("
2114 << NumFunctionsWithBadCFGs <<
" w/o CFGs).\n"
2115 <<
" " << NumCFGBlocks <<
" CFG blocks built.\n"
2116 <<
" " << AvgCFGBlocksPerFunction
2117 <<
" average CFG blocks per function.\n"
2118 <<
" " << MaxCFGBlocksPerFunction
2119 <<
" max CFG blocks per function.\n";
2121 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
2122 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
2123 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
2124 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
2125 llvm::errs() << NumUninitAnalysisFunctions
2126 <<
" functions analyzed for uninitialiazed variables\n"
2127 <<
" " << NumUninitAnalysisVariables <<
" variables analyzed.\n"
2128 <<
" " << AvgUninitVariablesPerFunction
2129 <<
" average variables per function.\n"
2130 <<
" " << MaxUninitAnalysisVariablesPerFunction
2131 <<
" max variables per function.\n"
2132 <<
" " << NumUninitAnalysisBlockVisits <<
" block visits.\n"
2133 <<
" " << AvgUninitBlockVisitsPerFunction
2134 <<
" average block visits per function.\n"
2135 <<
" " << MaxUninitAnalysisBlockVisitsPerFunction
2136 <<
" 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
FunctionDecl - An instance of this class is created to represent 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.
ASTContext & getASTContext() const
A (possibly-)qualified type.
SourceLocation getBegin() const
bool HasFallthroughStmt
Whether there is a fallthrough statement in this function.
succ_iterator succ_begin()
const LangOptions & getLangOpts() const
FunctionType - C99 6.7.5.3 - Function Declarators.
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.
Represents an attribute applied to a statement.
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.
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.
Defines the clang::Expr interface and subclasses for C++ expressions.
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.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
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()
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)
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.
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
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
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.
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;)
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.
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.
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...
Expr * getTrueExpr() const
reverse_iterator rbegin()
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.
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)
bool isValid() const
Return true if this is a valid SourceLocation object.
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
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>::".
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
SourceLocation FunLocation
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
SourceRange getSourceRange() const override LLVM_READONLY
static bool isLogicalOp(Opcode Opc)
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.
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()
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
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.
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
const Stmt * getThen() const
SwitchStmt - This represents a 'switch' stmt.
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.
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.
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...
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...
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)
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.
FunctionDecl * getCanonicalDecl() override
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).
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.