Path: blob/main/contrib/llvm-project/clang/lib/Sema/SemaFunctionEffects.cpp
213765 views
//=== SemaFunctionEffects.cpp - Sema handling of function effects ---------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements Sema handling of function effects.9//10//===----------------------------------------------------------------------===//1112#include "clang/AST/Decl.h"13#include "clang/AST/DeclCXX.h"14#include "clang/AST/DynamicRecursiveASTVisitor.h"15#include "clang/AST/ExprObjC.h"16#include "clang/AST/Stmt.h"17#include "clang/AST/StmtObjC.h"18#include "clang/AST/Type.h"19#include "clang/Basic/SourceManager.h"20#include "clang/Sema/SemaInternal.h"2122#define DEBUG_TYPE "effectanalysis"2324using namespace clang;2526namespace {2728enum class ViolationID : uint8_t {29None = 0, // Sentinel for an empty Violation.30// These first 5 map to a %select{} in one of several FunctionEffects31// diagnostics, e.g. warn_func_effect_violation.32BaseDiagnosticIndex,33AllocatesMemory = BaseDiagnosticIndex,34ThrowsOrCatchesExceptions,35HasStaticLocalVariable,36AccessesThreadLocalVariable,37AccessesObjCMethodOrProperty,3839// These only apply to callees, where the analysis stops at the Decl.40DeclDisallowsInference,4142// These both apply to indirect calls. The difference is that sometimes43// we have an actual Decl (generally a variable) which is the function44// pointer being called, and sometimes, typically due to a cast, we only45// have an expression.46CallsDeclWithoutEffect,47CallsExprWithoutEffect,48};4950// Information about the AST context in which a violation was found, so51// that diagnostics can point to the correct source.52class ViolationSite {53public:54enum class Kind : uint8_t {55Default, // Function body.56MemberInitializer,57DefaultArgExpr58};5960private:61llvm::PointerIntPair<CXXDefaultArgExpr *, 2, Kind> Impl;6263public:64ViolationSite() = default;6566explicit ViolationSite(CXXDefaultArgExpr *E)67: Impl(E, Kind::DefaultArgExpr) {}6869Kind kind() const { return static_cast<Kind>(Impl.getInt()); }70CXXDefaultArgExpr *defaultArgExpr() const { return Impl.getPointer(); }7172void setKind(Kind K) { Impl.setPointerAndInt(nullptr, K); }73};7475// Represents a violation of the rules, potentially for the entire duration of76// the analysis phase, in order to refer to it when explaining why a caller has77// been made unsafe by a callee. Can be transformed into either a Diagnostic78// (warning or a note), depending on whether the violation pertains to a79// function failing to be verifed as holding an effect vs. a function failing to80// be inferred as holding that effect.81struct Violation {82FunctionEffect Effect;83std::optional<FunctionEffect>84CalleeEffectPreventingInference; // Only for certain IDs; can be nullopt.85ViolationID ID = ViolationID::None;86ViolationSite Site;87SourceLocation Loc;88const Decl *Callee =89nullptr; // Only valid for ViolationIDs Calls{Decl,Expr}WithoutEffect.9091Violation(FunctionEffect Effect, ViolationID ID, ViolationSite VS,92SourceLocation Loc, const Decl *Callee = nullptr,93std::optional<FunctionEffect> CalleeEffect = std::nullopt)94: Effect(Effect), CalleeEffectPreventingInference(CalleeEffect), ID(ID),95Site(VS), Loc(Loc), Callee(Callee) {}9697unsigned diagnosticSelectIndex() const {98return unsigned(ID) - unsigned(ViolationID::BaseDiagnosticIndex);99}100};101102enum class SpecialFuncType : uint8_t { None, OperatorNew, OperatorDelete };103enum class CallableType : uint8_t {104// Unknown: probably function pointer.105Unknown,106Function,107Virtual,108Block109};110111// Return whether a function's effects CAN be verified.112// The question of whether it SHOULD be verified is independent.113static bool functionIsVerifiable(const FunctionDecl *FD) {114if (FD->isTrivial()) {115// Otherwise `struct x { int a; };` would have an unverifiable default116// constructor.117return true;118}119return FD->hasBody();120}121122static bool isNoexcept(const FunctionDecl *FD) {123const auto *FPT = FD->getType()->getAs<FunctionProtoType>();124return FPT && (FPT->isNothrow() || FD->hasAttr<NoThrowAttr>());125}126127// This list is probably incomplete.128// FIXME: Investigate:129// __builtin_eh_return?130// __builtin_allow_runtime_check?131// __builtin_unwind_init and other similar things that sound exception-related.132// va_copy?133// coroutines?134static FunctionEffectKindSet getBuiltinFunctionEffects(unsigned BuiltinID) {135FunctionEffectKindSet Result;136137switch (BuiltinID) {138case 0: // Not builtin.139default: // By default, builtins have no known effects.140break;141142// These allocate/deallocate heap memory.143case Builtin::ID::BI__builtin_calloc:144case Builtin::ID::BI__builtin_malloc:145case Builtin::ID::BI__builtin_realloc:146case Builtin::ID::BI__builtin_free:147case Builtin::ID::BI__builtin_operator_delete:148case Builtin::ID::BI__builtin_operator_new:149case Builtin::ID::BIaligned_alloc:150case Builtin::ID::BIcalloc:151case Builtin::ID::BImalloc:152case Builtin::ID::BImemalign:153case Builtin::ID::BIrealloc:154case Builtin::ID::BIfree:155156case Builtin::ID::BIfopen:157case Builtin::ID::BIpthread_create:158case Builtin::ID::BI_Block_object_dispose:159Result.insert(FunctionEffect(FunctionEffect::Kind::Allocating));160break;161162// These block in some other way than allocating memory.163// longjmp() and friends are presumed unsafe because they are the moral164// equivalent of throwing a C++ exception, which is unsafe.165case Builtin::ID::BIlongjmp:166case Builtin::ID::BI_longjmp:167case Builtin::ID::BIsiglongjmp:168case Builtin::ID::BI__builtin_longjmp:169case Builtin::ID::BIobjc_exception_throw:170171// Objective-C runtime.172case Builtin::ID::BIobjc_msgSend:173case Builtin::ID::BIobjc_msgSend_fpret:174case Builtin::ID::BIobjc_msgSend_fp2ret:175case Builtin::ID::BIobjc_msgSend_stret:176case Builtin::ID::BIobjc_msgSendSuper:177case Builtin::ID::BIobjc_getClass:178case Builtin::ID::BIobjc_getMetaClass:179case Builtin::ID::BIobjc_enumerationMutation:180case Builtin::ID::BIobjc_assign_ivar:181case Builtin::ID::BIobjc_assign_global:182case Builtin::ID::BIobjc_sync_enter:183case Builtin::ID::BIobjc_sync_exit:184case Builtin::ID::BINSLog:185case Builtin::ID::BINSLogv:186187// stdio.h188case Builtin::ID::BIfread:189case Builtin::ID::BIfwrite:190191// stdio.h: printf family.192case Builtin::ID::BIprintf:193case Builtin::ID::BI__builtin_printf:194case Builtin::ID::BIfprintf:195case Builtin::ID::BIsnprintf:196case Builtin::ID::BIsprintf:197case Builtin::ID::BIvprintf:198case Builtin::ID::BIvfprintf:199case Builtin::ID::BIvsnprintf:200case Builtin::ID::BIvsprintf:201202// stdio.h: scanf family.203case Builtin::ID::BIscanf:204case Builtin::ID::BIfscanf:205case Builtin::ID::BIsscanf:206case Builtin::ID::BIvscanf:207case Builtin::ID::BIvfscanf:208case Builtin::ID::BIvsscanf:209Result.insert(FunctionEffect(FunctionEffect::Kind::Blocking));210break;211}212213return Result;214}215216// Transitory, more extended information about a callable, which can be a217// function, block, or function pointer.218struct CallableInfo {219// CDecl holds the function's definition, if any.220// FunctionDecl if CallableType::Function or Virtual221// BlockDecl if CallableType::Block222const Decl *CDecl;223224// Remember whether the callable is a function, block, virtual method,225// or (presumed) function pointer.226CallableType CType = CallableType::Unknown;227228// Remember whether the callable is an operator new or delete function,229// so that calls to them are reported more meaningfully, as memory230// allocations.231SpecialFuncType FuncType = SpecialFuncType::None;232233// We inevitably want to know the callable's declared effects, so cache them.234FunctionEffectKindSet Effects;235236CallableInfo(const Decl &CD, SpecialFuncType FT = SpecialFuncType::None)237: CDecl(&CD), FuncType(FT) {238FunctionEffectsRef DeclEffects;239if (auto *FD = dyn_cast<FunctionDecl>(CDecl)) {240// Use the function's definition, if any.241if (const FunctionDecl *Def = FD->getDefinition())242CDecl = FD = Def;243CType = CallableType::Function;244if (auto *Method = dyn_cast<CXXMethodDecl>(FD);245Method && Method->isVirtual())246CType = CallableType::Virtual;247DeclEffects = FD->getFunctionEffects();248} else if (auto *BD = dyn_cast<BlockDecl>(CDecl)) {249CType = CallableType::Block;250DeclEffects = BD->getFunctionEffects();251} else if (auto *VD = dyn_cast<ValueDecl>(CDecl)) {252// ValueDecl is function, enum, or variable, so just look at its type.253DeclEffects = FunctionEffectsRef::get(VD->getType());254}255Effects = FunctionEffectKindSet(DeclEffects);256}257258CallableType type() const { return CType; }259260bool isCalledDirectly() const {261return CType == CallableType::Function || CType == CallableType::Block;262}263264bool isVerifiable() const {265switch (CType) {266case CallableType::Unknown:267case CallableType::Virtual:268return false;269case CallableType::Block:270return true;271case CallableType::Function:272return functionIsVerifiable(dyn_cast<FunctionDecl>(CDecl));273}274llvm_unreachable("undefined CallableType");275}276277/// Generate a name for logging and diagnostics.278std::string getNameForDiagnostic(Sema &S) const {279std::string Name;280llvm::raw_string_ostream OS(Name);281282if (auto *FD = dyn_cast<FunctionDecl>(CDecl))283FD->getNameForDiagnostic(OS, S.getPrintingPolicy(),284/*Qualified=*/true);285else if (auto *BD = dyn_cast<BlockDecl>(CDecl))286OS << "(block " << BD->getBlockManglingNumber() << ")";287else if (auto *VD = dyn_cast<NamedDecl>(CDecl))288VD->printQualifiedName(OS);289return Name;290}291};292293// ----------294// Map effects to single Violations, to hold the first (of potentially many)295// violations pertaining to an effect, per function.296class EffectToViolationMap {297// Since we currently only have a tiny number of effects (typically no more298// than 1), use a SmallVector with an inline capacity of 1. Since it299// is often empty, use a unique_ptr to the SmallVector.300// Note that Violation itself contains a FunctionEffect which is the key.301// FIXME: Is there a way to simplify this using existing data structures?302using ImplVec = llvm::SmallVector<Violation, 1>;303std::unique_ptr<ImplVec> Impl;304305public:306// Insert a new Violation if we do not already have one for its effect.307void maybeInsert(const Violation &Viol) {308if (Impl == nullptr)309Impl = std::make_unique<ImplVec>();310else if (lookup(Viol.Effect) != nullptr)311return;312313Impl->push_back(Viol);314}315316const Violation *lookup(FunctionEffect Key) {317if (Impl == nullptr)318return nullptr;319320auto *Iter = llvm::find_if(321*Impl, [&](const auto &Item) { return Item.Effect == Key; });322return Iter != Impl->end() ? &*Iter : nullptr;323}324325size_t size() const { return Impl ? Impl->size() : 0; }326};327328// ----------329// State pertaining to a function whose AST is walked and whose effect analysis330// is dependent on a subsequent analysis of other functions.331class PendingFunctionAnalysis {332friend class CompleteFunctionAnalysis;333334public:335struct DirectCall {336const Decl *Callee;337SourceLocation CallLoc;338// Not all recursive calls are detected, just enough339// to break cycles.340bool Recursed = false;341ViolationSite VSite;342343DirectCall(const Decl *D, SourceLocation CallLoc, ViolationSite VSite)344: Callee(D), CallLoc(CallLoc), VSite(VSite) {}345};346347// We always have two disjoint sets of effects to verify:348// 1. Effects declared explicitly by this function.349// 2. All other inferrable effects needing verification.350FunctionEffectKindSet DeclaredVerifiableEffects;351FunctionEffectKindSet EffectsToInfer;352353private:354// Violations pertaining to the function's explicit effects.355SmallVector<Violation, 0> ViolationsForExplicitEffects;356357// Violations pertaining to other, non-explicit, inferrable effects.358EffectToViolationMap InferrableEffectToFirstViolation;359360// These unverified direct calls are what keeps the analysis "pending",361// until the callees can be verified.362SmallVector<DirectCall, 0> UnverifiedDirectCalls;363364public:365PendingFunctionAnalysis(Sema &S, const CallableInfo &CInfo,366FunctionEffectKindSet AllInferrableEffectsToVerify)367: DeclaredVerifiableEffects(CInfo.Effects) {368// Check for effects we are not allowed to infer.369FunctionEffectKindSet InferrableEffects;370371for (FunctionEffect effect : AllInferrableEffectsToVerify) {372std::optional<FunctionEffect> ProblemCalleeEffect =373effect.effectProhibitingInference(*CInfo.CDecl, CInfo.Effects);374if (!ProblemCalleeEffect)375InferrableEffects.insert(effect);376else {377// Add a Violation for this effect if a caller were to378// try to infer it.379InferrableEffectToFirstViolation.maybeInsert(Violation(380effect, ViolationID::DeclDisallowsInference, ViolationSite{},381CInfo.CDecl->getLocation(), nullptr, ProblemCalleeEffect));382}383}384// InferrableEffects is now the set of inferrable effects which are not385// prohibited.386EffectsToInfer = FunctionEffectKindSet::difference(387InferrableEffects, DeclaredVerifiableEffects);388}389390// Hide the way that Violations for explicitly required effects vs. inferred391// ones are handled differently.392void checkAddViolation(bool Inferring, const Violation &NewViol) {393if (!Inferring)394ViolationsForExplicitEffects.push_back(NewViol);395else396InferrableEffectToFirstViolation.maybeInsert(NewViol);397}398399void addUnverifiedDirectCall(const Decl *D, SourceLocation CallLoc,400ViolationSite VSite) {401UnverifiedDirectCalls.emplace_back(D, CallLoc, VSite);402}403404// Analysis is complete when there are no unverified direct calls.405bool isComplete() const { return UnverifiedDirectCalls.empty(); }406407const Violation *violationForInferrableEffect(FunctionEffect effect) {408return InferrableEffectToFirstViolation.lookup(effect);409}410411// Mutable because caller may need to set a DirectCall's Recursing flag.412MutableArrayRef<DirectCall> unverifiedCalls() {413assert(!isComplete());414return UnverifiedDirectCalls;415}416417ArrayRef<Violation> getSortedViolationsForExplicitEffects(SourceManager &SM) {418if (!ViolationsForExplicitEffects.empty())419llvm::sort(ViolationsForExplicitEffects,420[&SM](const Violation &LHS, const Violation &RHS) {421return SM.isBeforeInTranslationUnit(LHS.Loc, RHS.Loc);422});423return ViolationsForExplicitEffects;424}425426void dump(Sema &SemaRef, llvm::raw_ostream &OS) const {427OS << "Pending: Declared ";428DeclaredVerifiableEffects.dump(OS);429OS << ", " << ViolationsForExplicitEffects.size() << " violations; ";430OS << " Infer ";431EffectsToInfer.dump(OS);432OS << ", " << InferrableEffectToFirstViolation.size() << " violations";433if (!UnverifiedDirectCalls.empty()) {434OS << "; Calls: ";435for (const DirectCall &Call : UnverifiedDirectCalls) {436CallableInfo CI(*Call.Callee);437OS << " " << CI.getNameForDiagnostic(SemaRef);438}439}440OS << "\n";441}442};443444// ----------445class CompleteFunctionAnalysis {446// Current size: 2 pointers447public:448// Has effects which are both the declared ones -- not to be inferred -- plus449// ones which have been successfully inferred. These are all considered450// "verified" for the purposes of callers; any issue with verifying declared451// effects has already been reported and is not the problem of any caller.452FunctionEffectKindSet VerifiedEffects;453454private:455// This is used to generate notes about failed inference.456EffectToViolationMap InferrableEffectToFirstViolation;457458public:459// The incoming Pending analysis is consumed (member(s) are moved-from).460CompleteFunctionAnalysis(ASTContext &Ctx, PendingFunctionAnalysis &&Pending,461FunctionEffectKindSet DeclaredEffects,462FunctionEffectKindSet AllInferrableEffectsToVerify)463: VerifiedEffects(DeclaredEffects) {464for (FunctionEffect effect : AllInferrableEffectsToVerify)465if (Pending.violationForInferrableEffect(effect) == nullptr)466VerifiedEffects.insert(effect);467468InferrableEffectToFirstViolation =469std::move(Pending.InferrableEffectToFirstViolation);470}471472const Violation *firstViolationForEffect(FunctionEffect Effect) {473return InferrableEffectToFirstViolation.lookup(Effect);474}475476void dump(llvm::raw_ostream &OS) const {477OS << "Complete: Verified ";478VerifiedEffects.dump(OS);479OS << "; Infer ";480OS << InferrableEffectToFirstViolation.size() << " violations\n";481}482};483484// ==========485class Analyzer {486Sema &S;487488// Subset of Sema.AllEffectsToVerify489FunctionEffectKindSet AllInferrableEffectsToVerify;490491using FuncAnalysisPtr =492llvm::PointerUnion<PendingFunctionAnalysis *, CompleteFunctionAnalysis *>;493494// Map all Decls analyzed to FuncAnalysisPtr. Pending state is larger495// than complete state, so use different objects to represent them.496// The state pointers are owned by the container.497class AnalysisMap : llvm::DenseMap<const Decl *, FuncAnalysisPtr> {498using Base = llvm::DenseMap<const Decl *, FuncAnalysisPtr>;499500public:501~AnalysisMap();502503// Use non-public inheritance in order to maintain the invariant504// that lookups and insertions are via the canonical Decls.505506FuncAnalysisPtr lookup(const Decl *Key) const {507return Base::lookup(Key->getCanonicalDecl());508}509510FuncAnalysisPtr &operator[](const Decl *Key) {511return Base::operator[](Key->getCanonicalDecl());512}513514/// Shortcut for the case where we only care about completed analysis.515CompleteFunctionAnalysis *completedAnalysisForDecl(const Decl *D) const {516if (FuncAnalysisPtr AP = lookup(D);517isa_and_nonnull<CompleteFunctionAnalysis *>(AP))518return cast<CompleteFunctionAnalysis *>(AP);519return nullptr;520}521522void dump(Sema &SemaRef, llvm::raw_ostream &OS) {523OS << "\nAnalysisMap:\n";524for (const auto &item : *this) {525CallableInfo CI(*item.first);526const auto AP = item.second;527OS << item.first << " " << CI.getNameForDiagnostic(SemaRef) << " : ";528if (AP.isNull()) {529OS << "null\n";530} else if (auto *CFA = dyn_cast<CompleteFunctionAnalysis *>(AP)) {531OS << CFA << " ";532CFA->dump(OS);533} else if (auto *PFA = dyn_cast<PendingFunctionAnalysis *>(AP)) {534OS << PFA << " ";535PFA->dump(SemaRef, OS);536} else537llvm_unreachable("never");538}539OS << "---\n";540}541};542AnalysisMap DeclAnalysis;543544public:545Analyzer(Sema &S) : S(S) {}546547void run(const TranslationUnitDecl &TU) {548// Gather all of the effects to be verified to see what operations need to549// be checked, and to see which ones are inferrable.550for (FunctionEffect Effect : S.AllEffectsToVerify) {551const FunctionEffect::Flags Flags = Effect.flags();552if (Flags & FunctionEffect::FE_InferrableOnCallees)553AllInferrableEffectsToVerify.insert(Effect);554}555LLVM_DEBUG(llvm::dbgs() << "AllInferrableEffectsToVerify: ";556AllInferrableEffectsToVerify.dump(llvm::dbgs());557llvm::dbgs() << "\n";);558559// We can use DeclsWithEffectsToVerify as a stack for a560// depth-first traversal; there's no need for a second container. But first,561// reverse it, so when working from the end, Decls are verified in the order562// they are declared.563SmallVector<const Decl *> &VerificationQueue = S.DeclsWithEffectsToVerify;564std::reverse(VerificationQueue.begin(), VerificationQueue.end());565566while (!VerificationQueue.empty()) {567const Decl *D = VerificationQueue.back();568if (FuncAnalysisPtr AP = DeclAnalysis.lookup(D)) {569if (auto *Pending = dyn_cast<PendingFunctionAnalysis *>(AP)) {570// All children have been traversed; finish analysis.571finishPendingAnalysis(D, Pending);572}573VerificationQueue.pop_back();574continue;575}576577// Not previously visited; begin a new analysis for this Decl.578PendingFunctionAnalysis *Pending = verifyDecl(D);579if (Pending == nullptr) {580// Completed now.581VerificationQueue.pop_back();582continue;583}584585// Analysis remains pending because there are direct callees to be586// verified first. Push them onto the queue.587for (PendingFunctionAnalysis::DirectCall &Call :588Pending->unverifiedCalls()) {589FuncAnalysisPtr AP = DeclAnalysis.lookup(Call.Callee);590if (AP.isNull()) {591VerificationQueue.push_back(Call.Callee);592continue;593}594595// This indicates recursion (not necessarily direct). For the596// purposes of effect analysis, we can just ignore it since597// no effects forbid recursion.598assert(isa<PendingFunctionAnalysis *>(AP));599Call.Recursed = true;600}601}602}603604private:605// Verify a single Decl. Return the pending structure if that was the result,606// else null. This method must not recurse.607PendingFunctionAnalysis *verifyDecl(const Decl *D) {608CallableInfo CInfo(*D);609bool isExternC = false;610611if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))612isExternC = FD->getCanonicalDecl()->isExternCContext();613614// For C++, with non-extern "C" linkage only - if any of the Decl's declared615// effects forbid throwing (e.g. nonblocking) then the function should also616// be declared noexcept.617if (S.getLangOpts().CPlusPlus && !isExternC) {618for (FunctionEffect Effect : CInfo.Effects) {619if (!(Effect.flags() & FunctionEffect::FE_ExcludeThrow))620continue;621622bool IsNoexcept = false;623if (auto *FD = D->getAsFunction()) {624IsNoexcept = isNoexcept(FD);625} else if (auto *BD = dyn_cast<BlockDecl>(D)) {626if (auto *TSI = BD->getSignatureAsWritten()) {627auto *FPT = TSI->getType()->castAs<FunctionProtoType>();628IsNoexcept = FPT->isNothrow() || BD->hasAttr<NoThrowAttr>();629}630}631if (!IsNoexcept)632S.Diag(D->getBeginLoc(), diag::warn_perf_constraint_implies_noexcept)633<< GetCallableDeclKind(D, nullptr) << Effect.name();634break;635}636}637638// Build a PendingFunctionAnalysis on the stack. If it turns out to be639// complete, we'll have avoided a heap allocation; if it's incomplete, it's640// a fairly trivial move to a heap-allocated object.641PendingFunctionAnalysis FAnalysis(S, CInfo, AllInferrableEffectsToVerify);642643LLVM_DEBUG(llvm::dbgs()644<< "\nVerifying " << CInfo.getNameForDiagnostic(S) << " ";645FAnalysis.dump(S, llvm::dbgs()););646647FunctionBodyASTVisitor Visitor(*this, FAnalysis, CInfo);648649Visitor.run();650if (FAnalysis.isComplete()) {651completeAnalysis(CInfo, std::move(FAnalysis));652return nullptr;653}654// Move the pending analysis to the heap and save it in the map.655PendingFunctionAnalysis *PendingPtr =656new PendingFunctionAnalysis(std::move(FAnalysis));657DeclAnalysis[D] = PendingPtr;658LLVM_DEBUG(llvm::dbgs() << "inserted pending " << PendingPtr << "\n";659DeclAnalysis.dump(S, llvm::dbgs()););660return PendingPtr;661}662663// Consume PendingFunctionAnalysis, create with it a CompleteFunctionAnalysis,664// inserted in the container.665void completeAnalysis(const CallableInfo &CInfo,666PendingFunctionAnalysis &&Pending) {667if (ArrayRef<Violation> Viols =668Pending.getSortedViolationsForExplicitEffects(S.getSourceManager());669!Viols.empty())670emitDiagnostics(Viols, CInfo);671672CompleteFunctionAnalysis *CompletePtr = new CompleteFunctionAnalysis(673S.getASTContext(), std::move(Pending), CInfo.Effects,674AllInferrableEffectsToVerify);675DeclAnalysis[CInfo.CDecl] = CompletePtr;676LLVM_DEBUG(llvm::dbgs() << "inserted complete " << CompletePtr << "\n";677DeclAnalysis.dump(S, llvm::dbgs()););678}679680// Called after all direct calls requiring inference have been found -- or681// not. Repeats calls to FunctionBodyASTVisitor::followCall() but without682// the possibility of inference. Deletes Pending.683void finishPendingAnalysis(const Decl *D, PendingFunctionAnalysis *Pending) {684CallableInfo Caller(*D);685LLVM_DEBUG(llvm::dbgs() << "finishPendingAnalysis for "686<< Caller.getNameForDiagnostic(S) << " : ";687Pending->dump(S, llvm::dbgs()); llvm::dbgs() << "\n";);688for (const PendingFunctionAnalysis::DirectCall &Call :689Pending->unverifiedCalls()) {690if (Call.Recursed)691continue;692693CallableInfo Callee(*Call.Callee);694followCall(Caller, *Pending, Callee, Call.CallLoc,695/*AssertNoFurtherInference=*/true, Call.VSite);696}697completeAnalysis(Caller, std::move(*Pending));698delete Pending;699}700701// Here we have a call to a Decl, either explicitly via a CallExpr or some702// other AST construct. PFA pertains to the caller.703void followCall(const CallableInfo &Caller, PendingFunctionAnalysis &PFA,704const CallableInfo &Callee, SourceLocation CallLoc,705bool AssertNoFurtherInference, ViolationSite VSite) {706const bool DirectCall = Callee.isCalledDirectly();707708// Initially, the declared effects; inferred effects will be added.709FunctionEffectKindSet CalleeEffects = Callee.Effects;710711bool IsInferencePossible = DirectCall;712713if (DirectCall)714if (CompleteFunctionAnalysis *CFA =715DeclAnalysis.completedAnalysisForDecl(Callee.CDecl)) {716// Combine declared effects with those which may have been inferred.717CalleeEffects.insert(CFA->VerifiedEffects);718IsInferencePossible = false; // We've already traversed it.719}720721if (AssertNoFurtherInference) {722assert(!IsInferencePossible);723}724725if (!Callee.isVerifiable())726IsInferencePossible = false;727728LLVM_DEBUG(llvm::dbgs()729<< "followCall from " << Caller.getNameForDiagnostic(S)730<< " to " << Callee.getNameForDiagnostic(S)731<< "; verifiable: " << Callee.isVerifiable() << "; callee ";732CalleeEffects.dump(llvm::dbgs()); llvm::dbgs() << "\n";733llvm::dbgs() << " callee " << Callee.CDecl << " canonical "734<< Callee.CDecl->getCanonicalDecl() << "\n";);735736auto Check1Effect = [&](FunctionEffect Effect, bool Inferring) {737if (!Effect.shouldDiagnoseFunctionCall(DirectCall, CalleeEffects))738return;739740// If inference is not allowed, or the target is indirect (virtual741// method/function ptr?), generate a Violation now.742if (!IsInferencePossible ||743!(Effect.flags() & FunctionEffect::FE_InferrableOnCallees)) {744if (Callee.FuncType == SpecialFuncType::None)745PFA.checkAddViolation(Inferring,746{Effect, ViolationID::CallsDeclWithoutEffect,747VSite, CallLoc, Callee.CDecl});748else749PFA.checkAddViolation(750Inferring,751{Effect, ViolationID::AllocatesMemory, VSite, CallLoc});752} else {753// Inference is allowed and necessary; defer it.754PFA.addUnverifiedDirectCall(Callee.CDecl, CallLoc, VSite);755}756};757758for (FunctionEffect Effect : PFA.DeclaredVerifiableEffects)759Check1Effect(Effect, false);760761for (FunctionEffect Effect : PFA.EffectsToInfer)762Check1Effect(Effect, true);763}764765// Describe a callable Decl for a diagnostic.766// (Not an enum class because the value is always converted to an integer for767// use in a diagnostic.)768enum CallableDeclKind {769CDK_Function,770CDK_Constructor,771CDK_Destructor,772CDK_Lambda,773CDK_Block,774CDK_MemberInitializer,775};776777// Describe a call site or target using an enum mapping to a %select{}778// in a diagnostic, e.g. warn_func_effect_violation,779// warn_perf_constraint_implies_noexcept, and others.780static CallableDeclKind GetCallableDeclKind(const Decl *D,781const Violation *V) {782if (V != nullptr &&783V->Site.kind() == ViolationSite::Kind::MemberInitializer)784return CDK_MemberInitializer;785if (isa<BlockDecl>(D))786return CDK_Block;787if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {788if (isa<CXXConstructorDecl>(D))789return CDK_Constructor;790if (isa<CXXDestructorDecl>(D))791return CDK_Destructor;792const CXXRecordDecl *Rec = Method->getParent();793if (Rec->isLambda())794return CDK_Lambda;795}796return CDK_Function;797};798799// Should only be called when function's analysis is determined to be800// complete.801void emitDiagnostics(ArrayRef<Violation> Viols, const CallableInfo &CInfo) {802if (Viols.empty())803return;804805auto MaybeAddTemplateNote = [&](const Decl *D) {806if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {807while (FD != nullptr && FD->isTemplateInstantiation() &&808FD->getPointOfInstantiation().isValid()) {809S.Diag(FD->getPointOfInstantiation(),810diag::note_func_effect_from_template);811FD = FD->getTemplateInstantiationPattern();812}813}814};815816// For note_func_effect_call_indirect.817enum { Indirect_VirtualMethod, Indirect_FunctionPtr };818819auto MaybeAddSiteContext = [&](const Decl *D, const Violation &V) {820// If a violation site is a member initializer, add a note pointing to821// the constructor which invoked it.822if (V.Site.kind() == ViolationSite::Kind::MemberInitializer) {823unsigned ImplicitCtor = 0;824if (auto *Ctor = dyn_cast<CXXConstructorDecl>(D);825Ctor && Ctor->isImplicit())826ImplicitCtor = 1;827S.Diag(D->getLocation(), diag::note_func_effect_in_constructor)828<< ImplicitCtor;829}830831// If a violation site is a default argument expression, add a note832// pointing to the call site using the default argument.833else if (V.Site.kind() == ViolationSite::Kind::DefaultArgExpr)834S.Diag(V.Site.defaultArgExpr()->getUsedLocation(),835diag::note_in_evaluating_default_argument);836};837838// Top-level violations are warnings.839for (const Violation &Viol1 : Viols) {840StringRef effectName = Viol1.Effect.name();841switch (Viol1.ID) {842case ViolationID::None:843case ViolationID::DeclDisallowsInference: // Shouldn't happen844// here.845llvm_unreachable("Unexpected violation kind");846break;847case ViolationID::AllocatesMemory:848case ViolationID::ThrowsOrCatchesExceptions:849case ViolationID::HasStaticLocalVariable:850case ViolationID::AccessesThreadLocalVariable:851case ViolationID::AccessesObjCMethodOrProperty:852S.Diag(Viol1.Loc, diag::warn_func_effect_violation)853<< GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName854<< Viol1.diagnosticSelectIndex();855MaybeAddSiteContext(CInfo.CDecl, Viol1);856MaybeAddTemplateNote(CInfo.CDecl);857break;858case ViolationID::CallsExprWithoutEffect:859S.Diag(Viol1.Loc, diag::warn_func_effect_calls_expr_without_effect)860<< GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName;861MaybeAddSiteContext(CInfo.CDecl, Viol1);862MaybeAddTemplateNote(CInfo.CDecl);863break;864865case ViolationID::CallsDeclWithoutEffect: {866CallableInfo CalleeInfo(*Viol1.Callee);867std::string CalleeName = CalleeInfo.getNameForDiagnostic(S);868869S.Diag(Viol1.Loc, diag::warn_func_effect_calls_func_without_effect)870<< GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName871<< GetCallableDeclKind(CalleeInfo.CDecl, nullptr) << CalleeName;872MaybeAddSiteContext(CInfo.CDecl, Viol1);873MaybeAddTemplateNote(CInfo.CDecl);874875// Emit notes explaining the transitive chain of inferences: Why isn't876// the callee safe?877for (const Decl *Callee = Viol1.Callee; Callee != nullptr;) {878std::optional<CallableInfo> MaybeNextCallee;879CompleteFunctionAnalysis *Completed =880DeclAnalysis.completedAnalysisForDecl(CalleeInfo.CDecl);881if (Completed == nullptr) {882// No result - could be883// - non-inline and extern884// - indirect (virtual or through function pointer)885// - effect has been explicitly disclaimed (e.g. "blocking")886887CallableType CType = CalleeInfo.type();888if (CType == CallableType::Virtual)889S.Diag(Callee->getLocation(),890diag::note_func_effect_call_indirect)891<< Indirect_VirtualMethod << effectName;892else if (CType == CallableType::Unknown)893S.Diag(Callee->getLocation(),894diag::note_func_effect_call_indirect)895<< Indirect_FunctionPtr << effectName;896else if (CalleeInfo.Effects.contains(Viol1.Effect.oppositeKind()))897S.Diag(Callee->getLocation(),898diag::note_func_effect_call_disallows_inference)899<< GetCallableDeclKind(CInfo.CDecl, nullptr) << effectName900<< FunctionEffect(Viol1.Effect.oppositeKind()).name();901else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Callee);902FD == nullptr || FD->getBuiltinID() == 0) {903// A builtin callee generally doesn't have a useful source904// location at which to insert a note.905S.Diag(Callee->getLocation(), diag::note_func_effect_call_extern)906<< effectName;907}908break;909}910const Violation *PtrViol2 =911Completed->firstViolationForEffect(Viol1.Effect);912if (PtrViol2 == nullptr)913break;914915const Violation &Viol2 = *PtrViol2;916switch (Viol2.ID) {917case ViolationID::None:918llvm_unreachable("Unexpected violation kind");919break;920case ViolationID::DeclDisallowsInference:921S.Diag(Viol2.Loc, diag::note_func_effect_call_disallows_inference)922<< GetCallableDeclKind(CalleeInfo.CDecl, nullptr) << effectName923<< Viol2.CalleeEffectPreventingInference->name();924break;925case ViolationID::CallsExprWithoutEffect:926S.Diag(Viol2.Loc, diag::note_func_effect_call_indirect)927<< Indirect_FunctionPtr << effectName;928break;929case ViolationID::AllocatesMemory:930case ViolationID::ThrowsOrCatchesExceptions:931case ViolationID::HasStaticLocalVariable:932case ViolationID::AccessesThreadLocalVariable:933case ViolationID::AccessesObjCMethodOrProperty:934S.Diag(Viol2.Loc, diag::note_func_effect_violation)935<< GetCallableDeclKind(CalleeInfo.CDecl, &Viol2) << effectName936<< Viol2.diagnosticSelectIndex();937MaybeAddSiteContext(CalleeInfo.CDecl, Viol2);938break;939case ViolationID::CallsDeclWithoutEffect:940MaybeNextCallee.emplace(*Viol2.Callee);941S.Diag(Viol2.Loc, diag::note_func_effect_calls_func_without_effect)942<< GetCallableDeclKind(CalleeInfo.CDecl, &Viol2) << effectName943<< GetCallableDeclKind(Viol2.Callee, nullptr)944<< MaybeNextCallee->getNameForDiagnostic(S);945break;946}947MaybeAddTemplateNote(Callee);948Callee = Viol2.Callee;949if (MaybeNextCallee) {950CalleeInfo = *MaybeNextCallee;951CalleeName = CalleeInfo.getNameForDiagnostic(S);952}953}954} break;955}956}957}958959// ----------960// This AST visitor is used to traverse the body of a function during effect961// verification. This happens in 2 situations:962// [1] The function has declared effects which need to be validated.963// [2] The function has not explicitly declared an effect in question, and is964// being checked for implicit conformance.965//966// Violations are always routed to a PendingFunctionAnalysis.967struct FunctionBodyASTVisitor : DynamicRecursiveASTVisitor {968Analyzer &Outer;969PendingFunctionAnalysis &CurrentFunction;970CallableInfo &CurrentCaller;971ViolationSite VSite;972const Expr *TrailingRequiresClause = nullptr;973const Expr *NoexceptExpr = nullptr;974975FunctionBodyASTVisitor(Analyzer &Outer,976PendingFunctionAnalysis &CurrentFunction,977CallableInfo &CurrentCaller)978: Outer(Outer), CurrentFunction(CurrentFunction),979CurrentCaller(CurrentCaller) {980ShouldVisitImplicitCode = true;981ShouldWalkTypesOfTypeLocs = false;982}983984// -- Entry point --985void run() {986// The target function may have implicit code paths beyond the987// body: member and base destructors. Visit these first.988if (auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl))989followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor);990991if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl)) {992TrailingRequiresClause = FD->getTrailingRequiresClause().ConstraintExpr;993994// Note that FD->getType->getAs<FunctionProtoType>() can yield a995// noexcept Expr which has been boiled down to a constant expression.996// Going through the TypeSourceInfo obtains the actual expression which997// will be traversed as part of the function -- unless we capture it998// here and have TraverseStmt skip it.999if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) {1000if (FunctionProtoTypeLoc TL =1001TSI->getTypeLoc().getAs<FunctionProtoTypeLoc>())1002if (const FunctionProtoType *FPT = TL.getTypePtr())1003NoexceptExpr = FPT->getNoexceptExpr();1004}1005}10061007// Do an AST traversal of the function/block body1008TraverseDecl(const_cast<Decl *>(CurrentCaller.CDecl));1009}10101011// -- Methods implementing common logic --10121013// Handle a language construct forbidden by some effects. Only effects whose1014// flags include the specified flag receive a violation. \p Flag describes1015// the construct.1016void diagnoseLanguageConstruct(FunctionEffect::FlagBit Flag,1017ViolationID VID, SourceLocation Loc,1018const Decl *Callee = nullptr) {1019// If there are any declared verifiable effects which forbid the construct1020// represented by the flag, store just one violation.1021for (FunctionEffect Effect : CurrentFunction.DeclaredVerifiableEffects) {1022if (Effect.flags() & Flag) {1023addViolation(/*inferring=*/false, Effect, VID, Loc, Callee);1024break;1025}1026}1027// For each inferred effect which forbids the construct, store a1028// violation, if we don't already have a violation for that effect.1029for (FunctionEffect Effect : CurrentFunction.EffectsToInfer)1030if (Effect.flags() & Flag)1031addViolation(/*inferring=*/true, Effect, VID, Loc, Callee);1032}10331034void addViolation(bool Inferring, FunctionEffect Effect, ViolationID VID,1035SourceLocation Loc, const Decl *Callee = nullptr) {1036CurrentFunction.checkAddViolation(1037Inferring, Violation(Effect, VID, VSite, Loc, Callee));1038}10391040// Here we have a call to a Decl, either explicitly via a CallExpr or some1041// other AST construct. CallableInfo pertains to the callee.1042void followCall(CallableInfo &CI, SourceLocation CallLoc) {1043// Check for a call to a builtin function, whose effects are1044// handled specially.1045if (const auto *FD = dyn_cast<FunctionDecl>(CI.CDecl)) {1046if (unsigned BuiltinID = FD->getBuiltinID()) {1047CI.Effects = getBuiltinFunctionEffects(BuiltinID);1048if (CI.Effects.empty()) {1049// A builtin with no known effects is assumed safe.1050return;1051}1052// A builtin WITH effects doesn't get any special treatment for1053// being noreturn/noexcept, e.g. longjmp(), so we skip the check1054// below.1055} else {1056// If the callee is both `noreturn` and `noexcept`, it presumably1057// terminates. Ignore it for the purposes of effect analysis.1058// If not C++, `noreturn` alone is sufficient.1059if (FD->isNoReturn() &&1060(!Outer.S.getLangOpts().CPlusPlus || isNoexcept(FD)))1061return;1062}1063}10641065Outer.followCall(CurrentCaller, CurrentFunction, CI, CallLoc,1066/*AssertNoFurtherInference=*/false, VSite);1067}10681069void checkIndirectCall(CallExpr *Call, QualType CalleeType) {1070FunctionEffectKindSet CalleeEffects;1071if (FunctionEffectsRef Effects = FunctionEffectsRef::get(CalleeType);1072!Effects.empty())1073CalleeEffects.insert(Effects);10741075auto Check1Effect = [&](FunctionEffect Effect, bool Inferring) {1076if (Effect.shouldDiagnoseFunctionCall(1077/*direct=*/false, CalleeEffects))1078addViolation(Inferring, Effect, ViolationID::CallsExprWithoutEffect,1079Call->getBeginLoc());1080};10811082for (FunctionEffect Effect : CurrentFunction.DeclaredVerifiableEffects)1083Check1Effect(Effect, false);10841085for (FunctionEffect Effect : CurrentFunction.EffectsToInfer)1086Check1Effect(Effect, true);1087}10881089// This destructor's body should be followed by the caller, but here we1090// follow the field and base destructors.1091void followDestructor(const CXXRecordDecl *Rec,1092const CXXDestructorDecl *Dtor) {1093SourceLocation DtorLoc = Dtor->getLocation();1094for (const FieldDecl *Field : Rec->fields())1095followTypeDtor(Field->getType(), DtorLoc);10961097if (const auto *Class = dyn_cast<CXXRecordDecl>(Rec))1098for (const CXXBaseSpecifier &Base : Class->bases())1099followTypeDtor(Base.getType(), DtorLoc);1100}11011102void followTypeDtor(QualType QT, SourceLocation CallSite) {1103const Type *Ty = QT.getTypePtr();1104while (Ty->isArrayType()) {1105const ArrayType *Arr = Ty->getAsArrayTypeUnsafe();1106QT = Arr->getElementType();1107Ty = QT.getTypePtr();1108}11091110if (Ty->isRecordType()) {1111if (const CXXRecordDecl *Class = Ty->getAsCXXRecordDecl()) {1112if (CXXDestructorDecl *Dtor = Class->getDestructor();1113Dtor && !Dtor->isDeleted()) {1114CallableInfo CI(*Dtor);1115followCall(CI, CallSite);1116}1117}1118}1119}11201121// -- Methods for use of RecursiveASTVisitor --11221123bool VisitCXXThrowExpr(CXXThrowExpr *Throw) override {1124diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThrow,1125ViolationID::ThrowsOrCatchesExceptions,1126Throw->getThrowLoc());1127return true;1128}11291130bool VisitCXXCatchStmt(CXXCatchStmt *Catch) override {1131diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,1132ViolationID::ThrowsOrCatchesExceptions,1133Catch->getCatchLoc());1134return true;1135}11361137bool VisitObjCAtThrowStmt(ObjCAtThrowStmt *Throw) override {1138diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThrow,1139ViolationID::ThrowsOrCatchesExceptions,1140Throw->getThrowLoc());1141return true;1142}11431144bool VisitObjCAtCatchStmt(ObjCAtCatchStmt *Catch) override {1145diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,1146ViolationID::ThrowsOrCatchesExceptions,1147Catch->getAtCatchLoc());1148return true;1149}11501151bool VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Finally) override {1152diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,1153ViolationID::ThrowsOrCatchesExceptions,1154Finally->getAtFinallyLoc());1155return true;1156}11571158bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) override {1159diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend,1160ViolationID::AccessesObjCMethodOrProperty,1161Msg->getBeginLoc());1162return true;1163}11641165bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *ARP) override {1166// Under the hood, @autorelease (potentially?) allocates memory and1167// invokes ObjC methods. We don't currently have memory allocation as1168// a "language construct" but we do have ObjC messaging, so diagnose that.1169diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend,1170ViolationID::AccessesObjCMethodOrProperty,1171ARP->getBeginLoc());1172return true;1173}11741175bool VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Sync) override {1176// Under the hood, this calls objc_sync_enter and objc_sync_exit, wrapped1177// in a @try/@finally block. Diagnose this generically as "ObjC1178// messaging".1179diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend,1180ViolationID::AccessesObjCMethodOrProperty,1181Sync->getBeginLoc());1182return true;1183}11841185bool VisitSEHExceptStmt(SEHExceptStmt *Exc) override {1186diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,1187ViolationID::ThrowsOrCatchesExceptions,1188Exc->getExceptLoc());1189return true;1190}11911192bool VisitCallExpr(CallExpr *Call) override {1193LLVM_DEBUG(llvm::dbgs()1194<< "VisitCallExpr : "1195<< Call->getBeginLoc().printToString(Outer.S.SourceMgr)1196<< "\n";);11971198Expr *CalleeExpr = Call->getCallee();1199if (const Decl *Callee = CalleeExpr->getReferencedDeclOfCallee()) {1200CallableInfo CI(*Callee);1201followCall(CI, Call->getBeginLoc());1202return true;1203}12041205if (isa<CXXPseudoDestructorExpr>(CalleeExpr)) {1206// Just destroying a scalar, fine.1207return true;1208}12091210// No Decl, just an Expr. Just check based on its type.1211checkIndirectCall(Call, CalleeExpr->getType());12121213return true;1214}12151216bool VisitVarDecl(VarDecl *Var) override {1217LLVM_DEBUG(llvm::dbgs()1218<< "VisitVarDecl : "1219<< Var->getBeginLoc().printToString(Outer.S.SourceMgr)1220<< "\n";);12211222if (Var->isStaticLocal())1223diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeStaticLocalVars,1224ViolationID::HasStaticLocalVariable,1225Var->getLocation());12261227const QualType::DestructionKind DK =1228Var->needsDestruction(Outer.S.getASTContext());1229if (DK == QualType::DK_cxx_destructor)1230followTypeDtor(Var->getType(), Var->getLocation());1231return true;1232}12331234bool VisitCXXNewExpr(CXXNewExpr *New) override {1235// RecursiveASTVisitor does not visit the implicit call to operator new.1236if (FunctionDecl *FD = New->getOperatorNew()) {1237CallableInfo CI(*FD, SpecialFuncType::OperatorNew);1238followCall(CI, New->getBeginLoc());1239}12401241// It's a bit excessive to check operator delete here, since it's1242// just a fallback for operator new followed by a failed constructor.1243// We could check it via New->getOperatorDelete().12441245// It DOES however visit the called constructor1246return true;1247}12481249bool VisitCXXDeleteExpr(CXXDeleteExpr *Delete) override {1250// RecursiveASTVisitor does not visit the implicit call to operator1251// delete.1252if (FunctionDecl *FD = Delete->getOperatorDelete()) {1253CallableInfo CI(*FD, SpecialFuncType::OperatorDelete);1254followCall(CI, Delete->getBeginLoc());1255}12561257// It DOES however visit the called destructor12581259return true;1260}12611262bool VisitCXXConstructExpr(CXXConstructExpr *Construct) override {1263LLVM_DEBUG(llvm::dbgs() << "VisitCXXConstructExpr : "1264<< Construct->getBeginLoc().printToString(1265Outer.S.SourceMgr)1266<< "\n";);12671268// RecursiveASTVisitor does not visit the implicit call to the1269// constructor.1270const CXXConstructorDecl *Ctor = Construct->getConstructor();1271CallableInfo CI(*Ctor);1272followCall(CI, Construct->getLocation());12731274return true;1275}12761277bool TraverseStmt(Stmt *Statement) override {1278// If this statement is a `requires` clause from the top-level function1279// being traversed, ignore it, since it's not generating runtime code.1280// We skip the traversal of lambdas (beyond their captures, see1281// TraverseLambdaExpr below), so just caching this from our constructor1282// should suffice.1283if (Statement != TrailingRequiresClause && Statement != NoexceptExpr)1284return DynamicRecursiveASTVisitor::TraverseStmt(Statement);1285return true;1286}12871288bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override {1289ViolationSite PrevVS = VSite;1290if (Init->isAnyMemberInitializer())1291VSite.setKind(ViolationSite::Kind::MemberInitializer);1292bool Result =1293DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init);1294VSite = PrevVS;1295return Result;1296}12971298bool TraverseCXXDefaultArgExpr(CXXDefaultArgExpr *E) override {1299LLVM_DEBUG(llvm::dbgs()1300<< "TraverseCXXDefaultArgExpr : "1301<< E->getUsedLocation().printToString(Outer.S.SourceMgr)1302<< "\n";);13031304ViolationSite PrevVS = VSite;1305if (VSite.kind() == ViolationSite::Kind::Default)1306VSite = ViolationSite{E};13071308bool Result = DynamicRecursiveASTVisitor::TraverseCXXDefaultArgExpr(E);1309VSite = PrevVS;1310return Result;1311}13121313bool TraverseLambdaExpr(LambdaExpr *Lambda) override {1314// We override this so as to be able to skip traversal of the lambda's1315// body. We have to explicitly traverse the captures. Why not return1316// false from shouldVisitLambdaBody()? Because we need to visit a lambda's1317// body when we are verifying the lambda itself; we only want to skip it1318// in the context of the outer function.1319for (unsigned I = 0, N = Lambda->capture_size(); I < N; ++I)1320TraverseLambdaCapture(Lambda, Lambda->capture_begin() + I,1321Lambda->capture_init_begin()[I]);13221323return true;1324}13251326bool TraverseBlockExpr(BlockExpr * /*unused*/) override {1327// As with lambdas, don't traverse the block's body.1328// TODO: are the capture expressions (ctor call?) safe?1329return true;1330}13311332bool VisitDeclRefExpr(DeclRefExpr *E) override {1333const ValueDecl *Val = E->getDecl();1334if (const auto *Var = dyn_cast<VarDecl>(Val)) {1335if (Var->getTLSKind() != VarDecl::TLS_None) {1336// At least on macOS, thread-local variables are initialized on1337// first access, including a heap allocation.1338diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThreadLocalVars,1339ViolationID::AccessesThreadLocalVariable,1340E->getLocation());1341}1342}1343return true;1344}13451346bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) override {1347return TraverseStmt(Node->getResultExpr());1348}1349bool1350TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) override {1351return true;1352}13531354bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override {1355return true;1356}13571358bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override { return true; }13591360bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override {1361return true;1362}13631364bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) override { return true; }13651366// Skip concept requirements since they don't generate code.1367bool TraverseConceptRequirement(concepts::Requirement *R) override {1368return true;1369}1370};1371};13721373Analyzer::AnalysisMap::~AnalysisMap() {1374for (const auto &Item : *this) {1375FuncAnalysisPtr AP = Item.second;1376if (auto *PFA = dyn_cast<PendingFunctionAnalysis *>(AP))1377delete PFA;1378else1379delete cast<CompleteFunctionAnalysis *>(AP);1380}1381}13821383} // anonymous namespace13841385namespace clang {13861387bool Sema::diagnoseConflictingFunctionEffect(1388const FunctionEffectsRef &FX, const FunctionEffectWithCondition &NewEC,1389SourceLocation NewAttrLoc) {1390// If the new effect has a condition, we can't detect conflicts until the1391// condition is resolved.1392if (NewEC.Cond.getCondition() != nullptr)1393return false;13941395// Diagnose the new attribute as incompatible with a previous one.1396auto Incompatible = [&](const FunctionEffectWithCondition &PrevEC) {1397Diag(NewAttrLoc, diag::err_attributes_are_not_compatible)1398<< ("'" + NewEC.description() + "'")1399<< ("'" + PrevEC.description() + "'") << false;1400// We don't necessarily have the location of the previous attribute,1401// so no note.1402return true;1403};14041405// Compare against previous attributes.1406FunctionEffect::Kind NewKind = NewEC.Effect.kind();14071408for (const FunctionEffectWithCondition &PrevEC : FX) {1409// Again, can't check yet when the effect is conditional.1410if (PrevEC.Cond.getCondition() != nullptr)1411continue;14121413FunctionEffect::Kind PrevKind = PrevEC.Effect.kind();1414// Note that we allow PrevKind == NewKind; it's redundant and ignored.14151416if (PrevEC.Effect.oppositeKind() == NewKind)1417return Incompatible(PrevEC);14181419// A new allocating is incompatible with a previous nonblocking.1420if (PrevKind == FunctionEffect::Kind::NonBlocking &&1421NewKind == FunctionEffect::Kind::Allocating)1422return Incompatible(PrevEC);14231424// A new nonblocking is incompatible with a previous allocating.1425if (PrevKind == FunctionEffect::Kind::Allocating &&1426NewKind == FunctionEffect::Kind::NonBlocking)1427return Incompatible(PrevEC);1428}14291430return false;1431}14321433void Sema::diagnoseFunctionEffectMergeConflicts(1434const FunctionEffectSet::Conflicts &Errs, SourceLocation NewLoc,1435SourceLocation OldLoc) {1436for (const FunctionEffectSet::Conflict &Conflict : Errs) {1437Diag(NewLoc, diag::warn_conflicting_func_effects)1438<< Conflict.Kept.description() << Conflict.Rejected.description();1439Diag(OldLoc, diag::note_previous_declaration);1440}1441}14421443// Decl should be a FunctionDecl or BlockDecl.1444void Sema::maybeAddDeclWithEffects(const Decl *D,1445const FunctionEffectsRef &FX) {1446if (!D->hasBody()) {1447if (const auto *FD = D->getAsFunction(); FD && !FD->willHaveBody())1448return;1449}14501451if (Diags.getIgnoreAllWarnings() ||1452(Diags.getSuppressSystemWarnings() &&1453SourceMgr.isInSystemHeader(D->getLocation())))1454return;14551456if (hasUncompilableErrorOccurred())1457return;14581459// For code in dependent contexts, we'll do this at instantiation time.1460// Without this check, we would analyze the function based on placeholder1461// template parameters, and potentially generate spurious diagnostics.1462if (cast<DeclContext>(D)->isDependentContext())1463return;14641465addDeclWithEffects(D, FX);1466}14671468void Sema::addDeclWithEffects(const Decl *D, const FunctionEffectsRef &FX) {1469// To avoid the possibility of conflict, don't add effects which are1470// not FE_InferrableOnCallees and therefore not verified; this removes1471// blocking/allocating but keeps nonblocking/nonallocating.1472// Also, ignore any conditions when building the list of effects.1473bool AnyVerifiable = false;1474for (const FunctionEffectWithCondition &EC : FX)1475if (EC.Effect.flags() & FunctionEffect::FE_InferrableOnCallees) {1476AllEffectsToVerify.insert(EC.Effect);1477AnyVerifiable = true;1478}14791480// Record the declaration for later analysis.1481if (AnyVerifiable)1482DeclsWithEffectsToVerify.push_back(D);1483}14841485void Sema::performFunctionEffectAnalysis(TranslationUnitDecl *TU) {1486if (hasUncompilableErrorOccurred() || Diags.getIgnoreAllWarnings())1487return;1488if (TU == nullptr)1489return;1490Analyzer{*this}.run(*TU);1491}14921493Sema::FunctionEffectDiffVector::FunctionEffectDiffVector(1494const FunctionEffectsRef &Old, const FunctionEffectsRef &New) {14951496FunctionEffectsRef::iterator POld = Old.begin();1497FunctionEffectsRef::iterator OldEnd = Old.end();1498FunctionEffectsRef::iterator PNew = New.begin();1499FunctionEffectsRef::iterator NewEnd = New.end();15001501while (true) {1502int cmp = 0;1503if (POld == OldEnd) {1504if (PNew == NewEnd)1505break;1506cmp = 1;1507} else if (PNew == NewEnd)1508cmp = -1;1509else {1510FunctionEffectWithCondition Old = *POld;1511FunctionEffectWithCondition New = *PNew;1512if (Old.Effect.kind() < New.Effect.kind())1513cmp = -1;1514else if (New.Effect.kind() < Old.Effect.kind())1515cmp = 1;1516else {1517cmp = 0;1518if (Old.Cond.getCondition() != New.Cond.getCondition()) {1519// FIXME: Cases where the expressions are equivalent but1520// don't have the same identity.1521push_back(FunctionEffectDiff{1522Old.Effect.kind(), FunctionEffectDiff::Kind::ConditionMismatch,1523Old, New});1524}1525}1526}15271528if (cmp < 0) {1529// removal1530FunctionEffectWithCondition Old = *POld;1531push_back(FunctionEffectDiff{Old.Effect.kind(),1532FunctionEffectDiff::Kind::Removed, Old,1533std::nullopt});1534++POld;1535} else if (cmp > 0) {1536// addition1537FunctionEffectWithCondition New = *PNew;1538push_back(FunctionEffectDiff{New.Effect.kind(),1539FunctionEffectDiff::Kind::Added,1540std::nullopt, New});1541++PNew;1542} else {1543++POld;1544++PNew;1545}1546}1547}15481549bool Sema::FunctionEffectDiff::shouldDiagnoseConversion(1550QualType SrcType, const FunctionEffectsRef &SrcFX, QualType DstType,1551const FunctionEffectsRef &DstFX) const {15521553switch (EffectKind) {1554case FunctionEffect::Kind::NonAllocating:1555// nonallocating can't be added (spoofed) during a conversion, unless we1556// have nonblocking.1557if (DiffKind == Kind::Added) {1558for (const auto &CFE : SrcFX) {1559if (CFE.Effect.kind() == FunctionEffect::Kind::NonBlocking)1560return false;1561}1562}1563[[fallthrough]];1564case FunctionEffect::Kind::NonBlocking:1565// nonblocking can't be added (spoofed) during a conversion.1566switch (DiffKind) {1567case Kind::Added:1568return true;1569case Kind::Removed:1570return false;1571case Kind::ConditionMismatch:1572// FIXME: Condition mismatches are too coarse right now -- expressions1573// which are equivalent but don't have the same identity are detected as1574// mismatches. We're going to diagnose those anyhow until expression1575// matching is better.1576return true;1577}1578break;1579case FunctionEffect::Kind::Blocking:1580case FunctionEffect::Kind::Allocating:1581return false;1582}1583llvm_unreachable("unknown effect kind");1584}15851586bool Sema::FunctionEffectDiff::shouldDiagnoseRedeclaration(1587const FunctionDecl &OldFunction, const FunctionEffectsRef &OldFX,1588const FunctionDecl &NewFunction, const FunctionEffectsRef &NewFX) const {1589switch (EffectKind) {1590case FunctionEffect::Kind::NonAllocating:1591case FunctionEffect::Kind::NonBlocking:1592// nonblocking/nonallocating can't be removed in a redeclaration.1593switch (DiffKind) {1594case Kind::Added:1595return false; // No diagnostic.1596case Kind::Removed:1597return true; // Issue diagnostic.1598case Kind::ConditionMismatch:1599// All these forms of mismatches are diagnosed.1600return true;1601}1602break;1603case FunctionEffect::Kind::Blocking:1604case FunctionEffect::Kind::Allocating:1605return false;1606}1607llvm_unreachable("unknown effect kind");1608}16091610Sema::FunctionEffectDiff::OverrideResult1611Sema::FunctionEffectDiff::shouldDiagnoseMethodOverride(1612const CXXMethodDecl &OldMethod, const FunctionEffectsRef &OldFX,1613const CXXMethodDecl &NewMethod, const FunctionEffectsRef &NewFX) const {1614switch (EffectKind) {1615case FunctionEffect::Kind::NonAllocating:1616case FunctionEffect::Kind::NonBlocking:1617switch (DiffKind) {16181619// If added on an override, that's fine and not diagnosed.1620case Kind::Added:1621return OverrideResult::NoAction;16221623// If missing from an override (removed), propagate from base to derived.1624case Kind::Removed:1625return OverrideResult::Merge;16261627// If there's a mismatch involving the effect's polarity or condition,1628// issue a warning.1629case Kind::ConditionMismatch:1630return OverrideResult::Warn;1631}1632break;1633case FunctionEffect::Kind::Blocking:1634case FunctionEffect::Kind::Allocating:1635return OverrideResult::NoAction;1636}1637llvm_unreachable("unknown effect kind");1638}16391640} // namespace clang164116421643