================ @@ -2380,6 +2382,1239 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler { }; } // namespace +// ============================================================================= + +// Temporary debugging option +#define FX_ANALYZER_VERIFY_DECL_LIST 1 + +namespace FXAnalysis { + +enum class DiagnosticID : uint8_t { + None = 0, // sentinel for an empty Diagnostic + Throws, + Catches, + CallsObjC, + AllocatesMemory, + HasStaticLocal, + AccessesThreadLocal, + + // These only apply to callees, where the analysis stops at the Decl + DeclWithoutConstraintOrInference, + + CallsUnsafeDecl, + CallsDisallowedExpr, +}; + +struct Diagnostic { + const FunctionEffect *Effect = nullptr; + const Decl *Callee = nullptr; // only valid for Calls* + SourceLocation Loc; + DiagnosticID ID = DiagnosticID::None; + + Diagnostic() = default; + + Diagnostic(const FunctionEffect *Effect, DiagnosticID ID, SourceLocation Loc, + const Decl *Callee = nullptr) + : Effect(Effect), Callee(Callee), Loc(Loc), ID(ID) {} +}; + +enum class SpecialFuncType : uint8_t { None, OperatorNew, OperatorDelete }; +enum class CallType { + Unknown, + Function, + Virtual, + Block + // unknown: probably function pointer +}; + +// Return whether the function CAN be verified. +// The question of whether it SHOULD be verified is independent. +static bool functionIsVerifiable(const FunctionDecl *FD) { + if (!(FD->hasBody() || FD->isInlined())) { + // externally defined; we couldn't verify if we wanted to. + return false; + } + if (FD->isTrivial()) { + // Otherwise `struct x { int a; };` would have an unverifiable default + // constructor. + return true; + } + return true; +} + +// Transitory, more extended information about a callable, which can be a +// function, block, function pointer... +struct CallableInfo { + const Decl *CDecl; + mutable std::optional<std::string> + MaybeName; // mutable because built on demand in const method + SpecialFuncType FuncType = SpecialFuncType::None; + FunctionEffectSet Effects; + CallType CType = CallType::Unknown; + + CallableInfo(const Decl &CD, SpecialFuncType FT = SpecialFuncType::None) + : CDecl(&CD), FuncType(FT) { + // llvm::errs() << "CallableInfo " << name() << "\n"; + + if (auto *FD = dyn_cast<FunctionDecl>(CDecl)) { + assert(FD->getCanonicalDecl() == FD); + // Use the function's definition, if any. + if (auto *Def = FD->getDefinition()) { + CDecl = FD = Def; + } + CType = CallType::Function; + if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { + if (Method->isVirtual()) { + CType = CallType::Virtual; + } + } + Effects = FD->getFunctionEffects(); + } else if (auto *BD = dyn_cast<BlockDecl>(CDecl)) { + CType = CallType::Block; + Effects = BD->getFunctionEffects(); + } else if (auto *VD = dyn_cast<ValueDecl>(CDecl)) { + // ValueDecl is function, enum, or variable, so just look at the type. + Effects = FunctionEffectSet::get(*VD->getType()); + } + } + + bool isDirectCall() const { + return CType == CallType::Function || CType == CallType::Block; + } + + bool isVerifiable() const { + switch (CType) { + case CallType::Unknown: + case CallType::Virtual: + break; + case CallType::Block: + return true; + case CallType::Function: + return functionIsVerifiable(dyn_cast<FunctionDecl>(CDecl)); + } + return false; + } + + /// Generate a name for logging and diagnostics. + std::string name(Sema &Sem) const { + if (!MaybeName) { + std::string Name; + llvm::raw_string_ostream OS(Name); + + if (auto *FD = dyn_cast<FunctionDecl>(CDecl)) { + FD->getNameForDiagnostic(OS, Sem.getPrintingPolicy(), + /*Qualified=*/true); + } else if (auto *BD = dyn_cast<BlockDecl>(CDecl)) { + OS << "(block " << BD->getBlockManglingNumber() << ")"; + } else if (auto *VD = dyn_cast<NamedDecl>(CDecl)) { + VD->printQualifiedName(OS); + } + MaybeName = Name; + } + return *MaybeName; + } +}; + +// ---------- +// Map effects to single diagnostics. +class EffectToDiagnosticMap { + // Since we currently only have a tiny number of effects (typically no more + // than 1), use a sorted SmallVector. ---------------- dougsonos wrote:
Done https://github.com/llvm/llvm-project/pull/84983 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits