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())) {
225 while (!Stack.empty()) {
246 unsigned next_ID = (*I)->getBlockID();
247 if (States[next_ID] < CurState) {
248 States[next_ID] = CurState;
295 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()) {
364 CFGBlock *CurBlock = Stack.pop_back_val();
378 for (
const auto &I : CurBlock->
succs())
379 if (I.isReachable()) {
380 unsigned NextID = I->getBlockID();
382 States[NextID] = CurState;
383 }
else if (States[NextID] < CurState) {
384 States[NextID] = CurState;
398 S.
Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
400 (isa<CXXDestructorDecl>(FD) ||
404 getAs<FunctionProtoType>())
406 << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
469 for (
const auto *B : *cfg) {
470 if (!live[B->getBlockID()]) {
471 if (B->pred_begin() == B->pred_end()) {
472 if (B->getTerminator() && isa<CXXTryStmt>(B->getTerminator()))
484 bool HasLiveReturn =
false;
485 bool HasFakeEdge =
false;
486 bool HasPlainEdge =
false;
487 bool HasAbnormalEdge =
false;
495 I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) {
504 HasAbnormalEdge =
true;
513 for ( ; ri != re ; ++ri)
520 HasAbnormalEdge =
true;
530 if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
531 HasLiveReturn =
true;
534 if (isa<ObjCAtThrowStmt>(S)) {
538 if (isa<CXXThrowExpr>(S)) {
542 if (isa<MSAsmStmt>(S)) {
545 HasLiveReturn =
true;
548 if (isa<CXXTryStmt>(S)) {
549 HasAbnormalEdge =
true;
554 HasAbnormalEdge =
true;
565 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
575 struct CheckFallThroughDiagnostics {
576 unsigned diag_MaybeFallThrough_HasNoReturn;
577 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
578 unsigned diag_AlwaysFallThrough_HasNoReturn;
579 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
580 unsigned diag_NeverFallThroughOrReturn;
581 enum { Function, Block, Lambda, Coroutine } funMode;
584 static CheckFallThroughDiagnostics MakeForFunction(
const Decl *Func) {
585 CheckFallThroughDiagnostics D;
587 D.diag_MaybeFallThrough_HasNoReturn =
588 diag::warn_falloff_noreturn_function;
589 D.diag_MaybeFallThrough_ReturnsNonVoid =
590 diag::warn_maybe_falloff_nonvoid_function;
591 D.diag_AlwaysFallThrough_HasNoReturn =
592 diag::warn_falloff_noreturn_function;
593 D.diag_AlwaysFallThrough_ReturnsNonVoid =
594 diag::warn_falloff_nonvoid_function;
598 bool isVirtualMethod =
false;
599 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
600 isVirtualMethod = Method->isVirtual();
604 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
605 isTemplateInstantiation = Function->isTemplateInstantiation();
607 if (!isVirtualMethod && !isTemplateInstantiation)
608 D.diag_NeverFallThroughOrReturn =
609 diag::warn_suggest_noreturn_function;
611 D.diag_NeverFallThroughOrReturn = 0;
613 D.funMode = Function;
617 static CheckFallThroughDiagnostics MakeForCoroutine(
const Decl *Func) {
618 CheckFallThroughDiagnostics D;
620 D.diag_MaybeFallThrough_HasNoReturn = 0;
621 D.diag_MaybeFallThrough_ReturnsNonVoid =
622 diag::warn_maybe_falloff_nonvoid_coroutine;
623 D.diag_AlwaysFallThrough_HasNoReturn = 0;
624 D.diag_AlwaysFallThrough_ReturnsNonVoid =
625 diag::warn_falloff_nonvoid_coroutine;
626 D.funMode = Coroutine;
630 static CheckFallThroughDiagnostics MakeForBlock() {
631 CheckFallThroughDiagnostics D;
632 D.diag_MaybeFallThrough_HasNoReturn =
633 diag::err_noreturn_block_has_return_expr;
634 D.diag_MaybeFallThrough_ReturnsNonVoid =
635 diag::err_maybe_falloff_nonvoid_block;
636 D.diag_AlwaysFallThrough_HasNoReturn =
637 diag::err_noreturn_block_has_return_expr;
638 D.diag_AlwaysFallThrough_ReturnsNonVoid =
639 diag::err_falloff_nonvoid_block;
640 D.diag_NeverFallThroughOrReturn = 0;
645 static CheckFallThroughDiagnostics MakeForLambda() {
646 CheckFallThroughDiagnostics D;
647 D.diag_MaybeFallThrough_HasNoReturn =
648 diag::err_noreturn_lambda_has_return_expr;
649 D.diag_MaybeFallThrough_ReturnsNonVoid =
650 diag::warn_maybe_falloff_nonvoid_lambda;
651 D.diag_AlwaysFallThrough_HasNoReturn =
652 diag::err_noreturn_lambda_has_return_expr;
653 D.diag_AlwaysFallThrough_ReturnsNonVoid =
654 diag::warn_falloff_nonvoid_lambda;
655 D.diag_NeverFallThroughOrReturn = 0;
661 bool HasNoReturn)
const {
662 if (funMode == Function) {
663 return (ReturnsVoid ||
664 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function,
667 D.
isIgnored(diag::warn_noreturn_function_has_return_expr,
670 D.
isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
672 if (funMode == Coroutine) {
673 return (ReturnsVoid ||
674 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
675 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
680 return ReturnsVoid && !HasNoReturn;
692 const CheckFallThroughDiagnostics& CD,
695 bool ReturnsVoid =
false;
696 bool HasNoReturn =
false;
699 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
700 if (
const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
701 ReturnsVoid = CBody->getFallthroughHandler() !=
nullptr;
703 ReturnsVoid = FD->getReturnType()->isVoidType();
704 HasNoReturn = FD->isNoReturn();
706 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
707 ReturnsVoid = MD->getReturnType()->isVoidType();
708 HasNoReturn = MD->hasAttr<NoReturnAttr>();
710 else if (isa<BlockDecl>(D)) {
714 if (FT->getReturnType()->isVoidType())
716 if (FT->getNoReturnAttr())
724 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
740 EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
741 else if (!ReturnsVoid)
742 EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
746 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
747 else if (!ReturnsVoid)
748 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
751 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
752 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
753 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
754 }
else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
755 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
757 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
782 : Inherited(Context), FoundReference(
false), Needle(Needle) {}
784 void VisitExpr(
const Expr *E) {
789 Inherited::VisitExpr(E);
794 FoundReference =
true;
796 Inherited::VisitDeclRefExpr(E);
799 bool doesContainReference()
const {
return FoundReference; }
807 S.
Diag(VD->
getLocation(), diag::note_block_var_fixit_add_initialization)
828 S.
Diag(Loc, diag::note_var_fixit_add_initialization) << VD->
getDeclName()
836 const Stmt *Else,
bool CondVal,
862 bool IsCapturedByBlock) {
863 bool Diagnosed =
false;
896 const Stmt *Term = I->Terminator;
906 int RemoveDiagKind = -1;
907 const char *FixitStr =
908 S.
getLangOpts().CPlusPlus ? (I->Output ?
"true" :
"false")
909 : (I->Output ?
"1" :
"0");
912 switch (Term ? Term->
getStmtClass() : Stmt::DeclStmtClass) {
919 case Stmt::IfStmtClass: {
920 const IfStmt *IS = cast<IfStmt>(Term);
926 I->Output, Fixit1, Fixit2);
929 case Stmt::ConditionalOperatorClass: {
936 I->Output, Fixit1, Fixit2);
939 case Stmt::BinaryOperatorClass: {
947 if ((BO->
getOpcode() == BO_LAnd && I->Output) ||
948 (BO->
getOpcode() == BO_LOr && !I->Output))
959 case Stmt::WhileStmtClass:
962 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
966 case Stmt::ForStmtClass:
969 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
976 case Stmt::CXXForRangeStmtClass:
977 if (I->Output == 1) {
985 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
989 case Stmt::DoStmtClass:
992 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
998 case Stmt::CaseStmtClass:
1001 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
1003 case Stmt::DefaultStmtClass:
1006 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
1010 S.
Diag(Range.
getBegin(), diag::warn_sometimes_uninit_var)
1011 << VD->
getDeclName() << IsCapturedByBlock << DiagKind
1012 << Str << I->Output << Range;
1013 S.
Diag(User->getLocStart(), diag::note_uninit_var_use)
1014 << IsCapturedByBlock << User->getSourceRange();
1015 if (RemoveDiagKind != -1)
1017 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
1035 bool alwaysReportSelfInit =
false) {
1049 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
1052 ContainsReference CR(S.
Context, DRE);
1053 CR.Visit(Initializer);
1054 if (CR.doesContainReference()) {
1055 S.
Diag(DRE->getLocStart(),
1056 diag::warn_uninit_self_reference_in_init)
1067 diag::warn_uninit_byref_blockvar_captured_by_block)
1086 FallthroughMapper(
Sema &S)
1087 : FoundSwitchStatements(
false),
1091 bool foundSwitchStatements()
const {
return FoundSwitchStatements; }
1094 bool Found = FallthroughStmts.erase(Stmt);
1099 typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;
1101 const AttrStmts &getFallthroughStmts()
const {
1102 return FallthroughStmts;
1105 void fillReachableBlocks(
CFG *Cfg) {
1106 assert(ReachableBlocks.empty() &&
"ReachableBlocks already filled");
1107 std::deque<const CFGBlock *> BlockQueue;
1109 ReachableBlocks.insert(&Cfg->
getEntry());
1110 BlockQueue.push_back(&Cfg->
getEntry());
1115 for (
const auto *B : *Cfg) {
1116 const Stmt *L = B->getLabel();
1117 if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1118 BlockQueue.push_back(B);
1121 while (!BlockQueue.empty()) {
1123 BlockQueue.pop_front();
1127 if (*I && ReachableBlocks.insert(*I).second)
1128 BlockQueue.push_back(*I);
1133 bool checkFallThroughIntoBlock(
const CFGBlock &B,
int &AnnotatedCnt,
1134 bool IsTemplateInstantiation) {
1135 assert(!ReachableBlocks.empty() &&
"ReachableBlocks empty");
1137 int UnannotatedCnt = 0;
1141 while (!BlockQueue.empty()) {
1143 BlockQueue.pop_front();
1147 if (Term && isa<SwitchStmt>(Term))
1158 if (!ReachableBlocks.count(P)) {
1160 ElemEnd = P->
rend();
1161 ElemIt != ElemEnd; ++ElemIt) {
1163 if (
const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1167 if (!IsTemplateInstantiation)
1168 S.
Diag(AS->getLocStart(),
1169 diag::warn_fallthrough_attr_unreachable);
1170 markFallthroughVisited(AS);
1190 markFallthroughVisited(AS);
1198 std::back_inserter(BlockQueue));
1204 return !!UnannotatedCnt;
1208 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1211 if (asFallThroughAttr(S))
1212 FallthroughStmts.insert(S);
1217 FoundSwitchStatements =
true;
1223 bool TraverseDecl(
Decl *D) {
return true; }
1226 bool TraverseLambdaBody(
LambdaExpr *LE) {
return true; }
1231 if (
const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1232 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1243 ElemIt != ElemEnd; ++ElemIt) {
1245 return CS->getStmt();
1251 if (!isa<SwitchCase>(SW->getSubStmt()))
1252 return SW->getSubStmt();
1257 bool FoundSwitchStatements;
1258 AttrStmts FallthroughStmts;
1260 llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
1267 tok::l_square, tok::l_square,
1269 tok::r_square, tok::r_square
1275 tok::r_square, tok::r_square
1278 bool PreferClangAttr = !PP.
getLangOpts().CPlusPlus17;
1280 StringRef MacroName;
1281 if (PreferClangAttr)
1283 if (MacroName.empty())
1285 if (MacroName.empty() && !PreferClangAttr)
1287 if (MacroName.empty())
1288 MacroName = PreferClangAttr ?
"[[clang::fallthrough]]" :
"[[fallthrough]]";
1305 FallthroughMapper FM(S);
1306 FM.TraverseStmt(AC.
getBody());
1308 if (!FM.foundSwitchStatements())
1311 if (PerFunction && FM.getFallthroughStmts().empty())
1319 FM.fillReachableBlocks(Cfg);
1321 for (
const CFGBlock *B : llvm::reverse(*Cfg)) {
1324 if (!Label || !isa<SwitchCase>(Label))
1329 bool IsTemplateInstantiation =
false;
1331 IsTemplateInstantiation = Function->isTemplateInstantiation();
1332 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1333 IsTemplateInstantiation))
1337 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1338 : diag::warn_unannotated_fallthrough);
1340 if (!AnnotatedCnt) {
1345 const Stmt *Term = B->getTerminator();
1347 while (B->empty() && !Term && B->succ_size() == 1) {
1348 B = *B->succ_begin();
1349 Term = B->getTerminator();
1351 if (!(B->empty() && Term && isa<BreakStmt>(Term))) {
1355 TextToInsert +=
"; ";
1356 S.
Diag(L, diag::note_insert_fallthrough_fixit) <<
1357 AnnotationSpelling <<
1361 S.
Diag(L, diag::note_insert_break_fixit) <<
1366 for (
const auto *F : FM.getFallthroughStmts())
1367 S.
Diag(F->getLocStart(), diag::err_fallthrough_attr_invalid_placement);
1376 case Stmt::ForStmtClass:
1377 case Stmt::WhileStmtClass:
1378 case Stmt::CXXForRangeStmtClass:
1379 case Stmt::ObjCForCollectionStmtClass:
1381 case Stmt::DoStmtClass: {
1382 const Expr *Cond = cast<DoStmt>(S)->getCond();
1386 return Val.getBoolValue();
1403 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1412 for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
1414 const WeakUseVector &Uses = I->second;
1417 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1418 for ( ; UI != UE; ++UI) {
1431 if (UI == Uses.begin()) {
1432 WeakUseVector::const_iterator UI2 = UI;
1433 for (++UI2; UI2 != UE; ++UI2)
1434 if (UI2->isUnsafe())
1438 if (!
isInLoop(Ctx, PM, UI->getUseExpr()))
1441 const WeakObjectProfileTy &Profile = I->first;
1442 if (!Profile.isExactProfile())
1447 Base = Profile.getProperty();
1448 assert(Base &&
"A profile always has a base or property.");
1450 if (
const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1451 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1456 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
1459 if (UsesByStmt.empty())
1464 std::sort(UsesByStmt.begin(), UsesByStmt.end(),
1465 [&
SM](
const StmtUsesPair &LHS,
const StmtUsesPair &RHS) {
1467 RHS.first->getLocStart());
1482 if (isa<sema::BlockScopeInfo>(CurFn))
1483 FunctionKind = Block;
1484 else if (isa<sema::LambdaScopeInfo>(CurFn))
1485 FunctionKind = Lambda;
1486 else if (isa<ObjCMethodDecl>(D))
1487 FunctionKind = Method;
1489 FunctionKind = Function;
1492 for (
const auto &
P : UsesByStmt) {
1493 const Stmt *FirstRead =
P.first;
1494 const WeakObjectProfileTy &Key =
P.second->first;
1495 const WeakUseVector &Uses =
P.second->second;
1503 if (Key.isExactProfile())
1504 DiagKind = diag::warn_arc_repeated_use_of_weak;
1506 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1518 const NamedDecl *KeyProp = Key.getProperty();
1519 if (isa<VarDecl>(KeyProp))
1520 ObjectKind = Variable;
1521 else if (isa<ObjCPropertyDecl>(KeyProp))
1523 else if (isa<ObjCMethodDecl>(KeyProp))
1524 ObjectKind = ImplicitProperty;
1525 else if (isa<ObjCIvarDecl>(KeyProp))
1528 llvm_unreachable(
"Unexpected weak object kind!");
1533 if (Prop->hasAttr<IBOutletAttr>())
1538 <<
int(ObjectKind) << KeyProp << int(FunctionKind)
1542 for (
const auto &Use : Uses) {
1543 if (Use.getUseExpr() == FirstRead)
1545 S.
Diag(Use.getUseExpr()->getLocStart(),
1546 diag::note_arc_weak_also_accessed_here)
1547 << Use.getUseExpr()->getSourceRange();
1556 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1560 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1564 UninitValsDiagReporter(
Sema &S) : S(S) {}
1567 MappedType &getUses(
const VarDecl *vd) {
1568 MappedType &V = uses[vd];
1569 if (!V.getPointer())
1570 V.setPointer(
new UsesVec());
1574 void handleUseOfUninitVariable(
const VarDecl *vd,
1576 getUses(vd).getPointer()->push_back(use);
1579 void handleSelfInit(
const VarDecl *vd)
override {
1580 getUses(vd).setInt(
true);
1584 for (
const auto &
P : uses) {
1586 const MappedType &V =
P.second;
1588 UsesVec *vec = V.getPointer();
1589 bool hasSelfInit = V.getInt();
1594 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1603 std::sort(vec->begin(), vec->end(),
1606 if (a.
getKind() != b.getKind())
1607 return a.
getKind() > b.getKind();
1611 for (
const auto &U : *vec) {
1630 static bool hasAlwaysUninitializedUse(
const UsesVec* vec) {
1631 return std::any_of(vec->begin(), vec->end(), [](
const UninitUse &U) {
1643 typedef std::pair<PartialDiagnosticAt, OptionalNotes>
DelayedDiag;
1644 typedef std::list<DelayedDiag>
DiagList;
1646 struct SortDiagBySourceLocation {
1650 bool operator()(
const DelayedDiag &left,
const DelayedDiag &right) {
1663 namespace threadSafety {
1674 if (Verbose && CurrentFunction) {
1676 S.
PDiag(diag::note_thread_warning_in_fun)
1685 if (Verbose && CurrentFunction) {
1687 S.
PDiag(diag::note_thread_warning_in_fun)
1689 ONS.push_back(std::move(FNote));
1697 ONS.push_back(Note1);
1698 ONS.push_back(Note2);
1699 if (Verbose && CurrentFunction) {
1701 S.
PDiag(diag::note_thread_warning_in_fun)
1703 ONS.push_back(std::move(FNote));
1709 void warnLockMismatch(
unsigned DiagID, StringRef
Kind, Name LockName,
1716 Warnings.emplace_back(std::move(
Warning), getNotes());
1721 : S(S), FunLocation(FL), FunEndLocation(FEL),
1722 CurrentFunction(
nullptr), Verbose(
false) {}
1724 void setVerbose(
bool b) { Verbose = b; }
1730 void emitDiagnostics() {
1732 for (
const auto &
Diag : Warnings) {
1734 for (
const auto &Note :
Diag.second)
1735 S.
Diag(Note.first, Note.second);
1739 void handleInvalidLockExp(StringRef Kind,
SourceLocation Loc)
override {
1742 Warnings.emplace_back(std::move(
Warning), getNotes());
1745 void handleUnmatchedUnlock(StringRef Kind, Name LockName,
1747 warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc);
1750 void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
1756 << Kind << LockName << Received
1758 Warnings.emplace_back(std::move(
Warning), getNotes());
1761 void handleDoubleLock(StringRef Kind, Name LockName,
SourceLocation Loc)
override {
1762 warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc);
1765 void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
1769 unsigned DiagID = 0;
1772 DiagID = diag::warn_lock_some_predecessors;
1775 DiagID = diag::warn_expecting_lock_held_on_loop;
1778 DiagID = diag::warn_no_unlock;
1781 DiagID = diag::warn_expecting_locked;
1785 LocEndOfScope = FunEndLocation;
1792 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1795 Warnings.emplace_back(std::move(
Warning), getNotes());
1798 void handleExclusiveAndShared(StringRef Kind, Name LockName,
1802 S.
PDiag(diag::warn_lock_exclusive_and_shared)
1803 << Kind << LockName);
1805 << Kind << LockName);
1806 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1809 void handleNoMutexHeld(StringRef Kind,
const NamedDecl *D,
1813 "Only works for variables");
1815 diag::warn_variable_requires_any_lock:
1816 diag::warn_var_deref_requires_any_lock;
1819 Warnings.emplace_back(std::move(
Warning), getNotes());
1822 void handleMutexNotHeld(StringRef Kind,
const NamedDecl *D,
1825 Name *PossibleMatch)
override {
1826 unsigned DiagID = 0;
1827 if (PossibleMatch) {
1830 DiagID = diag::warn_variable_requires_lock_precise;
1833 DiagID = diag::warn_var_deref_requires_lock_precise;
1836 DiagID = diag::warn_fun_requires_lock_precise;
1839 DiagID = diag::warn_guarded_pass_by_reference;
1842 DiagID = diag::warn_pt_guarded_pass_by_reference;
1852 S.
PDiag(diag::note_guarded_by_declared_here)
1854 Warnings.emplace_back(std::move(
Warning), getNotes(Note, VNote));
1856 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1860 DiagID = diag::warn_variable_requires_lock;
1863 DiagID = diag::warn_var_deref_requires_lock;
1866 DiagID = diag::warn_fun_requires_lock;
1869 DiagID = diag::warn_guarded_pass_by_reference;
1872 DiagID = diag::warn_pt_guarded_pass_by_reference;
1880 S.
PDiag(diag::note_guarded_by_declared_here)
1882 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1884 Warnings.emplace_back(std::move(
Warning), getNotes());
1888 void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
1891 S.
PDiag(diag::warn_acquire_requires_negative_cap)
1892 << Kind << LockName << Neg);
1893 Warnings.emplace_back(std::move(
Warning), getNotes());
1896 void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
1899 << Kind << FunName << LockName);
1900 Warnings.emplace_back(std::move(
Warning), getNotes());
1903 void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
1906 S.
PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
1907 Warnings.emplace_back(std::move(
Warning), getNotes());
1910 void handleBeforeAfterCycle(Name L1Name,
SourceLocation Loc)
override {
1912 S.
PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
1913 Warnings.emplace_back(std::move(
Warning), getNotes());
1917 CurrentFunction = FD;
1921 CurrentFunction =
nullptr;
1933 namespace consumed {
1935 class ConsumedWarningsHandler :
public ConsumedWarningsHandlerBase {
1942 ConsumedWarningsHandler(
Sema &S) : S(S) {}
1944 void emitDiagnostics()
override {
1946 for (
const auto &
Diag : Warnings) {
1948 for (
const auto &
Note :
Diag.second)
1954 StringRef VariableName)
override {
1962 StringRef VariableName,
1963 StringRef ExpectedState,
1964 StringRef ObservedState)
override {
1967 diag::warn_param_return_typestate_mismatch) << VariableName <<
1968 ExpectedState << ObservedState);
1973 void warnParamTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1974 StringRef ObservedState)
override {
1977 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
1983 StringRef TypeName)
override {
1985 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
1990 void warnReturnTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1991 StringRef ObservedState)
override {
1994 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
1999 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef
State,
2003 diag::warn_use_of_temp_in_invalid_state) << MethodName <<
State);
2008 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
2012 MethodName << VariableName <<
State);
2027 enableCheckFallThrough = 1;
2028 enableCheckUnreachable = 0;
2029 enableThreadSafetyAnalysis = 0;
2030 enableConsumedAnalysis = 0;
2039 NumFunctionsAnalyzed(0),
2040 NumFunctionsWithBadCFGs(0),
2042 MaxCFGBlocksPerFunction(0),
2043 NumUninitAnalysisFunctions(0),
2044 NumUninitAnalysisVariables(0),
2045 MaxUninitAnalysisVariablesPerFunction(0),
2046 NumUninitAnalysisBlockVisits(0),
2047 MaxUninitAnalysisBlockVisitsPerFunction(0) {
2049 using namespace diag;
2052 DefaultPolicy.enableCheckUnreachable =
2055 isEnabled(D, warn_unreachable_return) ||
2056 isEnabled(D, warn_unreachable_loop_increment);
2058 DefaultPolicy.enableThreadSafetyAnalysis =
2061 DefaultPolicy.enableConsumedAnalysis =
2062 isEnabled(D, warn_use_in_invalid_state);
2067 S.
Diag(D.Loc, D.PD);
2090 if (cast<DeclContext>(D)->isDependentContext())
2121 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
2122 P.enableConsumedAnalysis) {
2139 std::unique_ptr<LogicalErrorHandler> LEH;
2140 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2142 LEH.reset(
new LogicalErrorHandler(S));
2148 bool analyzed =
false;
2159 bool processed =
false;
2170 S.
Diag(D.Loc, D.PD);
2176 S.
Diag(D.Loc, D.PD);
2186 if (P.enableCheckFallThrough) {
2187 const CheckFallThroughDiagnostics &CD =
2189 ? CheckFallThroughDiagnostics::MakeForBlock()
2190 : (isa<CXXMethodDecl>(D) &&
2191 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2192 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2193 ? CheckFallThroughDiagnostics::MakeForLambda()
2195 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2196 : CheckFallThroughDiagnostics::MakeForFunction(D)));
2201 if (P.enableCheckUnreachable) {
2207 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
2208 isTemplateInstantiation = Function->isTemplateInstantiation();
2209 if (!isTemplateInstantiation)
2214 if (P.enableThreadSafetyAnalysis) {
2217 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
2219 Reporter.setIssueBetaWarnings(
true);
2221 Reporter.setVerbose(
true);
2225 Reporter.emitDiagnostics();
2229 if (P.enableConsumedAnalysis) {
2230 consumed::ConsumedWarningsHandler WarningHandler(S);
2239 UninitValsDiagReporter reporter(S);
2246 ++NumUninitAnalysisFunctions;
2249 MaxUninitAnalysisVariablesPerFunction =
2250 std::max(MaxUninitAnalysisVariablesPerFunction,
2252 MaxUninitAnalysisBlockVisitsPerFunction =
2253 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
2259 bool FallThroughDiagFull =
2261 bool FallThroughDiagPerFunction = !Diags.
isIgnored(
2262 diag::warn_unannotated_fallthrough_per_function, D->
getLocStart());
2263 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
2274 if (!Diags.
isIgnored(diag::warn_infinite_recursive_function,
2276 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2283 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2289 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2296 ++NumFunctionsAnalyzed;
2301 MaxCFGBlocksPerFunction =
std::max(MaxCFGBlocksPerFunction,
2302 cfg->getNumBlockIDs());
2304 ++NumFunctionsWithBadCFGs;
2310 llvm::errs() <<
"\n*** Analysis Based Warnings Stats:\n";
2312 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
2313 unsigned AvgCFGBlocksPerFunction =
2314 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
2315 llvm::errs() << NumFunctionsAnalyzed <<
" functions analyzed (" 2316 << NumFunctionsWithBadCFGs <<
" w/o CFGs).\n" 2317 <<
" " << NumCFGBlocks <<
" CFG blocks built.\n" 2318 <<
" " << AvgCFGBlocksPerFunction
2319 <<
" average CFG blocks per function.\n" 2320 <<
" " << MaxCFGBlocksPerFunction
2321 <<
" max CFG blocks per function.\n";
2323 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
2324 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
2325 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
2326 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
2327 llvm::errs() << NumUninitAnalysisFunctions
2328 <<
" functions analyzed for uninitialiazed variables\n" 2329 <<
" " << NumUninitAnalysisVariables <<
" variables analyzed.\n" 2330 <<
" " << AvgUninitVariablesPerFunction
2331 <<
" average variables per function.\n" 2332 <<
" " << MaxUninitAnalysisVariablesPerFunction
2333 <<
" max variables per function.\n" 2334 <<
" " << NumUninitAnalysisBlockVisits <<
" block visits.\n" 2335 <<
" " << AvgUninitBlockVisitsPerFunction
2336 <<
" average block visits per function.\n" 2337 <<
" " << MaxUninitAnalysisBlockVisitsPerFunction
2338 <<
" 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...
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.
const Stmt * getElse() const
A (possibly-)qualified type.
bool isBlockPointerType() const
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
static bool isThrowCaught(const CXXThrowExpr *Throw, const CXXCatchStmt *Catch)
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.
CXXCatchStmt * getHandler(unsigned i)
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 base class of the type hierarchy.
The use is uninitialized whenever a certain branch is taken.
Stmt * getParent(Stmt *) const
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
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()
void run(AnalysisDeclContext &AC)
Check a function's CFG for consumed violations.
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...
VarDecl - An instance of this class is created to represent 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
TextDiagnosticBuffer::DiagList DiagList
LabelStmt - Represents a label, which has a substatement.
LockKind
This enum distinguishes between different kinds of lock actions.
DeclarationName getDeclName() const
getDeclName - 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 ...
QualType getCaughtType() const
std::pair< PartialDiagnosticAt, OptionalNotes > DelayedDiag
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)
bool isReferenceType() const
const LangOptions & getLangOpts() const
SmallVectorImpl< Branch >::const_iterator branch_iterator
AdjacentBlocks::const_iterator const_succ_iterator
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
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)
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)...
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...
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.
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.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
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.
SourceLocation getLocEnd() const LLVM_READONLY
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...
CFGBlock - 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.
QualType getPointeeType() const
CFG - 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.
CXXTryStmt - A C++ try block, including all handlers.
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)
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.
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;)
ASTContext & getASTContext() const
Encodes a location in the source.
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
SourceLocation getOperatorLoc() const
static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc, const FunctionDecl *FD)
unsigned getNumHandlers() const
std::string getNameAsString() const
getNameAsString - Get a human-readable name for the declaration, even if it is one of the special kin...
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
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.
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.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs. ...
unsigned getNumBlockIDs() const
getNumBlockIDs - Returns the total number of BlockIDs allocated (which start at 0).
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
static bool isLogicalOp(Opcode Opc)
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...
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()
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...
llvm::SmallDenseMap< WeakObjectProfileTy, WeakUseVector, 8, WeakObjectProfileTy::DenseMapInfo > WeakObjectUseMap
Used to collect all uses of weak objects in a function body.
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
SmallVector< PartialDiagnosticAt, 1 > OptionalNotes
Represents a simple identification of a weak object.
SourceLocation getLocStart() const LLVM_READONLY
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.
SwitchStmt - This represents a 'switch' stmt.
The standard open() call: int open(const char *path, int oflag, ...);.
UnreachableKind
Classifications of unreachable code.
const Expr * getUser() const
Get the expression containing the uninitialized use.
The use is always uninitialized.
TypeSourceInfo * getTypeSourceInfo() const
Base for LValueReferenceType and RValueReferenceType.
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)
const Type * getTypePtrOrNull() const
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
bool hasNoReturnElement() 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...
Expr * getTrueExpr() const
sema::FunctionScopeInfo * getCurFunction() const
CXXCatchStmt - This represents a C++ catch block.
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...
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.
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.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
bool isPointerType() const
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.
NamedDecl - This represents a decl with a name.
SourceLocation getLocStart() const LLVM_READONLY
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.