23#define DEBUG_TYPE "effectanalysis" 
   29enum class ViolationID : uint8_t {
 
   35  ThrowsOrCatchesExceptions,
 
   36  HasStaticLocalVariable,
 
   37  AccessesThreadLocalVariable,
 
   38  AccessesObjCMethodOrProperty,
 
   41  DeclDisallowsInference,
 
   47  CallsDeclWithoutEffect,
 
   48  CallsExprWithoutEffect,
 
   55  enum class Kind : uint8_t {
 
   62  llvm::PointerIntPair<CXXDefaultArgExpr *, 2, Kind> Impl;
 
   65  ViolationSite() = 
default;
 
   68      : Impl(E, Kind::DefaultArgExpr) {}
 
   70  Kind kind()
 const { 
return static_cast<Kind
>(Impl.getInt()); }
 
   73  void setKind(Kind K) { Impl.setPointerAndInt(
nullptr, K); }
 
   84  std::optional<FunctionEffect>
 
   85      CalleeEffectPreventingInference; 
 
   86  ViolationID ID = ViolationID::None;
 
   94            std::optional<FunctionEffect> CalleeEffect = std::nullopt)
 
   95      : Effect(Effect), CalleeEffectPreventingInference(CalleeEffect), ID(ID),
 
   96        Site(VS), Loc(Loc), Callee(Callee) {}
 
   98  unsigned diagnosticSelectIndex()
 const {
 
  103enum class SpecialFuncType : uint8_t { 
None, OperatorNew, OperatorDelete };
 
  104enum class CallableType : uint8_t {
 
  114static bool functionIsVerifiable(
const FunctionDecl *FD) {
 
  125  return FPT && (FPT->isNothrow() || FD->
hasAttr<NoThrowAttr>());
 
  144  case Builtin::ID::BI__builtin_calloc:
 
  145  case Builtin::ID::BI__builtin_malloc:
 
  146  case Builtin::ID::BI__builtin_realloc:
 
  147  case Builtin::ID::BI__builtin_free:
 
  148  case Builtin::ID::BI__builtin_operator_delete:
 
  149  case Builtin::ID::BI__builtin_operator_new:
 
  150  case Builtin::ID::BIaligned_alloc:
 
  151  case Builtin::ID::BIcalloc:
 
  152  case Builtin::ID::BImalloc:
 
  153  case Builtin::ID::BImemalign:
 
  154  case Builtin::ID::BIrealloc:
 
  155  case Builtin::ID::BIfree:
 
  157  case Builtin::ID::BIfopen:
 
  158  case Builtin::ID::BIpthread_create:
 
  159  case Builtin::ID::BI_Block_object_dispose:
 
  166  case Builtin::ID::BIlongjmp:
 
  167  case Builtin::ID::BI_longjmp:
 
  168  case Builtin::ID::BIsiglongjmp:
 
  169  case Builtin::ID::BI__builtin_longjmp:
 
  170  case Builtin::ID::BIobjc_exception_throw:
 
  173  case Builtin::ID::BIobjc_msgSend:
 
  174  case Builtin::ID::BIobjc_msgSend_fpret:
 
  175  case Builtin::ID::BIobjc_msgSend_fp2ret:
 
  176  case Builtin::ID::BIobjc_msgSend_stret:
 
  177  case Builtin::ID::BIobjc_msgSendSuper:
 
  178  case Builtin::ID::BIobjc_getClass:
 
  179  case Builtin::ID::BIobjc_getMetaClass:
 
  180  case Builtin::ID::BIobjc_enumerationMutation:
 
  181  case Builtin::ID::BIobjc_assign_ivar:
 
  182  case Builtin::ID::BIobjc_assign_global:
 
  183  case Builtin::ID::BIobjc_sync_enter:
 
  184  case Builtin::ID::BIobjc_sync_exit:
 
  185  case Builtin::ID::BINSLog:
 
  186  case Builtin::ID::BINSLogv:
 
  189  case Builtin::ID::BIfread:
 
  190  case Builtin::ID::BIfwrite:
 
  193  case Builtin::ID::BIprintf:
 
  194  case Builtin::ID::BI__builtin_printf:
 
  195  case Builtin::ID::BIfprintf:
 
  196  case Builtin::ID::BIsnprintf:
 
  197  case Builtin::ID::BIsprintf:
 
  198  case Builtin::ID::BIvprintf:
 
  199  case Builtin::ID::BIvfprintf:
 
  200  case Builtin::ID::BIvsnprintf:
 
  201  case Builtin::ID::BIvsprintf:
 
  204  case Builtin::ID::BIscanf:
 
  205  case Builtin::ID::BIfscanf:
 
  206  case Builtin::ID::BIsscanf:
 
  207  case Builtin::ID::BIvscanf:
 
  208  case Builtin::ID::BIvfscanf:
 
  209  case Builtin::ID::BIvsscanf:
 
  227  CallableType CType = CallableType::Unknown;
 
  232  SpecialFuncType FuncType = SpecialFuncType::None;
 
  237  CallableInfo(
const Decl &CD, SpecialFuncType FT = SpecialFuncType::None)
 
  238      : CDecl(&CD), FuncType(FT) {
 
  240    if (
auto *FD = dyn_cast<FunctionDecl>(CDecl)) {
 
  244      CType = CallableType::Function;
 
  245      if (
auto *Method = dyn_cast<CXXMethodDecl>(FD);
 
  246          Method && Method->isVirtual())
 
  247        CType = CallableType::Virtual;
 
  249    } 
else if (
auto *BD = dyn_cast<BlockDecl>(CDecl)) {
 
  250      CType = CallableType::Block;
 
  251      DeclEffects = BD->getFunctionEffects();
 
  252    } 
else if (
auto *VD = dyn_cast<ValueDecl>(CDecl)) {
 
  259  CallableType 
type()
 const { 
return CType; }
 
  261  bool isCalledDirectly()
 const {
 
  262    return CType == CallableType::Function || CType == CallableType::Block;
 
  265  bool isVerifiable()
 const {
 
  267    case CallableType::Unknown:
 
  268    case CallableType::Virtual:
 
  270    case CallableType::Block:
 
  272    case CallableType::Function:
 
  273      return functionIsVerifiable(dyn_cast<FunctionDecl>(CDecl));
 
  275    llvm_unreachable(
"undefined CallableType");
 
  279  std::string getNameForDiagnostic(
Sema &S)
 const {
 
  281    llvm::raw_string_ostream OS(Name);
 
  283    if (
auto *FD = dyn_cast<FunctionDecl>(CDecl))
 
  286    else if (
auto *BD = dyn_cast<BlockDecl>(CDecl))
 
  287      OS << 
"(block " << BD->getBlockManglingNumber() << 
")";
 
  288    else if (
auto *VD = dyn_cast<NamedDecl>(CDecl))
 
  289      VD->printQualifiedName(OS);
 
  297class EffectToViolationMap {
 
  304  std::unique_ptr<ImplVec> Impl;
 
  308  void maybeInsert(
const Violation &Viol) {
 
  310      Impl = std::make_unique<ImplVec>();
 
  311    else if (lookup(Viol.Effect) != 
nullptr)
 
  314    Impl->push_back(Viol);
 
  321    auto *Iter = llvm::find_if(
 
  322        *Impl, [&](
const auto &Item) { 
return Item.Effect == Key; });
 
  323    return Iter != Impl->end() ? &*Iter : 
nullptr;
 
  326  size_t size()
 const { 
return Impl ? Impl->size() : 0; }
 
  332class PendingFunctionAnalysis {
 
  333  friend class CompleteFunctionAnalysis;
 
  341    bool Recursed = 
false;
 
  345        : Callee(D), CallLoc(CallLoc), VSite(VSite) {}
 
  359  EffectToViolationMap InferrableEffectToFirstViolation;
 
  366  PendingFunctionAnalysis(
Sema &S, 
const CallableInfo &CInfo,
 
  368      : DeclaredVerifiableEffects(CInfo.Effects) {
 
  373      std::optional<FunctionEffect> ProblemCalleeEffect =
 
  374          effect.effectProhibitingInference(*CInfo.CDecl, CInfo.Effects);
 
  375      if (!ProblemCalleeEffect)
 
  376        InferrableEffects.
insert(effect);
 
  380        InferrableEffectToFirstViolation.maybeInsert(Violation(
 
  381            effect, ViolationID::DeclDisallowsInference, ViolationSite{},
 
  382            CInfo.CDecl->
getLocation(), 
nullptr, ProblemCalleeEffect));
 
  388        InferrableEffects, DeclaredVerifiableEffects);
 
  393  void checkAddViolation(
bool Inferring, 
const Violation &NewViol) {
 
  395      ViolationsForExplicitEffects.push_back(NewViol);
 
  397      InferrableEffectToFirstViolation.maybeInsert(NewViol);
 
  401                               ViolationSite VSite) {
 
  402    UnverifiedDirectCalls.emplace_back(D, CallLoc, VSite);
 
  406  bool isComplete()
 const { 
return UnverifiedDirectCalls.empty(); }
 
  408  const Violation *violationForInferrableEffect(
FunctionEffect effect) {
 
  409    return InferrableEffectToFirstViolation.lookup(effect);
 
  414    assert(!isComplete());
 
  415    return UnverifiedDirectCalls;
 
  419    if (!ViolationsForExplicitEffects.empty())
 
  420      llvm::sort(ViolationsForExplicitEffects,
 
  421                 [&
SM](
const Violation &LHS, 
const Violation &RHS) {
 
  422                   return SM.isBeforeInTranslationUnit(LHS.Loc, RHS.Loc);
 
  424    return ViolationsForExplicitEffects;
 
  427  void dump(
Sema &SemaRef, llvm::raw_ostream &OS)
 const {
 
  428    OS << 
"Pending: Declared ";
 
  429    DeclaredVerifiableEffects.
dump(OS);
 
  430    OS << 
", " << ViolationsForExplicitEffects.size() << 
" violations; ";
 
  432    EffectsToInfer.
dump(OS);
 
  433    OS << 
", " << InferrableEffectToFirstViolation.size() << 
" violations";
 
  434    if (!UnverifiedDirectCalls.empty()) {
 
  436      for (
const DirectCall &
Call : UnverifiedDirectCalls) {
 
  437        CallableInfo CI(*
Call.Callee);
 
  438        OS << 
" " << CI.getNameForDiagnostic(SemaRef);
 
  446class CompleteFunctionAnalysis {
 
  457  EffectToViolationMap InferrableEffectToFirstViolation;
 
  461  CompleteFunctionAnalysis(
ASTContext &Ctx, PendingFunctionAnalysis &&Pending,
 
  464      : VerifiedEffects(DeclaredEffects) {
 
  466      if (Pending.violationForInferrableEffect(effect) == 
nullptr)
 
  467        VerifiedEffects.
insert(effect);
 
  469    InferrableEffectToFirstViolation =
 
  470        std::move(Pending.InferrableEffectToFirstViolation);
 
  474    return InferrableEffectToFirstViolation.lookup(Effect);
 
  477  void dump(llvm::raw_ostream &OS)
 const {
 
  478    OS << 
"Complete: Verified ";
 
  479    VerifiedEffects.
dump(OS);
 
  481    OS << InferrableEffectToFirstViolation.size() << 
" violations\n";
 
  492  using FuncAnalysisPtr =
 
  493      llvm::PointerUnion<PendingFunctionAnalysis *, CompleteFunctionAnalysis *>;
 
  498  class AnalysisMap : llvm::DenseMap<const Decl *, FuncAnalysisPtr> {
 
  499    using Base = llvm::DenseMap<const Decl *, FuncAnalysisPtr>;
 
  507    FuncAnalysisPtr lookup(
const Decl *Key)
 const {
 
  511    FuncAnalysisPtr &operator[](
const Decl *Key) {
 
  516    CompleteFunctionAnalysis *completedAnalysisForDecl(
const Decl *D)
 const {
 
  517      if (FuncAnalysisPtr AP = lookup(D);
 
  518          isa_and_nonnull<CompleteFunctionAnalysis *>(AP))
 
  523    void dump(
Sema &SemaRef, llvm::raw_ostream &OS) {
 
  524      OS << 
"\nAnalysisMap:\n";
 
  525      for (
const auto &item : *
this) {
 
  526        CallableInfo CI(*item.first);
 
  527        const auto AP = item.second;
 
  528        OS << item.first << 
" " << CI.getNameForDiagnostic(SemaRef) << 
" : ";
 
  531        } 
else if (
auto *CFA = dyn_cast<CompleteFunctionAnalysis *>(AP)) {
 
  534        } 
else if (
auto *PFA = dyn_cast<PendingFunctionAnalysis *>(AP)) {
 
  536          PFA->dump(SemaRef, OS);
 
  538          llvm_unreachable(
"never");
 
  543  AnalysisMap DeclAnalysis;
 
  546  Analyzer(
Sema &S) : S(S) {}
 
  554        AllInferrableEffectsToVerify.
insert(Effect);
 
  556    LLVM_DEBUG(llvm::dbgs() << 
"AllInferrableEffectsToVerify: ";
 
  557               AllInferrableEffectsToVerify.
dump(llvm::dbgs());
 
  558               llvm::dbgs() << 
"\n";);
 
  565    std::reverse(VerificationQueue.begin(), VerificationQueue.end());
 
  567    while (!VerificationQueue.empty()) {
 
  568      const Decl *D = VerificationQueue.back();
 
  569      if (FuncAnalysisPtr AP = DeclAnalysis.lookup(D)) {
 
  570        if (
auto *Pending = dyn_cast<PendingFunctionAnalysis *>(AP)) {
 
  572          finishPendingAnalysis(D, Pending);
 
  574        VerificationQueue.pop_back();
 
  579      PendingFunctionAnalysis *Pending = verifyDecl(D);
 
  580      if (Pending == 
nullptr) {
 
  582        VerificationQueue.pop_back();
 
  588      for (PendingFunctionAnalysis::DirectCall &
Call :
 
  589           Pending->unverifiedCalls()) {
 
  590        FuncAnalysisPtr AP = DeclAnalysis.lookup(
Call.Callee);
 
  592          VerificationQueue.push_back(
Call.Callee);
 
  600        Call.Recursed = 
true;
 
  608  PendingFunctionAnalysis *verifyDecl(
const Decl *D) {
 
  609    CallableInfo CInfo(*D);
 
  623        bool IsNoexcept = 
false;
 
  626        } 
else if (
auto *BD = dyn_cast<BlockDecl>(D)) {
 
  627          if (
auto *TSI = BD->getSignatureAsWritten()) {
 
  629            IsNoexcept = FPT->isNothrow() || BD->hasAttr<NoThrowAttr>();
 
  634              << GetCallableDeclKind(D, 
nullptr) << Effect.
name();
 
  642    PendingFunctionAnalysis FAnalysis(S, CInfo, AllInferrableEffectsToVerify);
 
  644    LLVM_DEBUG(llvm::dbgs()
 
  645                   << 
"\nVerifying " << CInfo.getNameForDiagnostic(S) << 
" ";
 
  646               FAnalysis.dump(S, llvm::dbgs()););
 
  648    FunctionBodyASTVisitor Visitor(*
this, FAnalysis, CInfo);
 
  651    if (FAnalysis.isComplete()) {
 
  652      completeAnalysis(CInfo, std::move(FAnalysis));
 
  656    PendingFunctionAnalysis *PendingPtr =
 
  657        new PendingFunctionAnalysis(std::move(FAnalysis));
 
  658    DeclAnalysis[D] = PendingPtr;
 
  659    LLVM_DEBUG(llvm::dbgs() << 
"inserted pending " << PendingPtr << 
"\n";
 
  660               DeclAnalysis.dump(S, llvm::dbgs()););
 
  666  void completeAnalysis(
const CallableInfo &CInfo,
 
  667                        PendingFunctionAnalysis &&Pending) {
 
  673    CompleteFunctionAnalysis *CompletePtr = 
new CompleteFunctionAnalysis(
 
  675        AllInferrableEffectsToVerify);
 
  676    DeclAnalysis[CInfo.CDecl] = CompletePtr;
 
  677    LLVM_DEBUG(llvm::dbgs() << 
"inserted complete " << CompletePtr << 
"\n";
 
  678               DeclAnalysis.dump(S, llvm::dbgs()););
 
  684  void finishPendingAnalysis(
const Decl *D, PendingFunctionAnalysis *Pending) {
 
  685    CallableInfo Caller(*D);
 
  686    LLVM_DEBUG(llvm::dbgs() << 
"finishPendingAnalysis for " 
  687                            << Caller.getNameForDiagnostic(S) << 
" : ";
 
  688               Pending->dump(S, llvm::dbgs()); llvm::dbgs() << 
"\n";);
 
  689    for (
const PendingFunctionAnalysis::DirectCall &
Call :
 
  690         Pending->unverifiedCalls()) {
 
  694      CallableInfo Callee(*
Call.Callee);
 
  695      followCall(Caller, *Pending, Callee, 
Call.CallLoc,
 
  698    completeAnalysis(Caller, std::move(*Pending));
 
  704  void followCall(
const CallableInfo &Caller, PendingFunctionAnalysis &PFA,
 
  706                  bool AssertNoFurtherInference, ViolationSite VSite) {
 
  707    const bool DirectCall = Callee.isCalledDirectly();
 
  712    bool IsInferencePossible = DirectCall;
 
  715      if (CompleteFunctionAnalysis *CFA =
 
  716              DeclAnalysis.completedAnalysisForDecl(Callee.CDecl)) {
 
  718        CalleeEffects.
insert(CFA->VerifiedEffects);
 
  719        IsInferencePossible = 
false; 
 
  722    if (AssertNoFurtherInference) {
 
  723      assert(!IsInferencePossible);
 
  726    if (!Callee.isVerifiable())
 
  727      IsInferencePossible = 
false;
 
  729    LLVM_DEBUG(llvm::dbgs()
 
  730                   << 
"followCall from " << Caller.getNameForDiagnostic(S)
 
  731                   << 
" to " << Callee.getNameForDiagnostic(S)
 
  732                   << 
"; verifiable: " << Callee.isVerifiable() << 
"; callee ";
 
  733               CalleeEffects.
dump(llvm::dbgs()); llvm::dbgs() << 
"\n";
 
  734               llvm::dbgs() << 
"  callee " << Callee.CDecl << 
" canonical " 
  735                            << Callee.CDecl->getCanonicalDecl() << 
"\n";);
 
  743      if (!IsInferencePossible ||
 
  745        if (Callee.FuncType == SpecialFuncType::None)
 
  746          PFA.checkAddViolation(Inferring,
 
  747                                {Effect, ViolationID::CallsDeclWithoutEffect,
 
  748                                 VSite, CallLoc, Callee.CDecl});
 
  750          PFA.checkAddViolation(
 
  752              {Effect, ViolationID::AllocatesMemory, VSite, CallLoc});
 
  755        PFA.addUnverifiedDirectCall(Callee.CDecl, CallLoc, VSite);
 
  760      Check1Effect(Effect, 
false);
 
  763      Check1Effect(Effect, 
true);
 
  769  enum CallableDeclKind {
 
  775    CDK_MemberInitializer,
 
  781  static CallableDeclKind GetCallableDeclKind(
const Decl *D,
 
  782                                              const Violation *
V) {
 
  784        V->Site.kind() == ViolationSite::Kind::MemberInitializer)
 
  785      return CDK_MemberInitializer;
 
  788    if (
auto *Method = dyn_cast<CXXMethodDecl>(D)) {
 
  790        return CDK_Constructor;
 
  792        return CDK_Destructor;
 
  806    auto MaybeAddTemplateNote = [&](
const Decl *D) {
 
  807      if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
 
  811                 diag::note_func_effect_from_template);
 
  818    enum { Indirect_VirtualMethod, Indirect_FunctionPtr };
 
  820    auto MaybeAddSiteContext = [&](
const Decl *D, 
const Violation &
V) {
 
  823      if (
V.Site.kind() == ViolationSite::Kind::MemberInitializer) {
 
  824        unsigned ImplicitCtor = 0;
 
  825        if (
auto *Ctor = dyn_cast<CXXConstructorDecl>(D);
 
  826            Ctor && Ctor->isImplicit())
 
  834      else if (
V.Site.kind() == ViolationSite::Kind::DefaultArgExpr)
 
  835        S.
Diag(
V.Site.defaultArgExpr()->getUsedLocation(),
 
  836               diag::note_in_evaluating_default_argument);
 
  840    for (
const Violation &Viol1 : Viols) {
 
  841      StringRef effectName = Viol1.Effect.name();
 
  843      case ViolationID::None:
 
  844      case ViolationID::DeclDisallowsInference: 
 
  846        llvm_unreachable(
"Unexpected violation kind");
 
  848      case ViolationID::AllocatesMemory:
 
  849      case ViolationID::ThrowsOrCatchesExceptions:
 
  850      case ViolationID::HasStaticLocalVariable:
 
  851      case ViolationID::AccessesThreadLocalVariable:
 
  852      case ViolationID::AccessesObjCMethodOrProperty:
 
  853        S.
Diag(Viol1.Loc, diag::warn_func_effect_violation)
 
  854            << GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName
 
  855            << Viol1.diagnosticSelectIndex();
 
  856        MaybeAddSiteContext(CInfo.CDecl, Viol1);
 
  857        MaybeAddTemplateNote(CInfo.CDecl);
 
  859      case ViolationID::CallsExprWithoutEffect:
 
  860        S.
Diag(Viol1.Loc, diag::warn_func_effect_calls_expr_without_effect)
 
  861            << GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName;
 
  862        MaybeAddSiteContext(CInfo.CDecl, Viol1);
 
  863        MaybeAddTemplateNote(CInfo.CDecl);
 
  866      case ViolationID::CallsDeclWithoutEffect: {
 
  867        CallableInfo CalleeInfo(*Viol1.Callee);
 
  868        std::string CalleeName = CalleeInfo.getNameForDiagnostic(S);
 
  870        S.
Diag(Viol1.Loc, diag::warn_func_effect_calls_func_without_effect)
 
  871            << GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName
 
  872            << GetCallableDeclKind(CalleeInfo.CDecl, 
nullptr) << CalleeName;
 
  873        MaybeAddSiteContext(CInfo.CDecl, Viol1);
 
  874        MaybeAddTemplateNote(CInfo.CDecl);
 
  878        for (
const Decl *Callee = Viol1.Callee; Callee != 
nullptr;) {
 
  879          std::optional<CallableInfo> MaybeNextCallee;
 
  880          CompleteFunctionAnalysis *Completed =
 
  881              DeclAnalysis.completedAnalysisForDecl(CalleeInfo.CDecl);
 
  882          if (Completed == 
nullptr) {
 
  888            CallableType CType = CalleeInfo.type();
 
  889            if (CType == CallableType::Virtual)
 
  890              S.
Diag(Callee->getLocation(),
 
  891                     diag::note_func_effect_call_indirect)
 
  892                  << Indirect_VirtualMethod << effectName;
 
  893            else if (CType == CallableType::Unknown)
 
  894              S.
Diag(Callee->getLocation(),
 
  895                     diag::note_func_effect_call_indirect)
 
  896                  << Indirect_FunctionPtr << effectName;
 
  897            else if (CalleeInfo.Effects.
contains(Viol1.Effect.oppositeKind()))
 
  898              S.
Diag(Callee->getLocation(),
 
  899                     diag::note_func_effect_call_disallows_inference)
 
  900                  << GetCallableDeclKind(CInfo.CDecl, 
nullptr) << effectName
 
  902            else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(Callee);
 
  906              S.
Diag(Callee->getLocation(), diag::note_func_effect_call_extern)
 
  911          const Violation *PtrViol2 =
 
  912              Completed->firstViolationForEffect(Viol1.Effect);
 
  913          if (PtrViol2 == 
nullptr)
 
  916          const Violation &Viol2 = *PtrViol2;
 
  918          case ViolationID::None:
 
  919            llvm_unreachable(
"Unexpected violation kind");
 
  921          case ViolationID::DeclDisallowsInference:
 
  922            S.
Diag(Viol2.Loc, diag::note_func_effect_call_disallows_inference)
 
  923                << GetCallableDeclKind(CalleeInfo.CDecl, 
nullptr) << effectName
 
  924                << Viol2.CalleeEffectPreventingInference->name();
 
  926          case ViolationID::CallsExprWithoutEffect:
 
  927            S.
Diag(Viol2.Loc, diag::note_func_effect_call_indirect)
 
  928                << Indirect_FunctionPtr << effectName;
 
  930          case ViolationID::AllocatesMemory:
 
  931          case ViolationID::ThrowsOrCatchesExceptions:
 
  932          case ViolationID::HasStaticLocalVariable:
 
  933          case ViolationID::AccessesThreadLocalVariable:
 
  934          case ViolationID::AccessesObjCMethodOrProperty:
 
  935            S.
Diag(Viol2.Loc, diag::note_func_effect_violation)
 
  936                << GetCallableDeclKind(CalleeInfo.CDecl, &Viol2) << effectName
 
  937                << Viol2.diagnosticSelectIndex();
 
  938            MaybeAddSiteContext(CalleeInfo.CDecl, Viol2);
 
  940          case ViolationID::CallsDeclWithoutEffect:
 
  941            MaybeNextCallee.emplace(*Viol2.Callee);
 
  942            S.
Diag(Viol2.Loc, diag::note_func_effect_calls_func_without_effect)
 
  943                << GetCallableDeclKind(CalleeInfo.CDecl, &Viol2) << effectName
 
  944                << GetCallableDeclKind(Viol2.Callee, 
nullptr)
 
  945                << MaybeNextCallee->getNameForDiagnostic(S);
 
  948          MaybeAddTemplateNote(Callee);
 
  949          Callee = Viol2.Callee;
 
  950          if (MaybeNextCallee) {
 
  951            CalleeInfo = *MaybeNextCallee;
 
  952            CalleeName = CalleeInfo.getNameForDiagnostic(S);
 
  970    PendingFunctionAnalysis &CurrentFunction;
 
  971    CallableInfo &CurrentCaller;
 
  973    const Expr *TrailingRequiresClause = 
nullptr;
 
  974    const Expr *NoexceptExpr = 
nullptr;
 
  976    FunctionBodyASTVisitor(Analyzer &Outer,
 
  977                           PendingFunctionAnalysis &CurrentFunction,
 
  978                           CallableInfo &CurrentCaller)
 
  979        : Outer(Outer), CurrentFunction(CurrentFunction),
 
  980          CurrentCaller(CurrentCaller) {
 
  981      ShouldVisitImplicitCode = 
true;
 
  982      ShouldWalkTypesOfTypeLocs = 
false;
 
  989      if (
auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl))
 
  990        followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor);
 
  992      if (
auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl)) {
 
 1004              NoexceptExpr = FPT->getNoexceptExpr();
 
 1009      TraverseDecl(
const_cast<Decl *
>(CurrentCaller.CDecl));
 
 1019                                   const Decl *Callee = 
nullptr) {
 
 1022      for (
FunctionEffect Effect : CurrentFunction.DeclaredVerifiableEffects) {
 
 1023        if (Effect.
flags() & Flag) {
 
 1024          addViolation(
false, Effect, VID, Loc, Callee);
 
 1031        if (Effect.
flags() & Flag)
 
 1032          addViolation(
true, Effect, VID, Loc, Callee);
 
 1035    void addViolation(
bool Inferring, 
FunctionEffect Effect, ViolationID VID,
 
 1037      CurrentFunction.checkAddViolation(
 
 1038          Inferring, Violation(Effect, VID, VSite, Loc, Callee));
 
 1046      if (
const auto *FD = dyn_cast<FunctionDecl>(CI.CDecl)) {
 
 1048          CI.Effects = getBuiltinFunctionEffects(BuiltinID);
 
 1049          if (CI.Effects.
empty()) {
 
 1066      Outer.followCall(CurrentCaller, CurrentFunction, CI, CallLoc,
 
 1074        CalleeEffects.
insert(Effects);
 
 1078                false, CalleeEffects))
 
 1079          addViolation(Inferring, Effect, ViolationID::CallsExprWithoutEffect,
 
 1080                       Call->getBeginLoc());
 
 1083      for (
FunctionEffect Effect : CurrentFunction.DeclaredVerifiableEffects)
 
 1084        Check1Effect(Effect, 
false);
 
 1087        Check1Effect(Effect, 
true);
 
 1096        followTypeDtor(Field->getType(), DtorLoc);
 
 1098      if (
const auto *Class = dyn_cast<CXXRecordDecl>(Rec))
 
 1100          followTypeDtor(
Base.getType(), DtorLoc);
 
 1115            CallableInfo CI(*Dtor);
 
 1116            followCall(CI, CallSite);
 
 1126                                ViolationID::ThrowsOrCatchesExceptions,
 
 1133                                ViolationID::ThrowsOrCatchesExceptions,
 
 1140                                ViolationID::ThrowsOrCatchesExceptions,
 
 1147                                ViolationID::ThrowsOrCatchesExceptions,
 
 1154                                ViolationID::ThrowsOrCatchesExceptions,
 
 1161                                ViolationID::AccessesObjCMethodOrProperty,
 
 1171                                ViolationID::AccessesObjCMethodOrProperty,
 
 1181                                ViolationID::AccessesObjCMethodOrProperty,
 
 1188                                ViolationID::ThrowsOrCatchesExceptions,
 
 1194      LLVM_DEBUG(llvm::dbgs()
 
 1195                     << 
"VisitCallExpr : " 
 1199      Expr *CalleeExpr = 
Call->getCallee();
 
 1201        CallableInfo CI(*Callee);
 
 1202        followCall(CI, 
Call->getBeginLoc());
 
 1217    bool VisitVarDecl(
VarDecl *Var)
 override {
 
 1218      LLVM_DEBUG(llvm::dbgs()
 
 1219                     << 
"VisitVarDecl : " 
 1225                                  ViolationID::HasStaticLocalVariable,
 
 1238        CallableInfo CI(*FD, SpecialFuncType::OperatorNew);
 
 1239        followCall(CI, 
New->getBeginLoc());
 
 1254        CallableInfo CI(*FD, SpecialFuncType::OperatorDelete);
 
 1255        followCall(CI, 
Delete->getBeginLoc());
 
 1264      LLVM_DEBUG(llvm::dbgs() << 
"VisitCXXConstructExpr : " 
 1272      CallableInfo CI(*Ctor);
 
 1278    bool TraverseStmt(
Stmt *Statement)
 override {
 
 1284      if (Statement != TrailingRequiresClause && Statement != NoexceptExpr)
 
 1290      ViolationSite PrevVS = VSite;
 
 1291      if (
Init->isAnyMemberInitializer())
 
 1292        VSite.setKind(ViolationSite::Kind::MemberInitializer);
 
 1300      LLVM_DEBUG(llvm::dbgs()
 
 1301                     << 
"TraverseCXXDefaultArgExpr : " 
 1305      ViolationSite PrevVS = VSite;
 
 1306      if (VSite.kind() == ViolationSite::Kind::Default)
 
 1307        VSite = ViolationSite{E};
 
 1309      bool Result = DynamicRecursiveASTVisitor::TraverseCXXDefaultArgExpr(E);
 
 1314    bool TraverseLambdaExpr(
LambdaExpr *Lambda)
 override {
 
 1320      for (
unsigned I = 0, N = Lambda->
capture_size(); I < N; ++I)
 
 1327    bool TraverseBlockExpr(
BlockExpr * )
 override {
 
 1335      if (
const auto *Var = dyn_cast<VarDecl>(Val)) {
 
 1340                                    ViolationID::AccessesThreadLocalVariable,
 
 1356                                   bool TraverseQualifier)
 override {
 
 1361                                 bool TraverseQualifier)
 override {
 
 1369    bool TraverseCXXTypeidExpr(
CXXTypeidExpr *Node)
 override { 
return true; }
 
 1378Analyzer::AnalysisMap::~AnalysisMap() {
 
 1379  for (
const auto &Item : *
this) {
 
 1380    FuncAnalysisPtr AP = Item.second;
 
 1381    if (
auto *PFA = dyn_cast<PendingFunctionAnalysis *>(AP))
 
 1402    Diag(NewAttrLoc, diag::err_attributes_are_not_compatible)
 
 1404        << (
"'" + PrevEC.description() + 
"'") << 
false;
 
 1415    if (PrevEC.Cond.getCondition() != 
nullptr)
 
 1421    if (PrevEC.Effect.oppositeKind() == NewKind)
 
 
 1442    Diag(NewLoc, diag::warn_conflicting_func_effects)
 
 1443        << Conflict.Kept.description() << Conflict.Rejected.description();
 
 1444    Diag(OldLoc, diag::note_previous_declaration);
 
 
 1456  if (
Diags.getIgnoreAllWarnings() ||
 
 1457      (
Diags.getSuppressSystemWarnings() &&
 
 
 1478  bool AnyVerifiable = 
false;
 
 1482      AnyVerifiable = 
true;
 
 
 1495  Analyzer{*
this}.run(*TU);
 
 
 1508    if (POld == OldEnd) {
 
 1512    } 
else if (PNew == NewEnd)
 
 1540    } 
else if (cmp > 0) {
 
 1545                                   std::nullopt, 
New});
 
 
 1563      for (
const auto &CFE : SrcFX) {
 
 1588  llvm_unreachable(
"unknown effect kind");
 
 
 1612  llvm_unreachable(
"unknown effect kind");
 
 
 1642  llvm_unreachable(
"unknown effect kind");
 
 
static bool isNoexcept(const FunctionDecl *FD)
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static bool AllocatesMemory(QualType T)
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.
static bool isExternC(const NamedDecl *ND)
static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR, AnalysisManager &AM, const ObjCAutoreleaseWriteChecker *Checker)
Defines the SourceManager interface.
Defines the Objective-C statement AST node classes.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Represents a base class of a C++ class.
CXXCatchStmt - This represents a C++ catch block.
SourceLocation getCatchLoc() const
Represents a call to a C++ constructor.
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Represents a C++ constructor within a class.
Represents a C++ base or member initializer.
A default argument (C++ [dcl.fct.default]).
SourceLocation getUsedLocation() const
Retrieve the location where this default argument was actually used.
Represents a delete expression for memory deallocation and destructor calls, e.g.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
A C++ throw-expression (C++ [except.throw]).
SourceLocation getThrowLoc() const
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
A reference to a declared variable, function, enum, etc.
SourceLocation getLocation() const
Decl - This represents one declaration (or definition), e.g.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
TypeSourceInfo * getTypeSourceInfo() const
virtual bool TraverseConstructorInitializer(MaybeConst< CXXCtorInitializer > *Init)
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
Expr * getCondition() const
This represents one expression.
Decl * getReferencedDeclOfCallee()
Represents a member of a struct/union/class.
Represents a function declaration or definition.
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
FunctionDecl * getTemplateInstantiationPattern(bool ForDefinition=true) const
Retrieve the function declaration from which this function could be instantiated, if it is an instant...
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isDeleted() const
Whether this function has been deleted.
FunctionEffectsRef getFunctionEffects() const
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
FunctionDecl * getDefinition()
Get the definition for this declaration.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const override
Appends a human-readable name for this declaration into the given stream.
bool willHaveBody() const
True if this function will eventually have a body, once it's fully parsed.
A mutable set of FunctionEffect::Kind.
static FunctionEffectKindSet difference(FunctionEffectKindSet LHS, FunctionEffectKindSet RHS)
bool contains(const FunctionEffect::Kind EK) const
void dump(llvm::raw_ostream &OS) const
void insert(FunctionEffect Effect)
SmallVector< Conflict > Conflicts
Represents an abstract function effect, using just an enumeration describing its kind.
Kind kind() const
The kind of the effect.
unsigned Flags
Flags describing some behaviors of the effect.
@ FE_ExcludeStaticLocalVars
@ FE_ExcludeThreadLocalVars
@ FE_ExcludeObjCMessageSend
Kind
Identifies the particular effect.
Flags flags() const
Flags describing some behaviors of the effect.
bool shouldDiagnoseFunctionCall(bool Direct, FunctionEffectKindSet CalleeFX) const
StringRef name() const
The description printed in diagnostics, e.g. 'nonblocking'.
An immutable set of FunctionEffects and possibly conditions attached to them.
FunctionEffectIterator< FunctionEffectsRef > iterator
static FunctionEffectsRef get(QualType QT)
Extract the effects from a Type if it is a function, block, or member function pointer,...
Represents a prototype with parameter type info, e.g.
Represents a C11 generic selection.
Expr * getResultExpr()
Return the result expression of this controlling expression.
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
capture_iterator capture_begin() const
Retrieve an iterator pointing to the first lambda capture.
unsigned capture_size() const
Determine the number of captures in this lambda.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
Represents Objective-C's @catch statement.
SourceLocation getAtCatchLoc() const
Represents Objective-C's @finally statement.
SourceLocation getAtFinallyLoc() const
Represents Objective-C's @synchronized statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Represents Objective-C's @throw statement.
SourceLocation getThrowLoc() const LLVM_READONLY
Represents Objective-C's @autoreleasepool Statement.
SourceLocation getBeginLoc() const LLVM_READONLY
An expression that sends a message to the given Objective-C object or class.
SourceLocation getBeginLoc() const LLVM_READONLY
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
field_range fields() const
SourceLocation getExceptLoc() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Sema - This implements semantic analysis and AST building for C.
void addDeclWithEffects(const Decl *D, const FunctionEffectsRef &FX)
Unconditionally add a Decl to DeclsWithEfffectsToVerify.
FunctionEffectKindSet AllEffectsToVerify
The union of all effects present on DeclsWithEffectsToVerify.
ASTContext & getASTContext() const
SmallVector< const Decl * > DeclsWithEffectsToVerify
All functions/lambdas/blocks which have bodies and which have a non-empty FunctionEffectsRef to be ve...
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
const LangOptions & getLangOpts() const
void maybeAddDeclWithEffects(FuncOrBlockDecl *D)
Inline checks from the start of maybeAddDeclWithEffects, to minimize performance impact on code not u...
void performFunctionEffectAnalysis(TranslationUnitDecl *TU)
SourceManager & getSourceManager() const
void diagnoseFunctionEffectMergeConflicts(const FunctionEffectSet::Conflicts &Errs, SourceLocation NewLoc, SourceLocation OldLoc)
bool diagnoseConflictingFunctionEffect(const FunctionEffectsRef &FX, const FunctionEffectWithCondition &EC, SourceLocation NewAttrLoc)
Warn and return true if adding a function effect to a set would create a conflict.
bool hasUncompilableErrorOccurred() const
Whether uncompilable error has occurred.
SourceManager & SourceMgr
DiagnosticsEngine & Diags
Encodes a location in the source.
std::string printToString(const SourceManager &SM) const
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
Stmt - This represents one statement.
The top declaration context.
T getAs() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
A container of type source information.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
TLSKind getTLSKind() const
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
@ TLS_None
Not a TLS variable.
A static requirement that can be used in a requires-expression to check properties of types and expre...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
@ Delete
'delete' clause, allowed on the 'exit data' construct.
@ Incompatible
Incompatible - We reject this conversion outright, it is invalid to represent it in the AST.
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
@ None
The alignment was not explicit in code.
const Expr * ConstraintExpr
A FunctionEffect plus a potential boolean expression determining whether the effect is declared (e....
std::string description() const
Return a textual description of the effect, and its condition, if any.
FunctionEffectDiffVector(const FunctionEffectsRef &Old, const FunctionEffectsRef &New)
Caller should short-circuit by checking for equality first.
bool shouldDiagnoseConversion(QualType SrcType, const FunctionEffectsRef &SrcFX, QualType DstType, const FunctionEffectsRef &DstFX) const
Return true if adding or removing the effect as part of a type conversion should generate a diagnosti...
bool shouldDiagnoseRedeclaration(const FunctionDecl &OldFunction, const FunctionEffectsRef &OldFX, const FunctionDecl &NewFunction, const FunctionEffectsRef &NewFX) const
Return true if adding or removing the effect in a redeclaration should generate a diagnostic.
OverrideResult shouldDiagnoseMethodOverride(const CXXMethodDecl &OldMethod, const FunctionEffectsRef &OldFX, const CXXMethodDecl &NewMethod, const FunctionEffectsRef &NewFX) const
Return true if adding or removing the effect in a C++ virtual method override should generate a diagn...
OverrideResult
Describes the result of effects differing between a base class's virtual method and an overriding met...
FunctionEffect::Kind EffectKind