================ @@ -5016,3 +5041,345 @@ void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getDeducedType(), getKeyword(), isDependentType(), getTypeConstraintConcept(), getTypeConstraintArguments()); } + +StringRef FunctionEffect::name() const { + switch (kind()) { + case Kind::NonBlocking: + return "nonblocking"; + case Kind::NonAllocating: + return "nonallocating"; + case Kind::None: + break; + } + llvm_unreachable("unknown effect kind"); +} + +bool FunctionEffectDiff::shouldDiagnoseConversion( + QualType SrcType, const FunctionEffectsRef &SrcFX, QualType DstType, + const FunctionEffectsRef &DstFX) const { + + switch (EffectKind) { + case FunctionEffect::Kind::NonAllocating: + // nonallocating can't be added (spoofed) during a conversion, unless we + // have nonblocking + if (DiffKind == Kind::Added) { + for (const auto &CFE : SrcFX) { + if (CFE.Effect.kind() == FunctionEffect::Kind::NonBlocking) + return false; + } + } + [[fallthrough]]; + case FunctionEffect::Kind::NonBlocking: + // nonblocking can't be added (spoofed) during a conversion. + switch (DiffKind) { + case Kind::Added: + return true; + case Kind::Removed: + return false; + case Kind::AssertToDeny: + // effect asserted -> denied: no diagnostic. + return false; + case Kind::DenyToAssert: + // effect denied -> asserted: diagnose. + return true; + case Kind::ConditionMismatch: + return true; // TODO: ??? + } + case FunctionEffect::Kind::None: + break; + } + llvm_unreachable("unknown effect kind"); +} + +bool FunctionEffectDiff::shouldDiagnoseRedeclaration( + const FunctionDecl &OldFunction, const FunctionEffectsRef &OldFX, + const FunctionDecl &NewFunction, const FunctionEffectsRef &NewFX) const { + switch (EffectKind) { + case FunctionEffect::Kind::NonAllocating: + case FunctionEffect::Kind::NonBlocking: + // nonblocking/nonallocating can't be removed in a redeclaration + switch (DiffKind) { + case Kind::Added: + return false; // No diagnostic. + case Kind::Removed: + return true; // Issue diagnostic + case Kind::DenyToAssert: + case Kind::AssertToDeny: + case Kind::ConditionMismatch: + // All these forms of mismatches are diagnosed. + return true; + } + case FunctionEffect::Kind::None: + break; + } + llvm_unreachable("unknown effect kind"); +} + +FunctionEffectDiff::OverrideResult +FunctionEffectDiff::shouldDiagnoseMethodOverride( + const CXXMethodDecl &OldMethod, const FunctionEffectsRef &OldFX, + const CXXMethodDecl &NewMethod, const FunctionEffectsRef &NewFX) const { + switch (EffectKind) { + case FunctionEffect::Kind::NonAllocating: + case FunctionEffect::Kind::NonBlocking: + switch (DiffKind) { + + // If added on an override, that's fine and not diagnosed. + case Kind::Added: + return OverrideResult::NoAction; + + // If missing from an override (removed), propagate from base to derived. + case Kind::Removed: + return OverrideResult::MergeAdded; + + // If there's a mismatch involving the effect's polarity or condition, + // issue a warning. + case Kind::DenyToAssert: + case Kind::AssertToDeny: + case Kind::ConditionMismatch: + return OverrideResult::Warn; + } + + case FunctionEffect::Kind::None: + break; + } + llvm_unreachable("unknown effect kind"); +} + +bool FunctionEffect::canInferOnFunction(const Decl &Callee) const { + switch (kind()) { + case Kind::NonAllocating: + case Kind::NonBlocking: + // Do any of the callee's Decls have type sugar for blocking or allocating? + for (const Decl *D : Callee.redecls()) { + QualType QT; + if (auto *FD = D->getAsFunction()) { + QT = FD->getType(); + } else if (auto *BD = dyn_cast<BlockDecl>(D)) { + if (auto *TSI = BD->getSignatureAsWritten()) + QT = TSI->getType(); + else + continue; + } else + continue; + + // c.f. Sema::getCallingConvAttributedType + const AttributedType *AT = QT->getAs<AttributedType>(); ---------------- dougsonos wrote:
TODO: update this for an all-canonical implementation 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