40 #include "llvm/ADT/BitVector.h" 41 #include "llvm/ADT/MapVector.h" 42 #include "llvm/ADT/SmallString.h" 43 #include "llvm/ADT/SmallVector.h" 44 #include "llvm/ADT/StringRef.h" 45 #include "llvm/Support/Casting.h" 50 using namespace clang;
62 UnreachableCodeHandler(
Sema &s) : S(s) {}
71 if (PreviousSilenceableCondVal.
isValid() &&
73 PreviousSilenceableCondVal == SilenceableCondVal)
75 PreviousSilenceableCondVal = SilenceableCondVal;
77 unsigned diag = diag::warn_unreachable;
80 diag = diag::warn_unreachable_break;
83 diag = diag::warn_unreachable_return;
86 diag = diag::warn_unreachable_loop_increment;
92 S.
Diag(L, diag) << R1 << R2;
99 S.
Diag(Open, diag::note_unreachable_silence)
120 UnreachableCodeHandler UC(S);
132 static bool HasMacroID(
const Expr *E) {
138 if (
const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
139 if (HasMacroID(SubExpr))
145 void compareAlwaysTrue(
const BinaryOperator *B,
bool isAlwaysTrue)
override {
150 S.
Diag(B->
getExprLoc(), diag::warn_tautological_overlap_comparison)
151 << DiagRange << isAlwaysTrue;
155 bool isAlwaysTrue)
override {
161 << DiagRange << isAlwaysTrue;
175 for (
const auto &B : Block) {
189 isa<TemplateSpecializationType>(NNS->getAsType())) {
205 llvm::SmallPtrSet<CFGBlock *, 16> Visited;
208 bool foundRecursion =
false;
213 WorkList.push_back(&cfg->
getEntry());
215 while (!WorkList.empty()) {
216 CFGBlock *Block = WorkList.pop_back_val();
220 if (!Visited.insert(SuccBlock).second)
224 if (ExitID == SuccBlock->getBlockID())
229 foundRecursion =
true;
233 WorkList.push_back(SuccBlock);
237 return foundRecursion;
269 Stack.push_back(&ThrowBlock);
272 while (!Stack.empty()) {
273 CFGBlock &UnwindBlock = *Stack.back();
276 for (
auto &Succ : UnwindBlock.
succs()) {
277 if (!Succ.isReachable() || Queued[Succ->getBlockID()])
284 dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
285 QualType Caught = Catch->getCaughtType();
292 Stack.push_back(Succ);
293 Queued[Succ->getBlockID()] =
true;
307 if (!Reachable[B->getBlockID()])
313 if (
auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
323 S.
Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD;
325 (isa<CXXDestructorDecl>(FD) ||
329 getAs<FunctionProtoType>())
331 << !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
354 if (FPT->isNothrow() || FD->
hasAttr<NoThrowAttr>())
395 for (
const auto *B : *cfg) {
396 if (!live[B->getBlockID()]) {
397 if (B->pred_begin() == B->pred_end()) {
398 if (B->getTerminator() && isa<CXXTryStmt>(B->getTerminator()))
410 bool HasLiveReturn =
false;
411 bool HasFakeEdge =
false;
412 bool HasPlainEdge =
false;
413 bool HasAbnormalEdge =
false;
421 cfg->getExit().filtered_pred_start_end(FO);
431 HasAbnormalEdge =
true;
440 for ( ; ri != re ; ++ri)
447 HasAbnormalEdge =
true;
457 if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
458 HasLiveReturn =
true;
461 if (isa<ObjCAtThrowStmt>(S)) {
465 if (isa<CXXThrowExpr>(S)) {
469 if (isa<MSAsmStmt>(S)) {
472 HasLiveReturn =
true;
475 if (isa<CXXTryStmt>(S)) {
476 HasAbnormalEdge =
true;
481 HasAbnormalEdge =
true;
492 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
502 struct CheckFallThroughDiagnostics {
503 unsigned diag_MaybeFallThrough_HasNoReturn;
504 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
505 unsigned diag_AlwaysFallThrough_HasNoReturn;
506 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
507 unsigned diag_NeverFallThroughOrReturn;
508 enum { Function, Block, Lambda, Coroutine } funMode;
511 static CheckFallThroughDiagnostics MakeForFunction(
const Decl *Func) {
512 CheckFallThroughDiagnostics D;
514 D.diag_MaybeFallThrough_HasNoReturn =
515 diag::warn_falloff_noreturn_function;
516 D.diag_MaybeFallThrough_ReturnsNonVoid =
517 diag::warn_maybe_falloff_nonvoid_function;
518 D.diag_AlwaysFallThrough_HasNoReturn =
519 diag::warn_falloff_noreturn_function;
520 D.diag_AlwaysFallThrough_ReturnsNonVoid =
521 diag::warn_falloff_nonvoid_function;
525 bool isVirtualMethod =
false;
526 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
527 isVirtualMethod = Method->isVirtual();
531 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
532 isTemplateInstantiation = Function->isTemplateInstantiation();
534 if (!isVirtualMethod && !isTemplateInstantiation)
535 D.diag_NeverFallThroughOrReturn =
536 diag::warn_suggest_noreturn_function;
538 D.diag_NeverFallThroughOrReturn = 0;
540 D.funMode = Function;
544 static CheckFallThroughDiagnostics MakeForCoroutine(
const Decl *Func) {
545 CheckFallThroughDiagnostics D;
547 D.diag_MaybeFallThrough_HasNoReturn = 0;
548 D.diag_MaybeFallThrough_ReturnsNonVoid =
549 diag::warn_maybe_falloff_nonvoid_coroutine;
550 D.diag_AlwaysFallThrough_HasNoReturn = 0;
551 D.diag_AlwaysFallThrough_ReturnsNonVoid =
552 diag::warn_falloff_nonvoid_coroutine;
553 D.funMode = Coroutine;
557 static CheckFallThroughDiagnostics MakeForBlock() {
558 CheckFallThroughDiagnostics D;
559 D.diag_MaybeFallThrough_HasNoReturn =
560 diag::err_noreturn_block_has_return_expr;
561 D.diag_MaybeFallThrough_ReturnsNonVoid =
562 diag::err_maybe_falloff_nonvoid_block;
563 D.diag_AlwaysFallThrough_HasNoReturn =
564 diag::err_noreturn_block_has_return_expr;
565 D.diag_AlwaysFallThrough_ReturnsNonVoid =
566 diag::err_falloff_nonvoid_block;
567 D.diag_NeverFallThroughOrReturn = 0;
572 static CheckFallThroughDiagnostics MakeForLambda() {
573 CheckFallThroughDiagnostics D;
574 D.diag_MaybeFallThrough_HasNoReturn =
575 diag::err_noreturn_lambda_has_return_expr;
576 D.diag_MaybeFallThrough_ReturnsNonVoid =
577 diag::warn_maybe_falloff_nonvoid_lambda;
578 D.diag_AlwaysFallThrough_HasNoReturn =
579 diag::err_noreturn_lambda_has_return_expr;
580 D.diag_AlwaysFallThrough_ReturnsNonVoid =
581 diag::warn_falloff_nonvoid_lambda;
582 D.diag_NeverFallThroughOrReturn = 0;
588 bool HasNoReturn)
const {
589 if (funMode == Function) {
590 return (ReturnsVoid ||
591 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function,
594 D.
isIgnored(diag::warn_noreturn_function_has_return_expr,
597 D.
isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
599 if (funMode == Coroutine) {
600 return (ReturnsVoid ||
601 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
602 D.
isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
607 return ReturnsVoid && !HasNoReturn;
619 const CheckFallThroughDiagnostics &CD,
623 bool ReturnsVoid =
false;
624 bool HasNoReturn =
false;
627 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
628 if (
const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
629 ReturnsVoid = CBody->getFallthroughHandler() !=
nullptr;
631 ReturnsVoid = FD->getReturnType()->isVoidType();
632 HasNoReturn = FD->isNoReturn();
634 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
635 ReturnsVoid = MD->getReturnType()->isVoidType();
636 HasNoReturn = MD->hasAttr<NoReturnAttr>();
638 else if (isa<BlockDecl>(D)) {
642 if (FT->getReturnType()->isVoidType())
644 if (FT->getNoReturnAttr())
652 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
673 EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
674 else if (!ReturnsVoid)
675 EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
679 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
680 else if (!ReturnsVoid)
681 EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
684 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
685 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
686 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
687 }
else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
688 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
690 S.
Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
715 : Inherited(Context), FoundReference(
false), Needle(Needle) {}
717 void VisitExpr(
const Expr *E) {
722 Inherited::VisitExpr(E);
727 FoundReference =
true;
729 Inherited::VisitDeclRefExpr(E);
732 bool doesContainReference()
const {
return FoundReference; }
740 S.
Diag(VD->
getLocation(), diag::note_block_var_fixit_add_initialization)
761 S.
Diag(Loc, diag::note_var_fixit_add_initialization) << VD->
getDeclName()
769 const Stmt *Else,
bool CondVal,
793 bool IsCapturedByBlock) {
794 bool Diagnosed =
false;
827 const Stmt *Term = I->Terminator;
837 int RemoveDiagKind = -1;
838 const char *FixitStr =
839 S.
getLangOpts().CPlusPlus ? (I->Output ?
"true" :
"false")
840 : (I->Output ?
"1" :
"0");
843 switch (Term ? Term->
getStmtClass() : Stmt::DeclStmtClass) {
850 case Stmt::IfStmtClass: {
851 const IfStmt *IS = cast<IfStmt>(Term);
857 I->Output, Fixit1, Fixit2);
860 case Stmt::ConditionalOperatorClass: {
867 I->Output, Fixit1, Fixit2);
870 case Stmt::BinaryOperatorClass: {
878 if ((BO->
getOpcode() == BO_LAnd && I->Output) ||
879 (BO->
getOpcode() == BO_LOr && !I->Output))
890 case Stmt::WhileStmtClass:
893 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
897 case Stmt::ForStmtClass:
900 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
907 case Stmt::CXXForRangeStmtClass:
908 if (I->Output == 1) {
916 Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
920 case Stmt::DoStmtClass:
923 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
929 case Stmt::CaseStmtClass:
932 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
934 case Stmt::DefaultStmtClass:
937 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
941 S.
Diag(Range.
getBegin(), diag::warn_sometimes_uninit_var)
942 << VD->
getDeclName() << IsCapturedByBlock << DiagKind
943 << Str << I->Output << Range;
944 S.
Diag(User->getBeginLoc(), diag::note_uninit_var_use)
945 << IsCapturedByBlock << User->getSourceRange();
946 if (RemoveDiagKind != -1)
948 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
966 bool alwaysReportSelfInit =
false) {
980 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
983 ContainsReference CR(S.
Context, DRE);
984 CR.Visit(Initializer);
985 if (CR.doesContainReference()) {
986 S.
Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
997 diag::warn_uninit_byref_blockvar_captured_by_block)
1016 FallthroughMapper(
Sema &S)
1017 : FoundSwitchStatements(
false),
1021 bool foundSwitchStatements()
const {
return FoundSwitchStatements; }
1024 bool Found = FallthroughStmts.erase(Stmt);
1029 typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;
1031 const AttrStmts &getFallthroughStmts()
const {
1032 return FallthroughStmts;
1035 void fillReachableBlocks(
CFG *Cfg) {
1036 assert(ReachableBlocks.empty() &&
"ReachableBlocks already filled");
1037 std::deque<const CFGBlock *> BlockQueue;
1039 ReachableBlocks.insert(&Cfg->
getEntry());
1040 BlockQueue.push_back(&Cfg->
getEntry());
1045 for (
const auto *B : *Cfg) {
1046 const Stmt *L = B->getLabel();
1047 if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
1048 BlockQueue.push_back(B);
1051 while (!BlockQueue.empty()) {
1053 BlockQueue.pop_front();
1057 if (*I && ReachableBlocks.insert(*I).second)
1058 BlockQueue.push_back(*I);
1063 bool checkFallThroughIntoBlock(
const CFGBlock &B,
int &AnnotatedCnt,
1064 bool IsTemplateInstantiation) {
1065 assert(!ReachableBlocks.empty() &&
"ReachableBlocks empty");
1067 int UnannotatedCnt = 0;
1071 while (!BlockQueue.empty()) {
1073 BlockQueue.pop_front();
1077 if (Term && isa<SwitchStmt>(Term))
1088 if (!ReachableBlocks.count(P)) {
1090 ElemEnd = P->
rend();
1091 ElemIt != ElemEnd; ++ElemIt) {
1093 if (
const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
1097 if (!IsTemplateInstantiation)
1098 S.
Diag(AS->getBeginLoc(),
1099 diag::warn_fallthrough_attr_unreachable);
1100 markFallthroughVisited(AS);
1120 markFallthroughVisited(AS);
1128 std::back_inserter(BlockQueue));
1134 return !!UnannotatedCnt;
1138 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1141 if (asFallThroughAttr(S))
1142 FallthroughStmts.insert(S);
1147 FoundSwitchStatements =
true;
1153 bool TraverseDecl(
Decl *D) {
return true; }
1159 TraverseLambdaCapture(LE, &std::get<0>(
C), std::get<1>(
C));
1166 if (
const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
1167 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
1178 ElemIt != ElemEnd; ++ElemIt) {
1180 return CS->getStmt();
1186 if (!isa<SwitchCase>(SW->getSubStmt()))
1187 return SW->getSubStmt();
1192 bool FoundSwitchStatements;
1193 AttrStmts FallthroughStmts;
1195 llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
1202 tok::l_square, tok::l_square,
1204 tok::r_square, tok::r_square
1210 tok::r_square, tok::r_square
1213 bool PreferClangAttr = !PP.
getLangOpts().CPlusPlus17;
1215 StringRef MacroName;
1216 if (PreferClangAttr)
1218 if (MacroName.empty())
1220 if (MacroName.empty() && !PreferClangAttr)
1222 if (MacroName.empty())
1223 MacroName = PreferClangAttr ?
"[[clang::fallthrough]]" :
"[[fallthrough]]";
1240 FallthroughMapper FM(S);
1241 FM.TraverseStmt(AC.
getBody());
1243 if (!FM.foundSwitchStatements())
1246 if (PerFunction && FM.getFallthroughStmts().empty())
1254 FM.fillReachableBlocks(Cfg);
1256 for (
const CFGBlock *B : llvm::reverse(*Cfg)) {
1259 if (!Label || !isa<SwitchCase>(Label))
1264 bool IsTemplateInstantiation =
false;
1266 IsTemplateInstantiation = Function->isTemplateInstantiation();
1267 if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
1268 IsTemplateInstantiation))
1272 PerFunction ? diag::warn_unannotated_fallthrough_per_function
1273 : diag::warn_unannotated_fallthrough);
1275 if (!AnnotatedCnt) {
1280 const Stmt *Term = B->getTerminator();
1282 while (B->empty() && !Term && B->succ_size() == 1) {
1283 B = *B->succ_begin();
1284 Term = B->getTerminator();
1286 if (!(B->empty() && Term && isa<BreakStmt>(Term))) {
1290 TextToInsert +=
"; ";
1291 S.
Diag(L, diag::note_insert_fallthrough_fixit) <<
1292 AnnotationSpelling <<
1296 S.
Diag(L, diag::note_insert_break_fixit) <<
1301 for (
const auto *F : FM.getFallthroughStmts())
1302 S.
Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);
1311 case Stmt::ForStmtClass:
1312 case Stmt::WhileStmtClass:
1313 case Stmt::CXXForRangeStmtClass:
1314 case Stmt::ObjCForCollectionStmtClass:
1316 case Stmt::DoStmtClass: {
1318 if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))
1320 return Result.
Val.
getInt().getBoolValue();
1337 typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
1346 for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end();
1348 const WeakUseVector &Uses = I->second;
1351 WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
1352 for ( ; UI != UE; ++UI) {
1365 if (UI == Uses.begin()) {
1366 WeakUseVector::const_iterator UI2 = UI;
1367 for (++UI2; UI2 != UE; ++UI2)
1368 if (UI2->isUnsafe())
1372 if (!
isInLoop(Ctx, PM, UI->getUseExpr()))
1375 const WeakObjectProfileTy &Profile = I->first;
1376 if (!Profile.isExactProfile())
1381 Base = Profile.getProperty();
1382 assert(Base &&
"A profile always has a base or property.");
1384 if (
const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
1385 if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
1390 UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
1393 if (UsesByStmt.empty())
1398 llvm::sort(UsesByStmt,
1399 [&SM](
const StmtUsesPair &LHS,
const StmtUsesPair &RHS) {
1401 RHS.first->getBeginLoc());
1416 if (isa<sema::BlockScopeInfo>(CurFn))
1417 FunctionKind = Block;
1418 else if (isa<sema::LambdaScopeInfo>(CurFn))
1419 FunctionKind = Lambda;
1420 else if (isa<ObjCMethodDecl>(D))
1421 FunctionKind = Method;
1423 FunctionKind = Function;
1426 for (
const auto &
P : UsesByStmt) {
1427 const Stmt *FirstRead =
P.first;
1428 const WeakObjectProfileTy &Key =
P.second->first;
1429 const WeakUseVector &Uses =
P.second->second;
1437 if (Key.isExactProfile())
1438 DiagKind = diag::warn_arc_repeated_use_of_weak;
1440 DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
1452 const NamedDecl *KeyProp = Key.getProperty();
1453 if (isa<VarDecl>(KeyProp))
1454 ObjectKind = Variable;
1455 else if (isa<ObjCPropertyDecl>(KeyProp))
1457 else if (isa<ObjCMethodDecl>(KeyProp))
1458 ObjectKind = ImplicitProperty;
1459 else if (isa<ObjCIvarDecl>(KeyProp))
1462 llvm_unreachable(
"Unexpected weak object kind!");
1467 if (Prop->hasAttr<IBOutletAttr>())
1472 <<
int(ObjectKind) << KeyProp << int(FunctionKind)
1476 for (
const auto &Use : Uses) {
1477 if (Use.getUseExpr() == FirstRead)
1479 S.
Diag(Use.getUseExpr()->getBeginLoc(),
1480 diag::note_arc_weak_also_accessed_here)
1481 << Use.getUseExpr()->getSourceRange();
1490 typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
1494 typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
1498 UninitValsDiagReporter(
Sema &S) : S(S) {}
1501 MappedType &getUses(
const VarDecl *vd) {
1502 MappedType &V = uses[vd];
1503 if (!V.getPointer())
1504 V.setPointer(
new UsesVec());
1508 void handleUseOfUninitVariable(
const VarDecl *vd,
1510 getUses(vd).getPointer()->push_back(use);
1513 void handleSelfInit(
const VarDecl *vd)
override {
1514 getUses(vd).setInt(
true);
1518 for (
const auto &
P : uses) {
1520 const MappedType &V =
P.second;
1522 UsesVec *vec = V.getPointer();
1523 bool hasSelfInit = V.getInt();
1528 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
1537 llvm::sort(vec->begin(), vec->end(),
1540 if (a.
getKind() != b.getKind())
1541 return a.
getKind() > b.getKind();
1545 for (
const auto &U : *vec) {
1564 static bool hasAlwaysUninitializedUse(
const UsesVec* vec) {
1565 return std::any_of(vec->begin(), vec->end(), [](
const UninitUse &U) {
1577 typedef std::pair<PartialDiagnosticAt, OptionalNotes>
DelayedDiag;
1578 typedef std::list<DelayedDiag>
DiagList;
1580 struct SortDiagBySourceLocation {
1584 bool operator()(
const DelayedDiag &left,
const DelayedDiag &right) {
1597 namespace threadSafety {
1608 if (Verbose && CurrentFunction) {
1610 S.
PDiag(diag::note_thread_warning_in_fun)
1611 << CurrentFunction);
1619 if (Verbose && CurrentFunction) {
1621 S.
PDiag(diag::note_thread_warning_in_fun)
1622 << CurrentFunction);
1623 ONS.push_back(std::move(FNote));
1631 ONS.push_back(Note1);
1632 ONS.push_back(Note2);
1633 if (Verbose && CurrentFunction) {
1635 S.
PDiag(diag::note_thread_warning_in_fun)
1636 << CurrentFunction);
1637 ONS.push_back(std::move(FNote));
1643 void warnLockMismatch(
unsigned DiagID, StringRef
Kind, Name LockName,
1650 Warnings.emplace_back(std::move(
Warning), getNotes());
1655 : S(S), FunLocation(FL), FunEndLocation(FEL),
1656 CurrentFunction(
nullptr), Verbose(
false) {}
1658 void setVerbose(
bool b) { Verbose = b; }
1666 for (
const auto &
Diag : Warnings) {
1668 for (
const auto &Note :
Diag.second)
1669 S.
Diag(Note.first, Note.second);
1673 void handleInvalidLockExp(StringRef Kind,
SourceLocation Loc)
override {
1676 Warnings.emplace_back(std::move(
Warning), getNotes());
1679 void handleUnmatchedUnlock(StringRef Kind, Name LockName,
1681 warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc);
1684 void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
1690 << Kind << LockName << Received
1692 Warnings.emplace_back(std::move(
Warning), getNotes());
1695 void handleDoubleLock(StringRef Kind, Name LockName,
SourceLocation Loc)
override {
1696 warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc);
1699 void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
1703 unsigned DiagID = 0;
1706 DiagID = diag::warn_lock_some_predecessors;
1709 DiagID = diag::warn_expecting_lock_held_on_loop;
1712 DiagID = diag::warn_no_unlock;
1715 DiagID = diag::warn_expecting_locked;
1719 LocEndOfScope = FunEndLocation;
1726 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1729 Warnings.emplace_back(std::move(
Warning), getNotes());
1732 void handleExclusiveAndShared(StringRef Kind, Name LockName,
1736 S.
PDiag(diag::warn_lock_exclusive_and_shared)
1737 << Kind << LockName);
1739 << Kind << LockName);
1740 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1743 void handleNoMutexHeld(StringRef Kind,
const NamedDecl *D,
1747 "Only works for variables");
1749 diag::warn_variable_requires_any_lock:
1750 diag::warn_var_deref_requires_any_lock;
1753 Warnings.emplace_back(std::move(
Warning), getNotes());
1756 void handleMutexNotHeld(StringRef Kind,
const NamedDecl *D,
1759 Name *PossibleMatch)
override {
1760 unsigned DiagID = 0;
1761 if (PossibleMatch) {
1764 DiagID = diag::warn_variable_requires_lock_precise;
1767 DiagID = diag::warn_var_deref_requires_lock_precise;
1770 DiagID = diag::warn_fun_requires_lock_precise;
1773 DiagID = diag::warn_guarded_pass_by_reference;
1776 DiagID = diag::warn_pt_guarded_pass_by_reference;
1786 S.
PDiag(diag::note_guarded_by_declared_here)
1788 Warnings.emplace_back(std::move(
Warning), getNotes(Note, VNote));
1790 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1794 DiagID = diag::warn_variable_requires_lock;
1797 DiagID = diag::warn_var_deref_requires_lock;
1800 DiagID = diag::warn_fun_requires_lock;
1803 DiagID = diag::warn_guarded_pass_by_reference;
1806 DiagID = diag::warn_pt_guarded_pass_by_reference;
1814 S.
PDiag(diag::note_guarded_by_declared_here));
1815 Warnings.emplace_back(std::move(
Warning), getNotes(Note));
1817 Warnings.emplace_back(std::move(
Warning), getNotes());
1821 void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
1824 S.
PDiag(diag::warn_acquire_requires_negative_cap)
1825 << Kind << LockName << Neg);
1826 Warnings.emplace_back(std::move(
Warning), getNotes());
1829 void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
1832 << Kind << FunName << LockName);
1833 Warnings.emplace_back(std::move(
Warning), getNotes());
1836 void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
1839 S.
PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
1840 Warnings.emplace_back(std::move(
Warning), getNotes());
1843 void handleBeforeAfterCycle(Name L1Name,
SourceLocation Loc)
override {
1845 S.
PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
1846 Warnings.emplace_back(std::move(
Warning), getNotes());
1850 CurrentFunction = FD;
1854 CurrentFunction =
nullptr;
1866 namespace consumed {
1868 class ConsumedWarningsHandler :
public ConsumedWarningsHandlerBase {
1875 ConsumedWarningsHandler(
Sema &S) : S(S) {}
1879 for (
const auto &
Diag : Warnings) {
1881 for (
const auto &
Note :
Diag.second)
1887 StringRef VariableName)
override {
1895 StringRef VariableName,
1896 StringRef ExpectedState,
1897 StringRef ObservedState)
override {
1900 diag::warn_param_return_typestate_mismatch) << VariableName <<
1901 ExpectedState << ObservedState);
1906 void warnParamTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1907 StringRef ObservedState)
override {
1910 diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
1916 StringRef TypeName)
override {
1918 diag::warn_return_typestate_for_unconsumable_type) << TypeName);
1923 void warnReturnTypestateMismatch(
SourceLocation Loc, StringRef ExpectedState,
1924 StringRef ObservedState)
override {
1927 diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
1932 void warnUseOfTempInInvalidState(StringRef MethodName, StringRef
State,
1936 diag::warn_use_of_temp_in_invalid_state) << MethodName <<
State);
1941 void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
1945 MethodName << VariableName <<
State);
1960 enableCheckFallThrough = 1;
1961 enableCheckUnreachable = 0;
1962 enableThreadSafetyAnalysis = 0;
1963 enableConsumedAnalysis = 0;
1972 NumFunctionsAnalyzed(0),
1973 NumFunctionsWithBadCFGs(0),
1975 MaxCFGBlocksPerFunction(0),
1976 NumUninitAnalysisFunctions(0),
1977 NumUninitAnalysisVariables(0),
1978 MaxUninitAnalysisVariablesPerFunction(0),
1979 NumUninitAnalysisBlockVisits(0),
1980 MaxUninitAnalysisBlockVisitsPerFunction(0) {
1982 using namespace diag;
1985 DefaultPolicy.enableCheckUnreachable =
1988 isEnabled(D, warn_unreachable_return) ||
1989 isEnabled(D, warn_unreachable_loop_increment);
1991 DefaultPolicy.enableThreadSafetyAnalysis =
1994 DefaultPolicy.enableConsumedAnalysis =
1995 isEnabled(D, warn_use_in_invalid_state);
2000 S.
Diag(D.Loc, D.PD);
2023 if (cast<DeclContext>(D)->isDependentContext())
2054 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
2055 P.enableConsumedAnalysis) {
2073 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2081 bool analyzed =
false;
2092 bool processed =
false;
2103 S.
Diag(D.Loc, D.PD);
2109 S.
Diag(D.Loc, D.PD);
2119 if (P.enableCheckFallThrough) {
2120 const CheckFallThroughDiagnostics &CD =
2122 ? CheckFallThroughDiagnostics::MakeForBlock()
2123 : (isa<CXXMethodDecl>(D) &&
2124 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
2125 cast<CXXMethodDecl>(D)->getParent()->isLambda())
2126 ? CheckFallThroughDiagnostics::MakeForLambda()
2128 ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
2129 : CheckFallThroughDiagnostics::MakeForFunction(D)));
2134 if (P.enableCheckUnreachable) {
2140 if (
const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
2141 isTemplateInstantiation = Function->isTemplateInstantiation();
2142 if (!isTemplateInstantiation)
2147 if (P.enableThreadSafetyAnalysis) {
2150 threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
2152 Reporter.setIssueBetaWarnings(
true);
2154 Reporter.setVerbose(
true);
2158 Reporter.emitDiagnostics();
2162 if (P.enableConsumedAnalysis) {
2163 consumed::ConsumedWarningsHandler WarningHandler(S);
2172 UninitValsDiagReporter reporter(S);
2179 ++NumUninitAnalysisFunctions;
2182 MaxUninitAnalysisVariablesPerFunction =
2183 std::max(MaxUninitAnalysisVariablesPerFunction,
2185 MaxUninitAnalysisBlockVisitsPerFunction =
2186 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
2192 bool FallThroughDiagFull =
2194 bool FallThroughDiagPerFunction = !Diags.
isIgnored(
2195 diag::warn_unannotated_fallthrough_per_function, D->
getBeginLoc());
2196 if (FallThroughDiagFull || FallThroughDiagPerFunction ||
2207 if (!Diags.
isIgnored(diag::warn_infinite_recursive_function,
2209 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2216 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2222 if (!Diags.
isIgnored(diag::warn_tautological_overlap_comparison,
2229 ++NumFunctionsAnalyzed;
2234 MaxCFGBlocksPerFunction =
std::max(MaxCFGBlocksPerFunction,
2235 cfg->getNumBlockIDs());
2237 ++NumFunctionsWithBadCFGs;
2243 llvm::errs() <<
"\n*** Analysis Based Warnings Stats:\n";
2245 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
2246 unsigned AvgCFGBlocksPerFunction =
2247 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
2248 llvm::errs() << NumFunctionsAnalyzed <<
" functions analyzed (" 2249 << NumFunctionsWithBadCFGs <<
" w/o CFGs).\n" 2250 <<
" " << NumCFGBlocks <<
" CFG blocks built.\n" 2251 <<
" " << AvgCFGBlocksPerFunction
2252 <<
" average CFG blocks per function.\n" 2253 <<
" " << MaxCFGBlocksPerFunction
2254 <<
" max CFG blocks per function.\n";
2256 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
2257 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
2258 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
2259 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
2260 llvm::errs() << NumUninitAnalysisFunctions
2261 <<
" functions analyzed for uninitialiazed variables\n" 2262 <<
" " << NumUninitAnalysisVariables <<
" variables analyzed.\n" 2263 <<
" " << AvgUninitVariablesPerFunction
2264 <<
" average variables per function.\n" 2265 <<
" " << MaxUninitAnalysisVariablesPerFunction
2266 <<
" max variables per function.\n" 2267 <<
" " << NumUninitAnalysisBlockVisits <<
" block visits.\n" 2268 <<
" " << AvgUninitBlockVisitsPerFunction
2269 <<
" average block visits per function.\n" 2270 <<
" " << MaxUninitAnalysisBlockVisitsPerFunction
2271 <<
" 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...
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.
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.
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.
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)
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".
void IssueWarnings(Policy P, FunctionScopeInfo *fscope, const Decl *D, const BlockExpr *blkExpr)
static StringRef getFallthroughAttrSpelling(Preprocessor &PP, SourceLocation Loc)
SourceLocation getThrowLoc() const
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC)
CheckUnreachable - Check for unreachable code.
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC)...
__DEVICE__ void * memset(void *__a, int __b, size_t __c)
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
const LangOptions & getLangOpts() const
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification, if any.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD)
DiagnosticsEngine & getDiagnostics() const
Passing a pt-guarded variable by reference.
ConditionalOperator - The ?: ternary operator.
Sema - This implements semantic analysis and AST building for C.
Represents a prototype with parameter type info, e.g.
static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool alwaysReportSelfInit=false)
DiagnoseUninitializedUse – Helper function for diagnosing uses of an uninitialized variable...
Handler class for thread safety warnings.
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
Retrieves 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.
CFGTerminator getTerminator()
QualType getCanonicalType() const
Reading or writing a variable (e.g. x in x = 5;)
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
ASTContext & getASTContext() const
Encodes a location in the source.
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
static void visitReachableThrows(CFG *BodyCFG, llvm::function_ref< void(const CXXThrowExpr *, CFGBlock &)> Visit)
SourceLocation getOperatorLoc() const
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
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.
A class that handles the analysis of uniqueness violations.
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
static bool isNoexcept(const FunctionDecl *FD)
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
SwitchStmt - This represents a 'switch' stmt.
The standard open() call: int open(const char *path, int oflag, ...);.
UnreachableKind
Classifications of unreachable code.
const Expr * getUser() const
Get the expression containing the uninitialized use.
The use is always uninitialized.
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, const BlockExpr *blkExpr, const CheckFallThroughDiagnostics &CD, AnalysisDeclContext &AC, sema::FunctionScopeInfo *FSI)
CheckFallThroughForBody - Check that we don't fall off the end of a function that should return a val...
TypeSourceInfo * getTypeSourceInfo() const
static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock, CFG *Body)
Determine whether an exception thrown by E, unwinding from ThrowBlock, can reach ExitBlock.
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, const Stmt *Body, AnalysisDeclContext &AC)
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope)
bool hasNoReturnElement() const
SmallVector< PartialDiagnosticAt, 1 > OptionalNotes
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Defines the clang::SourceLocation class and associated facilities.
SmallVector< PossiblyUnreachableDiag, 4 > PossiblyUnreachableDiags
A list of PartialDiagnostics created but delayed within the current function scope.
CFGCallback defines methods that should be called when a logical operator error is found when buildin...
Expr * getTrueExpr() const
void run(AnalysisDeclContext &AC)
Check a function's CFG for consumed violations.
Represents a top-level expression in a basic block.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string...
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
__DEVICE__ int max(int __a, int __b)
llvm::SmallDenseMap< WeakObjectProfileTy, WeakUseVector, 8, WeakObjectProfileTy::DenseMapInfo > WeakObjectUseMap
Used to collect all uses of weak objects in a function body.
A reference to a declared variable, function, enum, etc.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
SourceManager & SourceMgr
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
unsigned NumVariablesAnalyzed
ParentMap & getParentMap()
A trivial tuple used to represent a source range.
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
This represents a decl that may have a name.
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block)
This class handles loading and caching of source files into memory.
SourceLocation getLocation() const
QualType getType() const
Return the type wrapped by this type source info.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.