39 #include "llvm/ADT/BitVector.h" 40 #include "llvm/ADT/MapVector.h" 41 #include "llvm/ADT/SmallString.h" 42 #include "llvm/ADT/SmallVector.h" 43 #include "llvm/ADT/StringRef.h" 44 #include "llvm/Support/Casting.h" 49 using namespace clang;
61 UnreachableCodeHandler(
Sema &s) : S(s) {}
70 if (PreviousSilenceableCondVal.
isValid() &&
72 PreviousSilenceableCondVal == SilenceableCondVal)
74 PreviousSilenceableCondVal = SilenceableCondVal;
76 unsigned diag = diag::warn_unreachable;
79 diag = diag::warn_unreachable_break;
82 diag = diag::warn_unreachable_return;
85 diag = diag::warn_unreachable_loop_increment;
91 S.
Diag(L, diag) << R1 << R2;
98 S.
Diag(Open, diag::note_unreachable_silence)
119 UnreachableCodeHandler UC(S);
131 static bool HasMacroID(
const Expr *E) {
137 if (
const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
138 if (HasMacroID(SubExpr))
144 void compareAlwaysTrue(
const BinaryOperator *B,
bool isAlwaysTrue)
override {
149 S.
Diag(B->
getExprLoc(), diag::warn_tautological_overlap_comparison)
150 << DiagRange << isAlwaysTrue;
154 bool isAlwaysTrue)
override {
160 << DiagRange << isAlwaysTrue;
168 S.
Diag(B->
getExprLoc(), diag::warn_comparison_bitwise_or) << DiagRange;
173 return !Diags.
isIgnored(diag::warn_tautological_overlap_comparison, Loc) ||
174 !Diags.
isIgnored(diag::warn_comparison_bitwise_or, Loc);
188 for (
const auto &B : Block) {
202 isa<TemplateSpecializationType>(NNS->getAsType())) {
218 llvm::SmallPtrSet<CFGBlock *, 16> Visited;
221 bool foundRecursion =
false;
226 WorkList.push_back(&cfg->
getEntry());
228 while (!WorkList.empty()) {
229 CFGBlock *Block = WorkList.pop_back_val();
233 if (!Visited.insert(SuccBlock).second)
237 if (ExitID == SuccBlock->getBlockID())
242 foundRecursion =
true;
246 WorkList.push_back(SuccBlock);
250 return foundRecursion;
286 Stack.push_back(&ThrowBlock);
289 while (!Stack.empty()) {
290 CFGBlock &UnwindBlock = *Stack.back();
293 for (
auto &Succ : UnwindBlock.
succs()) {
294 if (!Succ.isReachable() || Queued[Succ->getBlockID()])
301 dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
302 QualType Caught = Catch->getCaughtType();
309 Stack.push_back(Succ);
310 Queued[Succ->getBlockID()] =
true;
324 if (!Reachable[B->getBlockID()])
330 if (
auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
340 S.
Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
342 (isa<CXXDestructorDecl>(FD) ||
346 getAs<FunctionProtoType>())
348 << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
371 if (FPT->isNothrow() || FD->
hasAttr<NoThrowAttr>())
412 for (
const auto *B : *cfg) {
413 if (!live[B->getBlockID()]) {
414 if (B->pred_begin() == B->pred_end()) {
415 const Stmt *Term = B->getTerminatorStmt();
416 if (Term && isa<CXXTryStmt>(Term))
428 bool HasLiveReturn =
false;
429 bool HasFakeEdge =
false;
430 bool HasPlainEdge =
false;
431 bool HasAbnormalEdge =
false;
439 cfg->getExit().filtered_pred_start_end(FO);
449 HasAbnormalEdge =
true;
458 for ( ; ri != re ; ++ri)
465 if (Term && isa<CXXTryStmt>(Term)) {
466 HasAbnormalEdge =
true;
476 if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
477 HasLiveReturn =
true;
480 if (isa<ObjCAtThrowStmt>(S)) {
484 if (isa<CXXThrowExpr>(S)) {
488 if (isa<MSAsmStmt>(S)) {
491 HasLiveReturn =
true;
494 if (isa<CXXTryStmt>(S)) {
495 HasAbnormalEdge =
true;
500 HasAbnormalEdge =
true;
511 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
521 struct CheckFallThroughDiagnostics {
522 unsigned diag_MaybeFallThrough_HasNoReturn;
523 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
524 unsigned diag_AlwaysFallThrough_HasNoReturn;
525 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
526 unsigned diag_NeverFallThroughOrReturn;
527 enum { Function, Block, Lambda, Coroutine } funMode;
530 static CheckFallThroughDiagnostics MakeForFunction(
const Decl *Func) {
531 CheckFallThroughDiagnostics D;
533 D.diag_MaybeFallThrough_HasNoReturn =
534 diag::warn_falloff_noreturn_function;
535 D.diag_MaybeFallThrough_ReturnsNonVoid =
536 diag::warn_maybe_falloff_nonvoid_function;
537 D.diag_AlwaysFallThrough_HasNoReturn =
538 diag::warn_falloff_noreturn_function;
539 D.diag_AlwaysFallThrough_ReturnsNonVoid =
540 diag::warn_falloff_nonvoid_function;
544 bool isVirtualMethod =
false;
545 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
546 isVirtualMethod = Method->isVirtual();
550 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
551 isTemplateInstantiation = Function->isTemplateInstantiation();
553 if (!isVirtualMethod && !isTemplateInstantiation)
554 D.diag_NeverFallThroughOrReturn =
555 diag::warn_suggest_noreturn_function;
557 D.diag_NeverFallThroughOrReturn = 0;
559 D.funMode = Function;
563 static CheckFallThroughDiagnostics MakeForCoroutine(
const Decl *Func) {
564 CheckFallThroughDiagnostics D;
566 D.diag_MaybeFallThrough_HasNoReturn = 0;
567 D.diag_MaybeFallThrough_ReturnsNonVoid =
568 diag::warn_maybe_falloff_nonvoid_coroutine;
569 D.diag_AlwaysFallThrough_HasNoReturn = 0;
570 D.diag_AlwaysFallThrough_ReturnsNonVoid =
571 diag::warn_falloff_nonvoid_coroutine;
572 D.funMode = Coroutine;
576 static CheckFallThroughDiagnostics MakeForBlock() {
577 CheckFallThroughDiagnostics D;
578 D.diag_MaybeFallThrough_HasNoReturn =
579 diag::err_noreturn_block_has_return_expr;
580 D.diag_MaybeFallThrough_ReturnsNonVoid =
581 diag::err_maybe_falloff_nonvoid_block;
582 D.diag_AlwaysFallThrough_HasNoReturn =
583 diag::err_noreturn_block_has_return_expr;
584 D.diag_AlwaysFallThrough_ReturnsNonVoid =
585 diag::err_falloff_nonvoid_block;
586 D.diag_NeverFallThroughOrReturn = 0;
591 static CheckFallThroughDiagnostics MakeForLambda() {
592 CheckFallThroughDiagnostics D;
593 D.diag_MaybeFallThrough_HasNoReturn =
594 diag::err_noreturn_lambda_has_return_expr;
595 D.diag_MaybeFallThrough_ReturnsNonVoid =
596 diag::warn_maybe_falloff_nonvoid_lambda;
597 D.diag_AlwaysFallThrough_HasNoReturn =
598 diag::err_noreturn_lambda_has_return_expr;
599 D.diag_AlwaysFallThrough_ReturnsNonVoid =
600 diag::warn_falloff_nonvoid_lambda;
601 D.diag_NeverFallThroughOrReturn = 0;
607 bool HasNoReturn)
const {
608 if (funMode == Function) {
609 return (ReturnsVoid ||
610 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function,
613 D.
isIgnored(diag::warn_noreturn_function_has_return_expr,
616 D.
isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
618 if (funMode == Coroutine) {
619 return (ReturnsVoid ||
620 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
621 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
626 return ReturnsVoid && !HasNoReturn;
638 const CheckFallThroughDiagnostics &CD,
642 bool ReturnsVoid =
false;
643 bool HasNoReturn =
false;
646 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
647 if (
const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
648 ReturnsVoid = CBody->getFallthroughHandler() !=
nullptr;
650 ReturnsVoid = FD->getReturnType()->isVoidType();
651 HasNoReturn = FD->isNoReturn();
653 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
654 ReturnsVoid = MD->getReturnType()->isVoidType();
655 HasNoReturn = MD->hasAttr<NoReturnAttr>();
657 else if (isa<BlockDecl>(D)) {
660 if (FT->getReturnType()->isVoidType())
662 if (FT->getNoReturnAttr())
670 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
691 EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
692 else if (!ReturnsVoid)
693 EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
697 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
698 else if (!ReturnsVoid)
699 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
702 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
703 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
704 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
705 }
else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
706 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
708 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
733 : Inherited(Context), FoundReference(
false), Needle(Needle) {}
735 void VisitExpr(
const Expr *E) {
740 Inherited::VisitExpr(E);
745 FoundReference =
true;
747 Inherited::VisitDeclRefExpr(E);
750 bool doesContainReference()
const {
return FoundReference; }
758 S.
Diag(VD->
getLocation(), diag::note_block_var_fixit_add_initialization)
779 S.
Diag(Loc, diag::note_var_fixit_add_initialization) << VD->
getDeclName()
787 const Stmt *Else,
bool CondVal,
811 bool IsCapturedByBlock) {
812 bool Diagnosed =
false;
845 const Stmt *Term = I->Terminator;
855 int RemoveDiagKind = -1;
856 const char *FixitStr =
857 S.
getLangOpts().CPlusPlus ? (I->Output ?
"true" :
"false")
858 : (I->Output ?
"1" :
"0");
861 switch (Term ? Term->
getStmtClass() : Stmt::DeclStmtClass) {
868 case Stmt::IfStmtClass: {
869 const IfStmt *IS = cast<IfStmt>(Term);
875 I->Output, Fixit1, Fixit2);
878 case Stmt::ConditionalOperatorClass: {
885 I->Output, Fixit1, Fixit2);
888 case Stmt::BinaryOperatorClass: {
896 if ((BO->
getOpcode() == BO_LAnd && I->Output) ||
897 (BO->
getOpcode() == BO_LOr && !I->Output))
908 case Stmt::WhileStmtClass:
911 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
915 case Stmt::ForStmtClass:
918 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
925 case Stmt::CXXForRangeStmtClass:
926 if (I->Output == 1) {
934 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
938 case Stmt::DoStmtClass:
941 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
947 case Stmt::CaseStmtClass:
950 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
952 case Stmt::DefaultStmtClass:
955 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
959 S.
Diag(Range.
getBegin(), diag::warn_sometimes_uninit_var)
960 << VD->
getDeclName() << IsCapturedByBlock << DiagKind
961 << Str << I->Output << Range;
962 S.
Diag(User->getBeginLoc(), diag::note_uninit_var_use)
963 << IsCapturedByBlock << User->getSourceRange();
964 if (RemoveDiagKind != -1)
966 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
984 bool alwaysReportSelfInit =
false) {
998 if (!alwaysReportSelfInit && DRE ==
Initializer->IgnoreParenImpCasts())
1001 ContainsReference CR(S.
Context, DRE);
1003 if (CR.doesContainReference()) {
1004 S.
Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
1015 diag::warn_uninit_byref_blockvar_captured_by_block)
1035 FallthroughMapper(
Sema &S)
1036 : FoundSwitchStatements(
false),
1040 bool foundSwitchStatements()
const {
return FoundSwitchStatements; }
1043 bool Found = FallthroughStmts.erase(Stmt);
1048 typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;
1050 const AttrStmts &getFallthroughStmts()
const {
1051 return FallthroughStmts;
1054 void fillReachableBlocks(
CFG *Cfg) {
1055 assert(ReachableBlocks.empty() &&
"ReachableBlocks already filled");
1056 std::deque<const CFGBlock *> BlockQueue;
1058 ReachableBlocks.insert(&Cfg->
getEntry());
1059 BlockQueue.push_back(&Cfg->
getEntry());
1064 for (
const auto *B : *Cfg) {
1065 const Stmt *L = B->getLabel();
1066 if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1067 BlockQueue.push_back(B);
1070 while (!BlockQueue.empty()) {
1072 BlockQueue.pop_front();
1076 if (*I && ReachableBlocks.insert(*I).second)
1077 BlockQueue.push_back(*I);
1082 bool checkFallThroughIntoBlock(
const CFGBlock &B,
int &AnnotatedCnt,
1083 bool IsTemplateInstantiation) {
1084 assert(!ReachableBlocks.empty() &&
"ReachableBlocks empty");
1086 int UnannotatedCnt = 0;
1090 while (!BlockQueue.empty()) {
1092 BlockQueue.pop_front();
1096 if (Term && isa<SwitchStmt>(Term))
1107 if (!ReachableBlocks.count(P)) {
1109 ElemEnd = P->
rend();
1110 ElemIt != ElemEnd; ++ElemIt) {
1112 if (
const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1116 if (!IsTemplateInstantiation)
1117 S.
Diag(AS->getBeginLoc(),
1118 diag::warn_fallthrough_attr_unreachable);
1119 markFallthroughVisited(AS);
1139 markFallthroughVisited(AS);
1147 std::back_inserter(BlockQueue));
1153 return !!UnannotatedCnt;
1157 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1160 if (asFallThroughAttr(S))
1161 FallthroughStmts.insert(S);
1166 FoundSwitchStatements =
true;
1172 bool TraverseDecl(
Decl *D) {
return true; }
1178 TraverseLambdaCapture(LE, &std::get<0>(
C), std::get<1>(
C));
1185 if (
const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1186 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1197 ElemIt != ElemEnd; ++ElemIt) {
1199 return CS->getStmt();
1205 if (!isa<SwitchCase>(SW->getSubStmt()))
1206 return SW->getSubStmt();
1211 bool FoundSwitchStatements;
1212 AttrStmts FallthroughStmts;
1214 llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
1221 tok::l_square, tok::l_square,
1223 tok::r_square, tok::r_square
1229 tok::r_square, tok::r_square
1234 StringRef MacroName;
1235 if (PreferClangAttr)
1237 if (MacroName.empty())
1239 if (MacroName.empty() && !PreferClangAttr)
1241 if (MacroName.empty()) {
1242 if (!PreferClangAttr)
1243 MacroName =
"[[fallthrough]]";
1245 MacroName =
"[[clang::fallthrough]]";
1247 MacroName =
"__attribute__((fallthrough))";
1254 FallthroughMapper FM(S);
1255 FM.TraverseStmt(AC.
getBody());
1257 if (!FM.foundSwitchStatements())
1260 if (PerFunction && FM.getFallthroughStmts().empty())
1268 FM.fillReachableBlocks(Cfg);
1270 for (
const CFGBlock *B : llvm::reverse(*Cfg)) {
1273 if (!Label || !isa<SwitchCase>(Label))
1278 bool IsTemplateInstantiation =
false;
1280 IsTemplateInstantiation = Function->isTemplateInstantiation();
1281 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1282 IsTemplateInstantiation))
1286 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1287 : diag::warn_unannotated_fallthrough);
1289 if (!AnnotatedCnt) {
1294 const Stmt *Term = B->getTerminatorStmt();
1296 while (B->empty() && !Term && B->succ_size() == 1) {
1297 B = *B->succ_begin();
1298 Term = B->getTerminatorStmt();
1300 if (!(B->empty() && Term && isa<BreakStmt>(Term))) {
1304 TextToInsert +=
"; ";
1305 S.
Diag(L, diag::note_insert_fallthrough_fixit)
1306 << AnnotationSpelling
1309 S.
Diag(L, diag::note_insert_break_fixit)
1314 for (
const auto *F : FM.getFallthroughStmts())
1315 S.
Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);
1324 case Stmt::ForStmtClass:
1325 case Stmt::WhileStmtClass:
1326 case Stmt::CXXForRangeStmtClass:
1327 case Stmt::ObjCForCollectionStmtClass:
1329 case Stmt::DoStmtClass: {
1331 if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))
1333 return Result.
Val.
getInt().getBoolValue();
1350 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1359 for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
1361 const WeakUseVector &Uses = I->second;
1364 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1365 for ( ; UI != UE; ++UI) {
1378 if (UI == Uses.begin()) {
1379 WeakUseVector::const_iterator UI2 = UI;
1380 for (++UI2; UI2 != UE; ++UI2)
1381 if (UI2->isUnsafe())
1385 if (!
isInLoop(Ctx, PM, UI->getUseExpr()))
1388 const WeakObjectProfileTy &Profile = I->first;
1389 if (!Profile.isExactProfile())
1394 Base = Profile.getProperty();
1395 assert(Base &&
"A profile always has a base or property.");
1397 if (
const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1398 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1403 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
1406 if (UsesByStmt.empty())
1411 llvm::sort(UsesByStmt,
1412 [&SM](
const StmtUsesPair &LHS,
const StmtUsesPair &RHS) {
1414 RHS.first->getBeginLoc());
1429 if (isa<sema::BlockScopeInfo>(CurFn))
1430 FunctionKind = Block;
1431 else if (isa<sema::LambdaScopeInfo>(CurFn))
1432 FunctionKind = Lambda;
1433 else if (isa<ObjCMethodDecl>(D))
1434 FunctionKind = Method;
1436 FunctionKind = Function;
1439 for (
const auto &
P : UsesByStmt) {
1440 const Stmt *FirstRead =
P.first;
1441 const WeakObjectProfileTy &Key =
P.second->first;
1442 const WeakUseVector &Uses =
P.second->second;
1450 if (Key.isExactProfile())
1451 DiagKind = diag::warn_arc_repeated_use_of_weak;
1453 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1465 const NamedDecl *KeyProp = Key.getProperty();
1466 if (isa<VarDecl>(KeyProp))
1467 ObjectKind = Variable;
1468 else if (isa<ObjCPropertyDecl>(KeyProp))
1470 else if (isa<ObjCMethodDecl>(KeyProp))
1471 ObjectKind = ImplicitProperty;
1472 else if (isa<ObjCIvarDecl>(KeyProp))
1475 llvm_unreachable(
"Unexpected weak object kind!");
1480 if (Prop->hasAttr<IBOutletAttr>())
1485 <<
int(ObjectKind) << KeyProp << int(FunctionKind)
1489 for (
const auto &Use : Uses) {
1490 if (Use.getUseExpr() == FirstRead)
1492 S.
Diag(Use.getUseExpr()->getBeginLoc(),
1493 diag::note_arc_weak_also_accessed_here)
1494 << Use.getUseExpr()->getSourceRange();
1503 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1507 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1511 UninitValsDiagReporter(
Sema &S) : S(S) {}
1514 MappedType &getUses(
const VarDecl *vd) {
1515 MappedType &
V = uses[vd];
1516 if (!V.getPointer())
1517 V.setPointer(
new UsesVec());
1521 void handleUseOfUninitVariable(
const VarDecl *vd,
1523 getUses(vd).getPointer()->push_back(use);
1526 void handleSelfInit(
const VarDecl *vd)
override {
1527 getUses(vd).setInt(
true);
1531 for (
const auto &
P : uses) {
1533 const MappedType &
V =
P.second;
1535 UsesVec *vec = V.getPointer();
1536 bool hasSelfInit = V.getInt();
1541 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1550 llvm::sort(vec->begin(), vec->end(),
1553 if (a.
getKind() != b.getKind())
1554 return a.
getKind() > b.getKind();
1558 for (
const auto &U : *vec) {
1577 static bool hasAlwaysUninitializedUse(
const UsesVec* vec) {
1578 return std::any_of(vec->begin(), vec->end(), [](
const UninitUse &U) {
1590 typedef std::pair<PartialDiagnosticAt, OptionalNotes>
DelayedDiag;
1591 typedef std::list<DelayedDiag>
DiagList;
1593 struct SortDiagBySourceLocation {
1597 bool operator()(
const DelayedDiag &left,
const DelayedDiag &right) {
1610 namespace threadSafety {
1621 if (Verbose && CurrentFunction) {
1623 S.
PDiag(diag::note_thread_warning_in_fun)
1624 << CurrentFunction);
1632 if (Verbose && CurrentFunction) {
1634 S.
PDiag(diag::note_thread_warning_in_fun)
1635 << CurrentFunction);
1636 ONS.push_back(std::move(FNote));
1644 ONS.push_back(Note1);
1645 ONS.push_back(Note2);
1646 if (Verbose && CurrentFunction) {
1648 S.
PDiag(diag::note_thread_warning_in_fun)
1649 << CurrentFunction);
1650 ONS.push_back(std::move(FNote));
1658 LocLocked, S.
PDiag(diag::note_locked_here) <<
Kind))
1664 : S(S), FunLocation(FL), FunEndLocation(FEL),
1665 CurrentFunction(
nullptr), Verbose(
false) {}
1667 void setVerbose(
bool b) { Verbose = b; }
1675 for (
const auto &
Diag : Warnings) {
1677 for (
const auto &Note :
Diag.second)
1678 S.
Diag(Note.first, Note.second);
1682 void handleInvalidLockExp(StringRef Kind,
SourceLocation Loc)
override {
1685 Warnings.emplace_back(std::move(
Warning), getNotes());
1688 void handleUnmatchedUnlock(StringRef Kind, Name LockName,
1693 << Kind << LockName);
1694 Warnings.emplace_back(std::move(
Warning), getNotes());
1697 void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
1702 LocUnlock = FunLocation;
1704 LocUnlock, S.
PDiag(diag::warn_unlock_kind_mismatch)
1705 << Kind << LockName << Received <<
Expected);
1706 Warnings.emplace_back(std::move(
Warning),
1707 makeLockedHereNote(LocLocked, Kind));
1710 void handleDoubleLock(StringRef Kind, Name LockName,
SourceLocation LocLocked,
1713 LocDoubleLock = FunLocation;
1715 << Kind << LockName);
1716 Warnings.emplace_back(std::move(
Warning),
1717 makeLockedHereNote(LocLocked, Kind));
1720 void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
1724 unsigned DiagID = 0;
1727 DiagID = diag::warn_lock_some_predecessors;
1730 DiagID = diag::warn_expecting_lock_held_on_loop;
1733 DiagID = diag::warn_no_unlock;
1736 DiagID = diag::warn_expecting_locked;
1740 LocEndOfScope = FunEndLocation;
1744 Warnings.emplace_back(std::move(
Warning),
1745 makeLockedHereNote(LocLocked, Kind));
1748 void handleExclusiveAndShared(StringRef Kind, Name LockName,
1752 S.
PDiag(diag::warn_lock_exclusive_and_shared)
1753 << Kind << LockName);
1755 << Kind << LockName);
1756 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1759 void handleNoMutexHeld(StringRef Kind,
const NamedDecl *D,
1763 "Only works for variables");
1765 diag::warn_variable_requires_any_lock:
1766 diag::warn_var_deref_requires_any_lock;
1769 Warnings.emplace_back(std::move(
Warning), getNotes());
1772 void handleMutexNotHeld(StringRef Kind,
const NamedDecl *D,
1775 Name *PossibleMatch)
override {
1776 unsigned DiagID = 0;
1777 if (PossibleMatch) {
1780 DiagID = diag::warn_variable_requires_lock_precise;
1783 DiagID = diag::warn_var_deref_requires_lock_precise;
1786 DiagID = diag::warn_fun_requires_lock_precise;
1789 DiagID = diag::warn_guarded_pass_by_reference;
1792 DiagID = diag::warn_pt_guarded_pass_by_reference;
1802 S.
PDiag(diag::note_guarded_by_declared_here)
1804 Warnings.emplace_back(std::move(
Warning), getNotes(Note, VNote));
1806 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1810 DiagID = diag::warn_variable_requires_lock;
1813 DiagID = diag::warn_var_deref_requires_lock;
1816 DiagID = diag::warn_fun_requires_lock;
1819 DiagID = diag::warn_guarded_pass_by_reference;
1822 DiagID = diag::warn_pt_guarded_pass_by_reference;
1830 S.
PDiag(diag::note_guarded_by_declared_here));
1831 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1833 Warnings.emplace_back(std::move(
Warning), getNotes());
1837 void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
1840 S.
PDiag(diag::warn_acquire_requires_negative_cap)
1841 << Kind << LockName << Neg);
1842 Warnings.emplace_back(std::move(
Warning), getNotes());
1845 void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
1848 << Kind << FunName << LockName);
1849 Warnings.emplace_back(std::move(
Warning), getNotes());
1852 void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
1855 S.
PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
1856 Warnings.emplace_back(std::move(
Warning), getNotes());
1859 void handleBeforeAfterCycle(Name L1Name,
SourceLocation Loc)
override {
1861 S.
PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
1862 Warnings.emplace_back(std::move(
Warning), getNotes());
1866 CurrentFunction = FD;
1870 CurrentFunction =
nullptr;
1882 namespace consumed {
1884 class ConsumedWarningsHandler :
public ConsumedWarningsHandlerBase {
1891 ConsumedWarningsHandler(
Sema &S) : S(S) {}
1895 for (
const auto &
Diag : Warnings) {
1897 for (
const auto &
Note :
Diag.second)
1903 StringRef VariableName)
override {
1911 StringRef VariableName,
1912 StringRef ExpectedState,
1913 StringRef ObservedState)
override {
1916 diag::warn_param_return_typestate_mismatch) << VariableName <<
1917 ExpectedState << ObservedState);
1922 void warnParamTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1923 StringRef ObservedState)
override {
1926 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
1932 StringRef TypeName)
override {
1934 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
1939 void warnReturnTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1940 StringRef ObservedState)
override {
1943 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
1948 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef
State,
1952 diag::warn_use_of_temp_in_invalid_state) << MethodName <<
State);
1957 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
1961 MethodName << VariableName <<
State);
1976 enableCheckFallThrough = 1;
1977 enableCheckUnreachable = 0;
1978 enableThreadSafetyAnalysis = 0;
1979 enableConsumedAnalysis = 0;
1988 NumFunctionsAnalyzed(0),
1989 NumFunctionsWithBadCFGs(0),
1991 MaxCFGBlocksPerFunction(0),
1992 NumUninitAnalysisFunctions(0),
1993 NumUninitAnalysisVariables(0),
1994 MaxUninitAnalysisVariablesPerFunction(0),
1995 NumUninitAnalysisBlockVisits(0),
1996 MaxUninitAnalysisBlockVisitsPerFunction(0) {
1998 using namespace diag;
2001 DefaultPolicy.enableCheckUnreachable =
2004 isEnabled(D, warn_unreachable_return) ||
2005 isEnabled(D, warn_unreachable_loop_increment);
2007 DefaultPolicy.enableThreadSafetyAnalysis =
2010 DefaultPolicy.enableConsumedAnalysis =
2011 isEnabled(D, warn_use_in_invalid_state);
2016 S.
Diag(D.Loc, D.PD);
2039 if (cast<DeclContext>(D)->isDependentContext())
2070 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
2071 P.enableConsumedAnalysis) {
2089 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->
getBeginLoc())) {
2096 bool analyzed =
false;
2100 for (
const Stmt *S : D.Stmts)
2107 bool AllReachable =
true;
2108 for (
const Stmt *S : D.Stmts) {
2118 AllReachable =
false;
2127 S.Diag(D.Loc, D.PD);
2136 if (P.enableCheckFallThrough) {
2137 const CheckFallThroughDiagnostics &CD =
2139 ? CheckFallThroughDiagnostics::MakeForBlock()
2140 : (isa<CXXMethodDecl>(D) &&
2141 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2142 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2143 ? CheckFallThroughDiagnostics::MakeForLambda()
2145 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2146 : CheckFallThroughDiagnostics::MakeForFunction(D)));
2151 if (P.enableCheckUnreachable) {
2157 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
2158 isTemplateInstantiation = Function->isTemplateInstantiation();
2159 if (!isTemplateInstantiation)
2164 if (P.enableThreadSafetyAnalysis) {
2167 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
2169 Reporter.setIssueBetaWarnings(
true);
2171 Reporter.setVerbose(
true);
2175 Reporter.emitDiagnostics();
2179 if (P.enableConsumedAnalysis) {
2180 consumed::ConsumedWarningsHandler WarningHandler(S);
2189 UninitValsDiagReporter reporter(S);
2196 ++NumUninitAnalysisFunctions;
2199 MaxUninitAnalysisVariablesPerFunction =
2200 std::max(MaxUninitAnalysisVariablesPerFunction,
2202 MaxUninitAnalysisBlockVisitsPerFunction =
2203 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
2209 bool FallThroughDiagFull =
2211 bool FallThroughDiagPerFunction = !Diags.
isIgnored(
2212 diag::warn_unannotated_fallthrough_per_function, D->
getBeginLoc());
2213 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
2224 if (!Diags.
isIgnored(diag::warn_infinite_recursive_function,
2226 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2233 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2239 if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->
getBeginLoc())) {
2245 ++NumFunctionsAnalyzed;
2250 MaxCFGBlocksPerFunction =
std::max(MaxCFGBlocksPerFunction,
2251 cfg->getNumBlockIDs());
2253 ++NumFunctionsWithBadCFGs;
2259 llvm::errs() <<
"\n*** Analysis Based Warnings Stats:\n";
2261 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
2262 unsigned AvgCFGBlocksPerFunction =
2263 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
2264 llvm::errs() << NumFunctionsAnalyzed <<
" functions analyzed (" 2265 << NumFunctionsWithBadCFGs <<
" w/o CFGs).\n" 2266 <<
" " << NumCFGBlocks <<
" CFG blocks built.\n" 2267 <<
" " << AvgCFGBlocksPerFunction
2268 <<
" average CFG blocks per function.\n" 2269 <<
" " << MaxCFGBlocksPerFunction
2270 <<
" max CFG blocks per function.\n";
2272 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
2273 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
2274 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
2275 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
2276 llvm::errs() << NumUninitAnalysisFunctions
2277 <<
" functions analyzed for uninitialiazed variables\n" 2278 <<
" " << NumUninitAnalysisVariables <<
" variables analyzed.\n" 2279 <<
" " << AvgUninitVariablesPerFunction
2280 <<
" average variables per function.\n" 2281 <<
" " << MaxUninitAnalysisVariablesPerFunction
2282 <<
" max variables per function.\n" 2283 <<
" " << NumUninitAnalysisBlockVisits <<
" block visits.\n" 2284 <<
" " << AvgUninitBlockVisitsPerFunction
2285 <<
" average block visits per function.\n" 2286 <<
" " << MaxUninitAnalysisBlockVisitsPerFunction
2287 <<
" max block visits per function.\n";
static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool IsCapturedByBlock)
DiagUninitUse – Helper function to produce a diagnostic for an uninitialized use of a variable...
Represents a function declaration or definition.
Passing a guarded variable by reference.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
A (possibly-)qualified type.
bool isBlockPointerType() const
SourceLocation getExprLoc() const
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
bool HasFallthroughStmt
Whether there is a fallthrough statement in this function.
const Expr * getSubExpr() const
const Stmt * getStmt() const
Stmt * getBody() const
Get the body of the Declaration.
succ_iterator succ_begin()
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Stmt - This represents one statement.
FunctionType - C99 6.7.5.3 - Function Declarators.
IfStmt - This represents an if/then/else.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
llvm::Expected< T > Expected
Defines the SourceManager interface.
static void diagnoseRepeatedUseOfWeak(Sema &S, const sema::FunctionScopeInfo *CurFn, const Decl *D, const ParentMap &PM)
unsigned getBlockID() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Decl - This represents one declaration (or definition), e.g.
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
SourceLocation getBeginLoc() const LLVM_READONLY
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
Represents an attribute applied to a statement.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
bool getAddEHEdges() const
getAddEHEdges - Return true iff we are adding exceptional edges from callExprs.
const WeakObjectUseMap & getWeakObjectUses() const
The use is uninitialized whenever a certain branch is taken.
Stmt * getParent(Stmt *) const
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
AnalysisBasedWarnings(Sema &s)
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
SourceLocation getEndLoc() const LLVM_READONLY
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
bool getSuppressSystemWarnings() const
LockKind getLockKindFromAccessKind(AccessKind AK)
Helper function that returns a LockKind required for the given level of access.
unsigned IgnoreDefaultsWithCoveredEnums
static std::pair< const Stmt *, const CFGBlock * > getLastStmt(const ExplodedNode *Node)
ProtectedOperationKind
This enum distinguishes between different kinds of operations that may need to be protected by locks...
Retains information about a function, method, or block that is currently being parsed.
Represents a variable declaration or definition.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
const T * getAs() const
Member-template getAs<specific type>'.
ObjCMethodDecl - Represents an instance or class method declaration.
The use might be uninitialized.
Defines the Objective-C statement AST node classes.
A C++ throw-expression (C++ [except.throw]).
Defines the clang::Expr interface and subclasses for C++ expressions.
branch_iterator branch_end() const
LabelStmt - Represents a label, which has a substatement.
LockKind
This enum distinguishes between different kinds of lock actions.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Kind getKind() const
Get the kind of uninitialized use.
Expr * getFalseExpr() const
SourceLocation getBegin() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceLocation getBeginLoc() const LLVM_READONLY
branch_iterator branch_begin() const
Branches which inevitably result in the variable being used uninitialized.
AnalysisDeclContext contains the context data for the function or method under analysis.
threadSafety::BeforeSet * ThreadSafetyDeclCache
static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, bool PerFunction)
__DEVICE__ int max(int __a, int __b)
SourceLocation getBeginLoc() const LLVM_READONLY
const LangOptions & getLangOpts() const
AdjacentBlocks::const_iterator const_succ_iterator
TextDiagnosticBuffer::DiagList DiagList
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
APValue Val
Val - This is the value the expression can be folded to.
bool AddCXXDefaultInitExprInCtors
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
Concrete class used by the front-end to report problems and issues.
A builtin binary operation expression such as "x + y" or "x <= y".
static StringRef getFallthroughAttrSpelling(Preprocessor &PP, SourceLocation Loc)
SourceLocation getThrowLoc() const
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC)
CheckUnreachable - Check for unreachable code.
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC)...
__DEVICE__ void * memset(void *__a, int __b, size_t __c)
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
const LangOptions & getLangOpts() const
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification, if any.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD)
DiagnosticsEngine & getDiagnostics() const
Passing a pt-guarded variable by reference.
ConditionalOperator - The ?: ternary operator.
Sema - This implements semantic analysis and AST building for C.
Represents a prototype with parameter type info, e.g.
static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool alwaysReportSelfInit=false)
DiagnoseUninitializedUse – Helper function for diagnosing uses of an uninitialized variable...
Handler class for thread safety warnings.
static StringRef getOpcodeStr(Opcode Op)
getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to...
Represents a single basic block in a source-level CFG.
static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, const Stmt *S)
Dereferencing a variable (e.g. p in *p = 5;)
This represents one expression.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool hasUncompilableErrorOccurred() const
Errors that actually prevent compilation, not those that are upgraded from a warning by -Werror...
const T * castAs() const
Member-template castAs<specific type>.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Defines the clang::Preprocessor interface.
bool isCPUDispatchMultiVersion() const
True if this function is a multiversioned dispatch function as a part of the cpu_specific/cpu_dispatc...
Stores token information for comparing actual tokens with predefined values.
void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, AnalysisDeclContext &ac, UninitVariablesHandler &handler, UninitVariablesAnalysisStats &stats)
void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP, Callback &CB)
unsigned ScanReachableFromBlock(const CFGBlock *Start, llvm::BitVector &Reachable)
ScanReachableFromBlock - Mark all blocks reachable from Start.
std::pair< PartialDiagnosticAt, OptionalNotes > DelayedDiag
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
bool handlerCanCatch(QualType HandlerType, QualType ExceptionType)
AccessKind
This enum distinguishes between different ways to access (read or write) a variable.
SourceLocation getEnd() const
Making a function call (e.g. fool())
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Preprocessor & getPreprocessor() const
A use of a variable, which might be uninitialized.
The result type of a method or function.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
A type, stored as a Type*.
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
reverse_iterator rbegin()
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
SourceLocation getEndLoc() const LLVM_READONLY
static CharSourceRange getCharRange(SourceRange R)
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
QualType getCanonicalType() const
Reading or writing a variable (e.g. x in x = 5;)
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
ASTContext & getASTContext() const
Encodes a location in the source.
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
static void visitReachableThrows(CFG *BodyCFG, llvm::function_ref< void(const CXXThrowExpr *, CFGBlock &)> Visit)
SourceLocation getOperatorLoc() const
SourceLocation getBeginLoc() const LLVM_READONLY
static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc, const FunctionDecl *FD)
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
bool isReachable(const CFGBlock *Src, const CFGBlock *Dst)
Returns true if the block 'Dst' can be reached from block 'Src'.
Represents a call to a member function that may be written either with member call syntax (e...
llvm::iterator_range< capture_init_iterator > capture_inits()
Retrieve the initialization expressions for this lambda's captures.
bool PruneTriviallyFalseEdges
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs. ...
Represents a static or instance method of a struct/union/class.
bool isCFGBuilt() const
Returns true if we have built a CFG for this analysis context.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
bool CollectStats
Flag indicating whether or not to collect detailed statistics.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
const Decl * getDecl() const
static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD, AnalysisDeclContext &AC)
Represents one property declaration in an Objective-C interface.
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
static bool isLogicalOp(Opcode Opc)
static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR, AnalysisManager &AM, const ObjCAutoreleaseWriteChecker *Checker)
BuildOptions & setAllAlwaysAdd()
The use is uninitialized the first time it is reached after we reach the variable's declaration...
std::string getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const
Get a string to suggest for zero-initialization of a type.
static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag)
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
bool getIgnoreAllWarnings() const
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, QualType BlockType, const CheckFallThroughDiagnostics &CD, AnalysisDeclContext &AC, sema::FunctionScopeInfo *FSI)
CheckFallThroughForBody - Check that we don't fall off the end of a function that should return a val...
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
pred_iterator pred_begin()
SmallVectorImpl< Branch >::const_iterator branch_iterator
Dataflow Directional Tag Classes.
CFG::BuildOptions & getCFGBuildOptions()
Return the build options used to construct the CFG.
bool isValid() const
Return true if this is a valid SourceLocation object.
EvalResult is a struct with detailed info about an evaluated expression.
void runThreadSafetyAnalysis(AnalysisDeclContext &AC, ThreadSafetyHandler &Handler, BeforeSet **Bset)
Check a function's CFG for thread-safety violations.
static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, const Stmt *Else, bool CondVal, FixItHint &Fixit1, FixItHint &Fixit2)
Create a fixit to remove an if-like statement, on the assumption that its condition is CondVal...
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
const Expr * getInit() const
static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg)
StmtClass getStmtClass() const
Represents a simple identification of a weak object.
Stmt * getTerminatorStmt()
A class that handles the analysis of uniqueness violations.
bool hasObjCLifetime() const
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
static bool isNoexcept(const FunctionDecl *FD)
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
SwitchStmt - This represents a 'switch' stmt.
The standard open() call: int open(const char *path, int oflag, ...);.
UnreachableKind
Classifications of unreachable code.
const Expr * getUser() const
Get the expression containing the uninitialized use.
The use is always uninitialized.
TypeSourceInfo * getTypeSourceInfo() const
static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock, CFG *Body)
Determine whether an exception thrown by E, unwinding from ThrowBlock, can reach ExitBlock.
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, const Stmt *Body, AnalysisDeclContext &AC)
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope)
bool hasNoReturnElement() const
SmallVector< PartialDiagnosticAt, 1 > OptionalNotes
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Defines the clang::SourceLocation class and associated facilities.
SmallVector< PossiblyUnreachableDiag, 4 > PossiblyUnreachableDiags
A list of PartialDiagnostics created but delayed within the current function scope.
CFGCallback defines methods that should be called when a logical operator error is found when buildin...
Expr * getTrueExpr() const
bool LE(InterpState &S, CodePtr OpPC)
void run(AnalysisDeclContext &AC)
Check a function's CFG for consumed violations.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Represents a top-level expression in a basic block.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string...
capture_range captures() const
Retrieve this lambda's captures.
SourceManager & getSourceManager() const
static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC)
CheckFallThrough - Check that we don't fall off the end of a Statement that should return a value...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
The use is uninitialized the first time it is reached after the function is called.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
void registerForcedBlockExpression(const Stmt *stmt)
SourceLocation getBeginLoc() const LLVM_READONLY
llvm::SmallDenseMap< WeakObjectProfileTy, WeakUseVector, 8, WeakObjectProfileTy::DenseMapInfo > WeakObjectUseMap
Used to collect all uses of weak objects in a function body.
A reference to a declared variable, function, enum, etc.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
SourceManager & SourceMgr
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
unsigned NumVariablesAnalyzed
ParentMap & getParentMap()
A trivial tuple used to represent a source range.
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
This represents a decl that may have a name.
void IssueWarnings(Policy P, FunctionScopeInfo *fscope, const Decl *D, QualType BlockType)
SourceLocation getBegin() const
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.