1670 lines · cpp
1//=== SemaFunctionEffects.cpp - Sema handling of function effects ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements Sema handling of function effects.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/Decl.h"14#include "clang/AST/DeclCXX.h"15#include "clang/AST/DynamicRecursiveASTVisitor.h"16#include "clang/AST/ExprObjC.h"17#include "clang/AST/Stmt.h"18#include "clang/AST/StmtObjC.h"19#include "clang/AST/Type.h"20#include "clang/Basic/SourceManager.h"21#include "clang/Sema/SemaInternal.h"22 23#define DEBUG_TYPE "effectanalysis"24 25using namespace clang;26 27namespace {28 29enum class ViolationID : uint8_t {30 None = 0, // Sentinel for an empty Violation.31 // These first 5 map to a %select{} in one of several FunctionEffects32 // diagnostics, e.g. warn_func_effect_violation.33 BaseDiagnosticIndex,34 AllocatesMemory = BaseDiagnosticIndex,35 ThrowsOrCatchesExceptions,36 HasStaticLocalVariable,37 AccessesThreadLocalVariable,38 AccessesObjCMethodOrProperty,39 40 // These only apply to callees, where the analysis stops at the Decl.41 DeclDisallowsInference,42 43 // These both apply to indirect calls. The difference is that sometimes44 // we have an actual Decl (generally a variable) which is the function45 // pointer being called, and sometimes, typically due to a cast, we only46 // have an expression.47 CallsDeclWithoutEffect,48 CallsExprWithoutEffect,49};50 51// Information about the AST context in which a violation was found, so52// that diagnostics can point to the correct source.53class ViolationSite {54public:55 enum class Kind : uint8_t {56 Default, // Function body.57 MemberInitializer,58 DefaultArgExpr59 };60 61private:62 llvm::PointerIntPair<CXXDefaultArgExpr *, 2, Kind> Impl;63 64public:65 ViolationSite() = default;66 67 explicit ViolationSite(CXXDefaultArgExpr *E)68 : Impl(E, Kind::DefaultArgExpr) {}69 70 Kind kind() const { return static_cast<Kind>(Impl.getInt()); }71 CXXDefaultArgExpr *defaultArgExpr() const { return Impl.getPointer(); }72 73 void setKind(Kind K) { Impl.setPointerAndInt(nullptr, K); }74};75 76// Represents a violation of the rules, potentially for the entire duration of77// the analysis phase, in order to refer to it when explaining why a caller has78// been made unsafe by a callee. Can be transformed into either a Diagnostic79// (warning or a note), depending on whether the violation pertains to a80// function failing to be verifed as holding an effect vs. a function failing to81// be inferred as holding that effect.82struct Violation {83 FunctionEffect Effect;84 std::optional<FunctionEffect>85 CalleeEffectPreventingInference; // Only for certain IDs; can be nullopt.86 ViolationID ID = ViolationID::None;87 ViolationSite Site;88 SourceLocation Loc;89 const Decl *Callee =90 nullptr; // Only valid for ViolationIDs Calls{Decl,Expr}WithoutEffect.91 92 Violation(FunctionEffect Effect, ViolationID ID, ViolationSite VS,93 SourceLocation Loc, const Decl *Callee = nullptr,94 std::optional<FunctionEffect> CalleeEffect = std::nullopt)95 : Effect(Effect), CalleeEffectPreventingInference(CalleeEffect), ID(ID),96 Site(VS), Loc(Loc), Callee(Callee) {}97 98 unsigned diagnosticSelectIndex() const {99 return unsigned(ID) - unsigned(ViolationID::BaseDiagnosticIndex);100 }101};102 103enum class SpecialFuncType : uint8_t { None, OperatorNew, OperatorDelete };104enum class CallableType : uint8_t {105 // Unknown: probably function pointer.106 Unknown,107 Function,108 Virtual,109 Block110};111 112// Return whether a function's effects CAN be verified.113// The question of whether it SHOULD be verified is independent.114static bool functionIsVerifiable(const FunctionDecl *FD) {115 if (FD->isTrivial()) {116 // Otherwise `struct x { int a; };` would have an unverifiable default117 // constructor.118 return true;119 }120 return FD->hasBody();121}122 123static bool isNoexcept(const FunctionDecl *FD) {124 const auto *FPT = FD->getType()->getAs<FunctionProtoType>();125 return FPT && (FPT->isNothrow() || FD->hasAttr<NoThrowAttr>());126}127 128// This list is probably incomplete.129// FIXME: Investigate:130// __builtin_eh_return?131// __builtin_allow_runtime_check?132// __builtin_unwind_init and other similar things that sound exception-related.133// va_copy?134// coroutines?135static FunctionEffectKindSet getBuiltinFunctionEffects(unsigned BuiltinID) {136 FunctionEffectKindSet Result;137 138 switch (BuiltinID) {139 case 0: // Not builtin.140 default: // By default, builtins have no known effects.141 break;142 143 // These allocate/deallocate heap memory.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:156 157 case Builtin::ID::BIfopen:158 case Builtin::ID::BIpthread_create:159 case Builtin::ID::BI_Block_object_dispose:160 Result.insert(FunctionEffect(FunctionEffect::Kind::Allocating));161 break;162 163 // These block in some other way than allocating memory.164 // longjmp() and friends are presumed unsafe because they are the moral165 // equivalent of throwing a C++ exception, which is unsafe.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:171 172 // Objective-C runtime.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:187 188 // stdio.h189 case Builtin::ID::BIfread:190 case Builtin::ID::BIfwrite:191 192 // stdio.h: printf family.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:202 203 // stdio.h: scanf family.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:210 Result.insert(FunctionEffect(FunctionEffect::Kind::Blocking));211 break;212 }213 214 return Result;215}216 217// Transitory, more extended information about a callable, which can be a218// function, block, or function pointer.219struct CallableInfo {220 // CDecl holds the function's definition, if any.221 // FunctionDecl if CallableType::Function or Virtual222 // BlockDecl if CallableType::Block223 const Decl *CDecl;224 225 // Remember whether the callable is a function, block, virtual method,226 // or (presumed) function pointer.227 CallableType CType = CallableType::Unknown;228 229 // Remember whether the callable is an operator new or delete function,230 // so that calls to them are reported more meaningfully, as memory231 // allocations.232 SpecialFuncType FuncType = SpecialFuncType::None;233 234 // We inevitably want to know the callable's declared effects, so cache them.235 FunctionEffectKindSet Effects;236 237 CallableInfo(const Decl &CD, SpecialFuncType FT = SpecialFuncType::None)238 : CDecl(&CD), FuncType(FT) {239 FunctionEffectsRef DeclEffects;240 if (auto *FD = dyn_cast<FunctionDecl>(CDecl)) {241 // Use the function's definition, if any.242 if (const FunctionDecl *Def = FD->getDefinition())243 CDecl = FD = Def;244 CType = CallableType::Function;245 if (auto *Method = dyn_cast<CXXMethodDecl>(FD);246 Method && Method->isVirtual())247 CType = CallableType::Virtual;248 DeclEffects = FD->getFunctionEffects();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)) {253 // ValueDecl is function, enum, or variable, so just look at its type.254 DeclEffects = FunctionEffectsRef::get(VD->getType());255 }256 Effects = FunctionEffectKindSet(DeclEffects);257 }258 259 CallableType type() const { return CType; }260 261 bool isCalledDirectly() const {262 return CType == CallableType::Function || CType == CallableType::Block;263 }264 265 bool isVerifiable() const {266 switch (CType) {267 case CallableType::Unknown:268 case CallableType::Virtual:269 return false;270 case CallableType::Block:271 return true;272 case CallableType::Function:273 return functionIsVerifiable(dyn_cast<FunctionDecl>(CDecl));274 }275 llvm_unreachable("undefined CallableType");276 }277 278 /// Generate a name for logging and diagnostics.279 std::string getNameForDiagnostic(Sema &S) const {280 std::string Name;281 llvm::raw_string_ostream OS(Name);282 283 if (auto *FD = dyn_cast<FunctionDecl>(CDecl))284 FD->getNameForDiagnostic(OS, S.getPrintingPolicy(),285 /*Qualified=*/true);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);290 return Name;291 }292};293 294// ----------295// Map effects to single Violations, to hold the first (of potentially many)296// violations pertaining to an effect, per function.297class EffectToViolationMap {298 // Since we currently only have a tiny number of effects (typically no more299 // than 1), use a SmallVector with an inline capacity of 1. Since it300 // is often empty, use a unique_ptr to the SmallVector.301 // Note that Violation itself contains a FunctionEffect which is the key.302 // FIXME: Is there a way to simplify this using existing data structures?303 using ImplVec = llvm::SmallVector<Violation, 1>;304 std::unique_ptr<ImplVec> Impl;305 306public:307 // Insert a new Violation if we do not already have one for its effect.308 void maybeInsert(const Violation &Viol) {309 if (Impl == nullptr)310 Impl = std::make_unique<ImplVec>();311 else if (lookup(Viol.Effect) != nullptr)312 return;313 314 Impl->push_back(Viol);315 }316 317 const Violation *lookup(FunctionEffect Key) {318 if (Impl == nullptr)319 return nullptr;320 321 auto *Iter = llvm::find_if(322 *Impl, [&](const auto &Item) { return Item.Effect == Key; });323 return Iter != Impl->end() ? &*Iter : nullptr;324 }325 326 size_t size() const { return Impl ? Impl->size() : 0; }327};328 329// ----------330// State pertaining to a function whose AST is walked and whose effect analysis331// is dependent on a subsequent analysis of other functions.332class PendingFunctionAnalysis {333 friend class CompleteFunctionAnalysis;334 335public:336 struct DirectCall {337 const Decl *Callee;338 SourceLocation CallLoc;339 // Not all recursive calls are detected, just enough340 // to break cycles.341 bool Recursed = false;342 ViolationSite VSite;343 344 DirectCall(const Decl *D, SourceLocation CallLoc, ViolationSite VSite)345 : Callee(D), CallLoc(CallLoc), VSite(VSite) {}346 };347 348 // We always have two disjoint sets of effects to verify:349 // 1. Effects declared explicitly by this function.350 // 2. All other inferrable effects needing verification.351 FunctionEffectKindSet DeclaredVerifiableEffects;352 FunctionEffectKindSet EffectsToInfer;353 354private:355 // Violations pertaining to the function's explicit effects.356 SmallVector<Violation, 0> ViolationsForExplicitEffects;357 358 // Violations pertaining to other, non-explicit, inferrable effects.359 EffectToViolationMap InferrableEffectToFirstViolation;360 361 // These unverified direct calls are what keeps the analysis "pending",362 // until the callees can be verified.363 SmallVector<DirectCall, 0> UnverifiedDirectCalls;364 365public:366 PendingFunctionAnalysis(Sema &S, const CallableInfo &CInfo,367 FunctionEffectKindSet AllInferrableEffectsToVerify)368 : DeclaredVerifiableEffects(CInfo.Effects) {369 // Check for effects we are not allowed to infer.370 FunctionEffectKindSet InferrableEffects;371 372 for (FunctionEffect effect : AllInferrableEffectsToVerify) {373 std::optional<FunctionEffect> ProblemCalleeEffect =374 effect.effectProhibitingInference(*CInfo.CDecl, CInfo.Effects);375 if (!ProblemCalleeEffect)376 InferrableEffects.insert(effect);377 else {378 // Add a Violation for this effect if a caller were to379 // try to infer it.380 InferrableEffectToFirstViolation.maybeInsert(Violation(381 effect, ViolationID::DeclDisallowsInference, ViolationSite{},382 CInfo.CDecl->getLocation(), nullptr, ProblemCalleeEffect));383 }384 }385 // InferrableEffects is now the set of inferrable effects which are not386 // prohibited.387 EffectsToInfer = FunctionEffectKindSet::difference(388 InferrableEffects, DeclaredVerifiableEffects);389 }390 391 // Hide the way that Violations for explicitly required effects vs. inferred392 // ones are handled differently.393 void checkAddViolation(bool Inferring, const Violation &NewViol) {394 if (!Inferring)395 ViolationsForExplicitEffects.push_back(NewViol);396 else397 InferrableEffectToFirstViolation.maybeInsert(NewViol);398 }399 400 void addUnverifiedDirectCall(const Decl *D, SourceLocation CallLoc,401 ViolationSite VSite) {402 UnverifiedDirectCalls.emplace_back(D, CallLoc, VSite);403 }404 405 // Analysis is complete when there are no unverified direct calls.406 bool isComplete() const { return UnverifiedDirectCalls.empty(); }407 408 const Violation *violationForInferrableEffect(FunctionEffect effect) {409 return InferrableEffectToFirstViolation.lookup(effect);410 }411 412 // Mutable because caller may need to set a DirectCall's Recursing flag.413 MutableArrayRef<DirectCall> unverifiedCalls() {414 assert(!isComplete());415 return UnverifiedDirectCalls;416 }417 418 ArrayRef<Violation> getSortedViolationsForExplicitEffects(SourceManager &SM) {419 if (!ViolationsForExplicitEffects.empty())420 llvm::sort(ViolationsForExplicitEffects,421 [&SM](const Violation &LHS, const Violation &RHS) {422 return SM.isBeforeInTranslationUnit(LHS.Loc, RHS.Loc);423 });424 return ViolationsForExplicitEffects;425 }426 427 void dump(Sema &SemaRef, llvm::raw_ostream &OS) const {428 OS << "Pending: Declared ";429 DeclaredVerifiableEffects.dump(OS);430 OS << ", " << ViolationsForExplicitEffects.size() << " violations; ";431 OS << " Infer ";432 EffectsToInfer.dump(OS);433 OS << ", " << InferrableEffectToFirstViolation.size() << " violations";434 if (!UnverifiedDirectCalls.empty()) {435 OS << "; Calls: ";436 for (const DirectCall &Call : UnverifiedDirectCalls) {437 CallableInfo CI(*Call.Callee);438 OS << " " << CI.getNameForDiagnostic(SemaRef);439 }440 }441 OS << "\n";442 }443};444 445// ----------446class CompleteFunctionAnalysis {447 // Current size: 2 pointers448public:449 // Has effects which are both the declared ones -- not to be inferred -- plus450 // ones which have been successfully inferred. These are all considered451 // "verified" for the purposes of callers; any issue with verifying declared452 // effects has already been reported and is not the problem of any caller.453 FunctionEffectKindSet VerifiedEffects;454 455private:456 // This is used to generate notes about failed inference.457 EffectToViolationMap InferrableEffectToFirstViolation;458 459public:460 // The incoming Pending analysis is consumed (member(s) are moved-from).461 CompleteFunctionAnalysis(ASTContext &Ctx, PendingFunctionAnalysis &&Pending,462 FunctionEffectKindSet DeclaredEffects,463 FunctionEffectKindSet AllInferrableEffectsToVerify)464 : VerifiedEffects(DeclaredEffects) {465 for (FunctionEffect effect : AllInferrableEffectsToVerify)466 if (Pending.violationForInferrableEffect(effect) == nullptr)467 VerifiedEffects.insert(effect);468 469 InferrableEffectToFirstViolation =470 std::move(Pending.InferrableEffectToFirstViolation);471 }472 473 const Violation *firstViolationForEffect(FunctionEffect Effect) {474 return InferrableEffectToFirstViolation.lookup(Effect);475 }476 477 void dump(llvm::raw_ostream &OS) const {478 OS << "Complete: Verified ";479 VerifiedEffects.dump(OS);480 OS << "; Infer ";481 OS << InferrableEffectToFirstViolation.size() << " violations\n";482 }483};484 485// ==========486class Analyzer {487 Sema &S;488 489 // Subset of Sema.AllEffectsToVerify490 FunctionEffectKindSet AllInferrableEffectsToVerify;491 492 using FuncAnalysisPtr =493 llvm::PointerUnion<PendingFunctionAnalysis *, CompleteFunctionAnalysis *>;494 495 // Map all Decls analyzed to FuncAnalysisPtr. Pending state is larger496 // than complete state, so use different objects to represent them.497 // The state pointers are owned by the container.498 class AnalysisMap : llvm::DenseMap<const Decl *, FuncAnalysisPtr> {499 using Base = llvm::DenseMap<const Decl *, FuncAnalysisPtr>;500 501 public:502 ~AnalysisMap();503 504 // Use non-public inheritance in order to maintain the invariant505 // that lookups and insertions are via the canonical Decls.506 507 FuncAnalysisPtr lookup(const Decl *Key) const {508 return Base::lookup(Key->getCanonicalDecl());509 }510 511 FuncAnalysisPtr &operator[](const Decl *Key) {512 return Base::operator[](Key->getCanonicalDecl());513 }514 515 /// Shortcut for the case where we only care about completed analysis.516 CompleteFunctionAnalysis *completedAnalysisForDecl(const Decl *D) const {517 if (FuncAnalysisPtr AP = lookup(D);518 isa_and_nonnull<CompleteFunctionAnalysis *>(AP))519 return cast<CompleteFunctionAnalysis *>(AP);520 return nullptr;521 }522 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) << " : ";529 if (AP.isNull()) {530 OS << "null\n";531 } else if (auto *CFA = dyn_cast<CompleteFunctionAnalysis *>(AP)) {532 OS << CFA << " ";533 CFA->dump(OS);534 } else if (auto *PFA = dyn_cast<PendingFunctionAnalysis *>(AP)) {535 OS << PFA << " ";536 PFA->dump(SemaRef, OS);537 } else538 llvm_unreachable("never");539 }540 OS << "---\n";541 }542 };543 AnalysisMap DeclAnalysis;544 545public:546 Analyzer(Sema &S) : S(S) {}547 548 void run(const TranslationUnitDecl &TU) {549 // Gather all of the effects to be verified to see what operations need to550 // be checked, and to see which ones are inferrable.551 for (FunctionEffect Effect : S.AllEffectsToVerify) {552 const FunctionEffect::Flags Flags = Effect.flags();553 if (Flags & FunctionEffect::FE_InferrableOnCallees)554 AllInferrableEffectsToVerify.insert(Effect);555 }556 LLVM_DEBUG(llvm::dbgs() << "AllInferrableEffectsToVerify: ";557 AllInferrableEffectsToVerify.dump(llvm::dbgs());558 llvm::dbgs() << "\n";);559 560 // We can use DeclsWithEffectsToVerify as a stack for a561 // depth-first traversal; there's no need for a second container. But first,562 // reverse it, so when working from the end, Decls are verified in the order563 // they are declared.564 SmallVector<const Decl *> &VerificationQueue = S.DeclsWithEffectsToVerify;565 std::reverse(VerificationQueue.begin(), VerificationQueue.end());566 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)) {571 // All children have been traversed; finish analysis.572 finishPendingAnalysis(D, Pending);573 }574 VerificationQueue.pop_back();575 continue;576 }577 578 // Not previously visited; begin a new analysis for this Decl.579 PendingFunctionAnalysis *Pending = verifyDecl(D);580 if (Pending == nullptr) {581 // Completed now.582 VerificationQueue.pop_back();583 continue;584 }585 586 // Analysis remains pending because there are direct callees to be587 // verified first. Push them onto the queue.588 for (PendingFunctionAnalysis::DirectCall &Call :589 Pending->unverifiedCalls()) {590 FuncAnalysisPtr AP = DeclAnalysis.lookup(Call.Callee);591 if (AP.isNull()) {592 VerificationQueue.push_back(Call.Callee);593 continue;594 }595 596 // This indicates recursion (not necessarily direct). For the597 // purposes of effect analysis, we can just ignore it since598 // no effects forbid recursion.599 assert(isa<PendingFunctionAnalysis *>(AP));600 Call.Recursed = true;601 }602 }603 }604 605private:606 // Verify a single Decl. Return the pending structure if that was the result,607 // else null. This method must not recurse.608 PendingFunctionAnalysis *verifyDecl(const Decl *D) {609 CallableInfo CInfo(*D);610 bool isExternC = false;611 612 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))613 isExternC = FD->getCanonicalDecl()->isExternCContext();614 615 // For C++, with non-extern "C" linkage only - if any of the Decl's declared616 // effects forbid throwing (e.g. nonblocking) then the function should also617 // be declared noexcept.618 if (S.getLangOpts().CPlusPlus && !isExternC) {619 for (FunctionEffect Effect : CInfo.Effects) {620 if (!(Effect.flags() & FunctionEffect::FE_ExcludeThrow))621 continue;622 623 bool IsNoexcept = false;624 if (auto *FD = D->getAsFunction()) {625 IsNoexcept = isNoexcept(FD);626 } else if (auto *BD = dyn_cast<BlockDecl>(D)) {627 if (auto *TSI = BD->getSignatureAsWritten()) {628 auto *FPT = TSI->getType()->castAs<FunctionProtoType>();629 IsNoexcept = FPT->isNothrow() || BD->hasAttr<NoThrowAttr>();630 }631 }632 if (!IsNoexcept)633 S.Diag(D->getBeginLoc(), diag::warn_perf_constraint_implies_noexcept)634 << GetCallableDeclKind(D, nullptr) << Effect.name();635 break;636 }637 }638 639 // Build a PendingFunctionAnalysis on the stack. If it turns out to be640 // complete, we'll have avoided a heap allocation; if it's incomplete, it's641 // a fairly trivial move to a heap-allocated object.642 PendingFunctionAnalysis FAnalysis(S, CInfo, AllInferrableEffectsToVerify);643 644 LLVM_DEBUG(llvm::dbgs()645 << "\nVerifying " << CInfo.getNameForDiagnostic(S) << " ";646 FAnalysis.dump(S, llvm::dbgs()););647 648 FunctionBodyASTVisitor Visitor(*this, FAnalysis, CInfo);649 650 Visitor.run();651 if (FAnalysis.isComplete()) {652 completeAnalysis(CInfo, std::move(FAnalysis));653 return nullptr;654 }655 // Move the pending analysis to the heap and save it in the map.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()););661 return PendingPtr;662 }663 664 // Consume PendingFunctionAnalysis, create with it a CompleteFunctionAnalysis,665 // inserted in the container.666 void completeAnalysis(const CallableInfo &CInfo,667 PendingFunctionAnalysis &&Pending) {668 if (ArrayRef<Violation> Viols =669 Pending.getSortedViolationsForExplicitEffects(S.getSourceManager());670 !Viols.empty())671 emitDiagnostics(Viols, CInfo);672 673 CompleteFunctionAnalysis *CompletePtr = new CompleteFunctionAnalysis(674 S.getASTContext(), std::move(Pending), CInfo.Effects,675 AllInferrableEffectsToVerify);676 DeclAnalysis[CInfo.CDecl] = CompletePtr;677 LLVM_DEBUG(llvm::dbgs() << "inserted complete " << CompletePtr << "\n";678 DeclAnalysis.dump(S, llvm::dbgs()););679 }680 681 // Called after all direct calls requiring inference have been found -- or682 // not. Repeats calls to FunctionBodyASTVisitor::followCall() but without683 // the possibility of inference. Deletes Pending.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()) {691 if (Call.Recursed)692 continue;693 694 CallableInfo Callee(*Call.Callee);695 followCall(Caller, *Pending, Callee, Call.CallLoc,696 /*AssertNoFurtherInference=*/true, Call.VSite);697 }698 completeAnalysis(Caller, std::move(*Pending));699 delete Pending;700 }701 702 // Here we have a call to a Decl, either explicitly via a CallExpr or some703 // other AST construct. PFA pertains to the caller.704 void followCall(const CallableInfo &Caller, PendingFunctionAnalysis &PFA,705 const CallableInfo &Callee, SourceLocation CallLoc,706 bool AssertNoFurtherInference, ViolationSite VSite) {707 const bool DirectCall = Callee.isCalledDirectly();708 709 // Initially, the declared effects; inferred effects will be added.710 FunctionEffectKindSet CalleeEffects = Callee.Effects;711 712 bool IsInferencePossible = DirectCall;713 714 if (DirectCall)715 if (CompleteFunctionAnalysis *CFA =716 DeclAnalysis.completedAnalysisForDecl(Callee.CDecl)) {717 // Combine declared effects with those which may have been inferred.718 CalleeEffects.insert(CFA->VerifiedEffects);719 IsInferencePossible = false; // We've already traversed it.720 }721 722 if (AssertNoFurtherInference) {723 assert(!IsInferencePossible);724 }725 726 if (!Callee.isVerifiable())727 IsInferencePossible = false;728 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";);736 737 auto Check1Effect = [&](FunctionEffect Effect, bool Inferring) {738 if (!Effect.shouldDiagnoseFunctionCall(DirectCall, CalleeEffects))739 return;740 741 // If inference is not allowed, or the target is indirect (virtual742 // method/function ptr?), generate a Violation now.743 if (!IsInferencePossible ||744 !(Effect.flags() & FunctionEffect::FE_InferrableOnCallees)) {745 if (Callee.FuncType == SpecialFuncType::None)746 PFA.checkAddViolation(Inferring,747 {Effect, ViolationID::CallsDeclWithoutEffect,748 VSite, CallLoc, Callee.CDecl});749 else750 PFA.checkAddViolation(751 Inferring,752 {Effect, ViolationID::AllocatesMemory, VSite, CallLoc});753 } else {754 // Inference is allowed and necessary; defer it.755 PFA.addUnverifiedDirectCall(Callee.CDecl, CallLoc, VSite);756 }757 };758 759 for (FunctionEffect Effect : PFA.DeclaredVerifiableEffects)760 Check1Effect(Effect, false);761 762 for (FunctionEffect Effect : PFA.EffectsToInfer)763 Check1Effect(Effect, true);764 }765 766 // Describe a callable Decl for a diagnostic.767 // (Not an enum class because the value is always converted to an integer for768 // use in a diagnostic.)769 enum CallableDeclKind {770 CDK_Function,771 CDK_Constructor,772 CDK_Destructor,773 CDK_Lambda,774 CDK_Block,775 CDK_MemberInitializer,776 };777 778 // Describe a call site or target using an enum mapping to a %select{}779 // in a diagnostic, e.g. warn_func_effect_violation,780 // warn_perf_constraint_implies_noexcept, and others.781 static CallableDeclKind GetCallableDeclKind(const Decl *D,782 const Violation *V) {783 if (V != nullptr &&784 V->Site.kind() == ViolationSite::Kind::MemberInitializer)785 return CDK_MemberInitializer;786 if (isa<BlockDecl>(D))787 return CDK_Block;788 if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {789 if (isa<CXXConstructorDecl>(D))790 return CDK_Constructor;791 if (isa<CXXDestructorDecl>(D))792 return CDK_Destructor;793 const CXXRecordDecl *Rec = Method->getParent();794 if (Rec->isLambda())795 return CDK_Lambda;796 }797 return CDK_Function;798 };799 800 // Should only be called when function's analysis is determined to be801 // complete.802 void emitDiagnostics(ArrayRef<Violation> Viols, const CallableInfo &CInfo) {803 if (Viols.empty())804 return;805 806 auto MaybeAddTemplateNote = [&](const Decl *D) {807 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {808 while (FD != nullptr && FD->isTemplateInstantiation() &&809 FD->getPointOfInstantiation().isValid()) {810 S.Diag(FD->getPointOfInstantiation(),811 diag::note_func_effect_from_template);812 FD = FD->getTemplateInstantiationPattern();813 }814 }815 };816 817 // For note_func_effect_call_indirect.818 enum { Indirect_VirtualMethod, Indirect_FunctionPtr };819 820 auto MaybeAddSiteContext = [&](const Decl *D, const Violation &V) {821 // If a violation site is a member initializer, add a note pointing to822 // the constructor which invoked it.823 if (V.Site.kind() == ViolationSite::Kind::MemberInitializer) {824 unsigned ImplicitCtor = 0;825 if (auto *Ctor = dyn_cast<CXXConstructorDecl>(D);826 Ctor && Ctor->isImplicit())827 ImplicitCtor = 1;828 S.Diag(D->getLocation(), diag::note_func_effect_in_constructor)829 << ImplicitCtor;830 }831 832 // If a violation site is a default argument expression, add a note833 // pointing to the call site using the default argument.834 else if (V.Site.kind() == ViolationSite::Kind::DefaultArgExpr)835 S.Diag(V.Site.defaultArgExpr()->getUsedLocation(),836 diag::note_in_evaluating_default_argument);837 };838 839 // Top-level violations are warnings.840 for (const Violation &Viol1 : Viols) {841 StringRef effectName = Viol1.Effect.name();842 switch (Viol1.ID) {843 case ViolationID::None:844 case ViolationID::DeclDisallowsInference: // Shouldn't happen845 // here.846 llvm_unreachable("Unexpected violation kind");847 break;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) << effectName855 << Viol1.diagnosticSelectIndex();856 MaybeAddSiteContext(CInfo.CDecl, Viol1);857 MaybeAddTemplateNote(CInfo.CDecl);858 break;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);864 break;865 866 case ViolationID::CallsDeclWithoutEffect: {867 CallableInfo CalleeInfo(*Viol1.Callee);868 std::string CalleeName = CalleeInfo.getNameForDiagnostic(S);869 870 S.Diag(Viol1.Loc, diag::warn_func_effect_calls_func_without_effect)871 << GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName872 << GetCallableDeclKind(CalleeInfo.CDecl, nullptr) << CalleeName;873 MaybeAddSiteContext(CInfo.CDecl, Viol1);874 MaybeAddTemplateNote(CInfo.CDecl);875 876 // Emit notes explaining the transitive chain of inferences: Why isn't877 // the callee safe?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) {883 // No result - could be884 // - non-inline and extern885 // - indirect (virtual or through function pointer)886 // - effect has been explicitly disclaimed (e.g. "blocking")887 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) << effectName901 << FunctionEffect(Viol1.Effect.oppositeKind()).name();902 else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Callee);903 FD == nullptr || FD->getBuiltinID() == 0) {904 // A builtin callee generally doesn't have a useful source905 // location at which to insert a note.906 S.Diag(Callee->getLocation(), diag::note_func_effect_call_extern)907 << effectName;908 }909 break;910 }911 const Violation *PtrViol2 =912 Completed->firstViolationForEffect(Viol1.Effect);913 if (PtrViol2 == nullptr)914 break;915 916 const Violation &Viol2 = *PtrViol2;917 switch (Viol2.ID) {918 case ViolationID::None:919 llvm_unreachable("Unexpected violation kind");920 break;921 case ViolationID::DeclDisallowsInference:922 S.Diag(Viol2.Loc, diag::note_func_effect_call_disallows_inference)923 << GetCallableDeclKind(CalleeInfo.CDecl, nullptr) << effectName924 << Viol2.CalleeEffectPreventingInference->name();925 break;926 case ViolationID::CallsExprWithoutEffect:927 S.Diag(Viol2.Loc, diag::note_func_effect_call_indirect)928 << Indirect_FunctionPtr << effectName;929 break;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) << effectName937 << Viol2.diagnosticSelectIndex();938 MaybeAddSiteContext(CalleeInfo.CDecl, Viol2);939 break;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) << effectName944 << GetCallableDeclKind(Viol2.Callee, nullptr)945 << MaybeNextCallee->getNameForDiagnostic(S);946 break;947 }948 MaybeAddTemplateNote(Callee);949 Callee = Viol2.Callee;950 if (MaybeNextCallee) {951 CalleeInfo = *MaybeNextCallee;952 CalleeName = CalleeInfo.getNameForDiagnostic(S);953 }954 }955 } break;956 }957 }958 }959 960 // ----------961 // This AST visitor is used to traverse the body of a function during effect962 // verification. This happens in 2 situations:963 // [1] The function has declared effects which need to be validated.964 // [2] The function has not explicitly declared an effect in question, and is965 // being checked for implicit conformance.966 //967 // Violations are always routed to a PendingFunctionAnalysis.968 struct FunctionBodyASTVisitor : DynamicRecursiveASTVisitor {969 Analyzer &Outer;970 PendingFunctionAnalysis &CurrentFunction;971 CallableInfo &CurrentCaller;972 ViolationSite VSite;973 const Expr *TrailingRequiresClause = nullptr;974 const Expr *NoexceptExpr = nullptr;975 976 FunctionBodyASTVisitor(Analyzer &Outer,977 PendingFunctionAnalysis &CurrentFunction,978 CallableInfo &CurrentCaller)979 : Outer(Outer), CurrentFunction(CurrentFunction),980 CurrentCaller(CurrentCaller) {981 ShouldVisitImplicitCode = true;982 ShouldWalkTypesOfTypeLocs = false;983 }984 985 // -- Entry point --986 void run() {987 // The target function may have implicit code paths beyond the988 // body: member and base destructors. Visit these first.989 if (auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl))990 followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor);991 992 if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl)) {993 TrailingRequiresClause = FD->getTrailingRequiresClause().ConstraintExpr;994 995 // Note that FD->getType->getAs<FunctionProtoType>() can yield a996 // noexcept Expr which has been boiled down to a constant expression.997 // Going through the TypeSourceInfo obtains the actual expression which998 // will be traversed as part of the function -- unless we capture it999 // here and have TraverseStmt skip it.1000 if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) {1001 if (FunctionProtoTypeLoc TL =1002 TSI->getTypeLoc().getAs<FunctionProtoTypeLoc>())1003 if (const FunctionProtoType *FPT = TL.getTypePtr())1004 NoexceptExpr = FPT->getNoexceptExpr();1005 }1006 }1007 1008 // Do an AST traversal of the function/block body1009 TraverseDecl(const_cast<Decl *>(CurrentCaller.CDecl));1010 }1011 1012 // -- Methods implementing common logic --1013 1014 // Handle a language construct forbidden by some effects. Only effects whose1015 // flags include the specified flag receive a violation. \p Flag describes1016 // the construct.1017 void diagnoseLanguageConstruct(FunctionEffect::FlagBit Flag,1018 ViolationID VID, SourceLocation Loc,1019 const Decl *Callee = nullptr) {1020 // If there are any declared verifiable effects which forbid the construct1021 // represented by the flag, store just one violation.1022 for (FunctionEffect Effect : CurrentFunction.DeclaredVerifiableEffects) {1023 if (Effect.flags() & Flag) {1024 addViolation(/*inferring=*/false, Effect, VID, Loc, Callee);1025 break;1026 }1027 }1028 // For each inferred effect which forbids the construct, store a1029 // violation, if we don't already have a violation for that effect.1030 for (FunctionEffect Effect : CurrentFunction.EffectsToInfer)1031 if (Effect.flags() & Flag)1032 addViolation(/*inferring=*/true, Effect, VID, Loc, Callee);1033 }1034 1035 void addViolation(bool Inferring, FunctionEffect Effect, ViolationID VID,1036 SourceLocation Loc, const Decl *Callee = nullptr) {1037 CurrentFunction.checkAddViolation(1038 Inferring, Violation(Effect, VID, VSite, Loc, Callee));1039 }1040 1041 // Here we have a call to a Decl, either explicitly via a CallExpr or some1042 // other AST construct. CallableInfo pertains to the callee.1043 void followCall(CallableInfo &CI, SourceLocation CallLoc) {1044 // Check for a call to a builtin function, whose effects are1045 // handled specially.1046 if (const auto *FD = dyn_cast<FunctionDecl>(CI.CDecl)) {1047 if (unsigned BuiltinID = FD->getBuiltinID()) {1048 CI.Effects = getBuiltinFunctionEffects(BuiltinID);1049 if (CI.Effects.empty()) {1050 // A builtin with no known effects is assumed safe.1051 return;1052 }1053 // A builtin WITH effects doesn't get any special treatment for1054 // being noreturn/noexcept, e.g. longjmp(), so we skip the check1055 // below.1056 } else {1057 // If the callee is both `noreturn` and `noexcept`, it presumably1058 // terminates. Ignore it for the purposes of effect analysis.1059 // If not C++, `noreturn` alone is sufficient.1060 if (FD->isNoReturn() &&1061 (!Outer.S.getLangOpts().CPlusPlus || isNoexcept(FD)))1062 return;1063 }1064 }1065 1066 Outer.followCall(CurrentCaller, CurrentFunction, CI, CallLoc,1067 /*AssertNoFurtherInference=*/false, VSite);1068 }1069 1070 void checkIndirectCall(CallExpr *Call, QualType CalleeType) {1071 FunctionEffectKindSet CalleeEffects;1072 if (FunctionEffectsRef Effects = FunctionEffectsRef::get(CalleeType);1073 !Effects.empty())1074 CalleeEffects.insert(Effects);1075 1076 auto Check1Effect = [&](FunctionEffect Effect, bool Inferring) {1077 if (Effect.shouldDiagnoseFunctionCall(1078 /*direct=*/false, CalleeEffects))1079 addViolation(Inferring, Effect, ViolationID::CallsExprWithoutEffect,1080 Call->getBeginLoc());1081 };1082 1083 for (FunctionEffect Effect : CurrentFunction.DeclaredVerifiableEffects)1084 Check1Effect(Effect, false);1085 1086 for (FunctionEffect Effect : CurrentFunction.EffectsToInfer)1087 Check1Effect(Effect, true);1088 }1089 1090 // This destructor's body should be followed by the caller, but here we1091 // follow the field and base destructors.1092 void followDestructor(const CXXRecordDecl *Rec,1093 const CXXDestructorDecl *Dtor) {1094 SourceLocation DtorLoc = Dtor->getLocation();1095 for (const FieldDecl *Field : Rec->fields())1096 followTypeDtor(Field->getType(), DtorLoc);1097 1098 if (const auto *Class = dyn_cast<CXXRecordDecl>(Rec))1099 for (const CXXBaseSpecifier &Base : Class->bases())1100 followTypeDtor(Base.getType(), DtorLoc);1101 }1102 1103 void followTypeDtor(QualType QT, SourceLocation CallSite) {1104 const Type *Ty = QT.getTypePtr();1105 while (Ty->isArrayType()) {1106 const ArrayType *Arr = Ty->getAsArrayTypeUnsafe();1107 QT = Arr->getElementType();1108 Ty = QT.getTypePtr();1109 }1110 1111 if (Ty->isRecordType()) {1112 if (const CXXRecordDecl *Class = Ty->getAsCXXRecordDecl()) {1113 if (CXXDestructorDecl *Dtor = Class->getDestructor();1114 Dtor && !Dtor->isDeleted()) {1115 CallableInfo CI(*Dtor);1116 followCall(CI, CallSite);1117 }1118 }1119 }1120 }1121 1122 // -- Methods for use of RecursiveASTVisitor --1123 1124 bool VisitCXXThrowExpr(CXXThrowExpr *Throw) override {1125 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThrow,1126 ViolationID::ThrowsOrCatchesExceptions,1127 Throw->getThrowLoc());1128 return true;1129 }1130 1131 bool VisitCXXCatchStmt(CXXCatchStmt *Catch) override {1132 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,1133 ViolationID::ThrowsOrCatchesExceptions,1134 Catch->getCatchLoc());1135 return true;1136 }1137 1138 bool VisitObjCAtThrowStmt(ObjCAtThrowStmt *Throw) override {1139 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThrow,1140 ViolationID::ThrowsOrCatchesExceptions,1141 Throw->getThrowLoc());1142 return true;1143 }1144 1145 bool VisitObjCAtCatchStmt(ObjCAtCatchStmt *Catch) override {1146 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,1147 ViolationID::ThrowsOrCatchesExceptions,1148 Catch->getAtCatchLoc());1149 return true;1150 }1151 1152 bool VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Finally) override {1153 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,1154 ViolationID::ThrowsOrCatchesExceptions,1155 Finally->getAtFinallyLoc());1156 return true;1157 }1158 1159 bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) override {1160 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend,1161 ViolationID::AccessesObjCMethodOrProperty,1162 Msg->getBeginLoc());1163 return true;1164 }1165 1166 bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *ARP) override {1167 // Under the hood, @autorelease (potentially?) allocates memory and1168 // invokes ObjC methods. We don't currently have memory allocation as1169 // a "language construct" but we do have ObjC messaging, so diagnose that.1170 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend,1171 ViolationID::AccessesObjCMethodOrProperty,1172 ARP->getBeginLoc());1173 return true;1174 }1175 1176 bool VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Sync) override {1177 // Under the hood, this calls objc_sync_enter and objc_sync_exit, wrapped1178 // in a @try/@finally block. Diagnose this generically as "ObjC1179 // messaging".1180 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend,1181 ViolationID::AccessesObjCMethodOrProperty,1182 Sync->getBeginLoc());1183 return true;1184 }1185 1186 bool VisitSEHExceptStmt(SEHExceptStmt *Exc) override {1187 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,1188 ViolationID::ThrowsOrCatchesExceptions,1189 Exc->getExceptLoc());1190 return true;1191 }1192 1193 bool VisitCallExpr(CallExpr *Call) override {1194 LLVM_DEBUG(llvm::dbgs()1195 << "VisitCallExpr : "1196 << Call->getBeginLoc().printToString(Outer.S.SourceMgr)1197 << "\n";);1198 1199 Expr *CalleeExpr = Call->getCallee();1200 if (const Decl *Callee = CalleeExpr->getReferencedDeclOfCallee()) {1201 CallableInfo CI(*Callee);1202 followCall(CI, Call->getBeginLoc());1203 return true;1204 }1205 1206 if (isa<CXXPseudoDestructorExpr>(CalleeExpr)) {1207 // Just destroying a scalar, fine.1208 return true;1209 }1210 1211 // No Decl, just an Expr. Just check based on its type. Bound member1212 // functions are a special expression type and need to be specially1213 // unpacked.1214 QualType CalleeExprQT = CalleeExpr->getType();1215 if (CalleeExpr->isBoundMemberFunction(Outer.S.getASTContext())) {1216 QualType QT = Expr::findBoundMemberType(CalleeExpr);1217 if (!QT.isNull())1218 CalleeExprQT = QT;1219 }1220 checkIndirectCall(Call, CalleeExprQT);1221 1222 return true;1223 }1224 1225 bool VisitVarDecl(VarDecl *Var) override {1226 LLVM_DEBUG(llvm::dbgs()1227 << "VisitVarDecl : "1228 << Var->getBeginLoc().printToString(Outer.S.SourceMgr)1229 << "\n";);1230 1231 if (Var->isStaticLocal())1232 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeStaticLocalVars,1233 ViolationID::HasStaticLocalVariable,1234 Var->getLocation());1235 1236 const QualType::DestructionKind DK =1237 Var->needsDestruction(Outer.S.getASTContext());1238 if (DK == QualType::DK_cxx_destructor)1239 followTypeDtor(Var->getType(), Var->getLocation());1240 return true;1241 }1242 1243 bool VisitCXXNewExpr(CXXNewExpr *New) override {1244 // RecursiveASTVisitor does not visit the implicit call to operator new.1245 if (FunctionDecl *FD = New->getOperatorNew()) {1246 CallableInfo CI(*FD, SpecialFuncType::OperatorNew);1247 followCall(CI, New->getBeginLoc());1248 }1249 1250 // It's a bit excessive to check operator delete here, since it's1251 // just a fallback for operator new followed by a failed constructor.1252 // We could check it via New->getOperatorDelete().1253 1254 // It DOES however visit the called constructor1255 return true;1256 }1257 1258 bool VisitCXXDeleteExpr(CXXDeleteExpr *Delete) override {1259 // RecursiveASTVisitor does not visit the implicit call to operator1260 // delete.1261 if (FunctionDecl *FD = Delete->getOperatorDelete()) {1262 CallableInfo CI(*FD, SpecialFuncType::OperatorDelete);1263 followCall(CI, Delete->getBeginLoc());1264 }1265 1266 // It DOES however visit the called destructor1267 1268 return true;1269 }1270 1271 bool VisitCXXConstructExpr(CXXConstructExpr *Construct) override {1272 LLVM_DEBUG(llvm::dbgs() << "VisitCXXConstructExpr : "1273 << Construct->getBeginLoc().printToString(1274 Outer.S.SourceMgr)1275 << "\n";);1276 1277 // RecursiveASTVisitor does not visit the implicit call to the1278 // constructor.1279 const CXXConstructorDecl *Ctor = Construct->getConstructor();1280 CallableInfo CI(*Ctor);1281 followCall(CI, Construct->getLocation());1282 return true;1283 }1284 1285 bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *BTE) override {1286 const CXXDestructorDecl *Dtor = BTE->getTemporary()->getDestructor();1287 if (Dtor != nullptr) {1288 CallableInfo CI(*Dtor);1289 followCall(CI, BTE->getBeginLoc());1290 }1291 return true;1292 }1293 1294 bool TraverseStmt(Stmt *Statement) override {1295 // If this statement is a `requires` clause from the top-level function1296 // being traversed, ignore it, since it's not generating runtime code.1297 // We skip the traversal of lambdas (beyond their captures, see1298 // TraverseLambdaExpr below), so just caching this from our constructor1299 // should suffice.1300 if (Statement != TrailingRequiresClause && Statement != NoexceptExpr)1301 return DynamicRecursiveASTVisitor::TraverseStmt(Statement);1302 return true;1303 }1304 1305 bool TraverseCXXRecordDecl(CXXRecordDecl *D) override {1306 // Completely skip local struct/class/union declarations since their1307 // methods would otherwise be incorrectly interpreted as part of the1308 // function we are currently traversing. The initial Sema pass will have1309 // already recorded any nonblocking methods needing analysis.1310 return true;1311 }1312 1313 bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override {1314 ViolationSite PrevVS = VSite;1315 if (Init->isAnyMemberInitializer())1316 VSite.setKind(ViolationSite::Kind::MemberInitializer);1317 bool Result =1318 DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init);1319 VSite = PrevVS;1320 return Result;1321 }1322 1323 bool TraverseCXXDefaultArgExpr(CXXDefaultArgExpr *E) override {1324 LLVM_DEBUG(llvm::dbgs()1325 << "TraverseCXXDefaultArgExpr : "1326 << E->getUsedLocation().printToString(Outer.S.SourceMgr)1327 << "\n";);1328 1329 ViolationSite PrevVS = VSite;1330 if (VSite.kind() == ViolationSite::Kind::Default)1331 VSite = ViolationSite{E};1332 1333 bool Result = DynamicRecursiveASTVisitor::TraverseCXXDefaultArgExpr(E);1334 VSite = PrevVS;1335 return Result;1336 }1337 1338 bool TraverseLambdaExpr(LambdaExpr *Lambda) override {1339 // We override this so as to be able to skip traversal of the lambda's1340 // body. We have to explicitly traverse the captures. Why not return1341 // false from shouldVisitLambdaBody()? Because we need to visit a lambda's1342 // body when we are verifying the lambda itself; we only want to skip it1343 // in the context of the outer function.1344 for (unsigned I = 0, N = Lambda->capture_size(); I < N; ++I)1345 TraverseLambdaCapture(Lambda, Lambda->capture_begin() + I,1346 Lambda->capture_init_begin()[I]);1347 1348 return true;1349 }1350 1351 bool TraverseBlockExpr(BlockExpr * /*unused*/) override {1352 // As with lambdas, don't traverse the block's body.1353 // TODO: are the capture expressions (ctor call?) safe?1354 return true;1355 }1356 1357 bool VisitDeclRefExpr(DeclRefExpr *E) override {1358 const ValueDecl *Val = E->getDecl();1359 if (const auto *Var = dyn_cast<VarDecl>(Val)) {1360 if (Var->getTLSKind() != VarDecl::TLS_None) {1361 // At least on macOS, thread-local variables are initialized on1362 // first access, including a heap allocation.1363 diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThreadLocalVars,1364 ViolationID::AccessesThreadLocalVariable,1365 E->getLocation());1366 }1367 }1368 return true;1369 }1370 1371 bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) override {1372 return TraverseStmt(Node->getResultExpr());1373 }1374 bool1375 TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) override {1376 return true;1377 }1378 1379 bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node,1380 bool TraverseQualifier) override {1381 return true;1382 }1383 1384 bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node,1385 bool TraverseQualifier) override {1386 return true;1387 }1388 1389 bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override {1390 return true;1391 }1392 1393 bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) override { return true; }1394 1395 // Skip concept requirements since they don't generate code.1396 bool TraverseConceptRequirement(concepts::Requirement *R) override {1397 return true;1398 }1399 };1400};1401 1402Analyzer::AnalysisMap::~AnalysisMap() {1403 for (const auto &Item : *this) {1404 FuncAnalysisPtr AP = Item.second;1405 if (auto *PFA = dyn_cast<PendingFunctionAnalysis *>(AP))1406 delete PFA;1407 else1408 delete cast<CompleteFunctionAnalysis *>(AP);1409 }1410}1411 1412} // anonymous namespace1413 1414namespace clang {1415 1416bool Sema::diagnoseConflictingFunctionEffect(1417 const FunctionEffectsRef &FX, const FunctionEffectWithCondition &NewEC,1418 SourceLocation NewAttrLoc) {1419 // If the new effect has a condition, we can't detect conflicts until the1420 // condition is resolved.1421 if (NewEC.Cond.getCondition() != nullptr)1422 return false;1423 1424 // Diagnose the new attribute as incompatible with a previous one.1425 auto Incompatible = [&](const FunctionEffectWithCondition &PrevEC) {1426 Diag(NewAttrLoc, diag::err_attributes_are_not_compatible)1427 << ("'" + NewEC.description() + "'")1428 << ("'" + PrevEC.description() + "'") << false;1429 // We don't necessarily have the location of the previous attribute,1430 // so no note.1431 return true;1432 };1433 1434 // Compare against previous attributes.1435 FunctionEffect::Kind NewKind = NewEC.Effect.kind();1436 1437 for (const FunctionEffectWithCondition &PrevEC : FX) {1438 // Again, can't check yet when the effect is conditional.1439 if (PrevEC.Cond.getCondition() != nullptr)1440 continue;1441 1442 FunctionEffect::Kind PrevKind = PrevEC.Effect.kind();1443 // Note that we allow PrevKind == NewKind; it's redundant and ignored.1444 1445 if (PrevEC.Effect.oppositeKind() == NewKind)1446 return Incompatible(PrevEC);1447 1448 // A new allocating is incompatible with a previous nonblocking.1449 if (PrevKind == FunctionEffect::Kind::NonBlocking &&1450 NewKind == FunctionEffect::Kind::Allocating)1451 return Incompatible(PrevEC);1452 1453 // A new nonblocking is incompatible with a previous allocating.1454 if (PrevKind == FunctionEffect::Kind::Allocating &&1455 NewKind == FunctionEffect::Kind::NonBlocking)1456 return Incompatible(PrevEC);1457 }1458 1459 return false;1460}1461 1462void Sema::diagnoseFunctionEffectMergeConflicts(1463 const FunctionEffectSet::Conflicts &Errs, SourceLocation NewLoc,1464 SourceLocation OldLoc) {1465 for (const FunctionEffectSet::Conflict &Conflict : Errs) {1466 Diag(NewLoc, diag::warn_conflicting_func_effects)1467 << Conflict.Kept.description() << Conflict.Rejected.description();1468 Diag(OldLoc, diag::note_previous_declaration);1469 }1470}1471 1472// Decl should be a FunctionDecl or BlockDecl.1473void Sema::maybeAddDeclWithEffects(const Decl *D,1474 const FunctionEffectsRef &FX) {1475 if (!D->hasBody()) {1476 if (const auto *FD = D->getAsFunction(); FD && !FD->willHaveBody())1477 return;1478 }1479 1480 if (Diags.getIgnoreAllWarnings() ||1481 (Diags.getSuppressSystemWarnings() &&1482 SourceMgr.isInSystemHeader(D->getLocation())))1483 return;1484 1485 if (hasUncompilableErrorOccurred())1486 return;1487 1488 // For code in dependent contexts, we'll do this at instantiation time.1489 // Without this check, we would analyze the function based on placeholder1490 // template parameters, and potentially generate spurious diagnostics.1491 if (cast<DeclContext>(D)->isDependentContext())1492 return;1493 1494 addDeclWithEffects(D, FX);1495}1496 1497void Sema::addDeclWithEffects(const Decl *D, const FunctionEffectsRef &FX) {1498 // To avoid the possibility of conflict, don't add effects which are1499 // not FE_InferrableOnCallees and therefore not verified; this removes1500 // blocking/allocating but keeps nonblocking/nonallocating.1501 // Also, ignore any conditions when building the list of effects.1502 bool AnyVerifiable = false;1503 for (const FunctionEffectWithCondition &EC : FX)1504 if (EC.Effect.flags() & FunctionEffect::FE_InferrableOnCallees) {1505 AllEffectsToVerify.insert(EC.Effect);1506 AnyVerifiable = true;1507 }1508 1509 // Record the declaration for later analysis.1510 if (AnyVerifiable)1511 DeclsWithEffectsToVerify.push_back(D);1512}1513 1514void Sema::performFunctionEffectAnalysis(TranslationUnitDecl *TU) {1515 if (hasUncompilableErrorOccurred() || Diags.getIgnoreAllWarnings())1516 return;1517 if (TU == nullptr)1518 return;1519 Analyzer{*this}.run(*TU);1520}1521 1522Sema::FunctionEffectDiffVector::FunctionEffectDiffVector(1523 const FunctionEffectsRef &Old, const FunctionEffectsRef &New) {1524 1525 FunctionEffectsRef::iterator POld = Old.begin();1526 FunctionEffectsRef::iterator OldEnd = Old.end();1527 FunctionEffectsRef::iterator PNew = New.begin();1528 FunctionEffectsRef::iterator NewEnd = New.end();1529 1530 while (true) {1531 int cmp = 0;1532 if (POld == OldEnd) {1533 if (PNew == NewEnd)1534 break;1535 cmp = 1;1536 } else if (PNew == NewEnd)1537 cmp = -1;1538 else {1539 FunctionEffectWithCondition Old = *POld;1540 FunctionEffectWithCondition New = *PNew;1541 if (Old.Effect.kind() < New.Effect.kind())1542 cmp = -1;1543 else if (New.Effect.kind() < Old.Effect.kind())1544 cmp = 1;1545 else {1546 cmp = 0;1547 if (Old.Cond.getCondition() != New.Cond.getCondition()) {1548 // FIXME: Cases where the expressions are equivalent but1549 // don't have the same identity.1550 push_back(FunctionEffectDiff{1551 Old.Effect.kind(), FunctionEffectDiff::Kind::ConditionMismatch,1552 Old, New});1553 }1554 }1555 }1556 1557 if (cmp < 0) {1558 // removal1559 FunctionEffectWithCondition Old = *POld;1560 push_back(FunctionEffectDiff{Old.Effect.kind(),1561 FunctionEffectDiff::Kind::Removed, Old,1562 std::nullopt});1563 ++POld;1564 } else if (cmp > 0) {1565 // addition1566 FunctionEffectWithCondition New = *PNew;1567 push_back(FunctionEffectDiff{New.Effect.kind(),1568 FunctionEffectDiff::Kind::Added,1569 std::nullopt, New});1570 ++PNew;1571 } else {1572 ++POld;1573 ++PNew;1574 }1575 }1576}1577 1578bool Sema::FunctionEffectDiff::shouldDiagnoseConversion(1579 QualType SrcType, const FunctionEffectsRef &SrcFX, QualType DstType,1580 const FunctionEffectsRef &DstFX) const {1581 1582 switch (EffectKind) {1583 case FunctionEffect::Kind::NonAllocating:1584 // nonallocating can't be added (spoofed) during a conversion, unless we1585 // have nonblocking.1586 if (DiffKind == Kind::Added) {1587 for (const auto &CFE : SrcFX) {1588 if (CFE.Effect.kind() == FunctionEffect::Kind::NonBlocking)1589 return false;1590 }1591 }1592 [[fallthrough]];1593 case FunctionEffect::Kind::NonBlocking:1594 // nonblocking can't be added (spoofed) during a conversion.1595 switch (DiffKind) {1596 case Kind::Added:1597 return true;1598 case Kind::Removed:1599 return false;1600 case Kind::ConditionMismatch:1601 // FIXME: Condition mismatches are too coarse right now -- expressions1602 // which are equivalent but don't have the same identity are detected as1603 // mismatches. We're going to diagnose those anyhow until expression1604 // matching is better.1605 return true;1606 }1607 break;1608 case FunctionEffect::Kind::Blocking:1609 case FunctionEffect::Kind::Allocating:1610 return false;1611 }1612 llvm_unreachable("unknown effect kind");1613}1614 1615bool Sema::FunctionEffectDiff::shouldDiagnoseRedeclaration(1616 const FunctionDecl &OldFunction, const FunctionEffectsRef &OldFX,1617 const FunctionDecl &NewFunction, const FunctionEffectsRef &NewFX) const {1618 switch (EffectKind) {1619 case FunctionEffect::Kind::NonAllocating:1620 case FunctionEffect::Kind::NonBlocking:1621 // nonblocking/nonallocating can't be removed in a redeclaration.1622 switch (DiffKind) {1623 case Kind::Added:1624 return false; // No diagnostic.1625 case Kind::Removed:1626 return true; // Issue diagnostic.1627 case Kind::ConditionMismatch:1628 // All these forms of mismatches are diagnosed.1629 return true;1630 }1631 break;1632 case FunctionEffect::Kind::Blocking:1633 case FunctionEffect::Kind::Allocating:1634 return false;1635 }1636 llvm_unreachable("unknown effect kind");1637}1638 1639Sema::FunctionEffectDiff::OverrideResult1640Sema::FunctionEffectDiff::shouldDiagnoseMethodOverride(1641 const CXXMethodDecl &OldMethod, const FunctionEffectsRef &OldFX,1642 const CXXMethodDecl &NewMethod, const FunctionEffectsRef &NewFX) const {1643 switch (EffectKind) {1644 case FunctionEffect::Kind::NonAllocating:1645 case FunctionEffect::Kind::NonBlocking:1646 switch (DiffKind) {1647 1648 // If added on an override, that's fine and not diagnosed.1649 case Kind::Added:1650 return OverrideResult::NoAction;1651 1652 // If missing from an override (removed), propagate from base to derived.1653 case Kind::Removed:1654 return OverrideResult::Merge;1655 1656 // If there's a mismatch involving the effect's polarity or condition,1657 // issue a warning.1658 case Kind::ConditionMismatch:1659 return OverrideResult::Warn;1660 }1661 break;1662 case FunctionEffect::Kind::Blocking:1663 case FunctionEffect::Kind::Allocating:1664 return OverrideResult::NoAction;1665 }1666 llvm_unreachable("unknown effect kind");1667}1668 1669} // namespace clang1670