From 35cb97b8ad5fc5f51beff2de3263efce571c5457 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Thu, 19 Aug 2021 22:27:14 -0700 Subject: [PATCH] ABIChecker: minor refactoring to move code to APIDigester lib. NFC --- .../swift/APIDigester/ModuleAnalyzerNodes.h | 5 + lib/APIDigester/ModuleAnalyzerNodes.cpp | 314 +++++++++++++++++ lib/DriverTool/swift_api_digester_main.cpp | 320 +----------------- lib/Frontend/CMakeLists.txt | 3 +- lib/Frontend/ModuleInterfaceBuilder.cpp | 1 + 5 files changed, 328 insertions(+), 315 deletions(-) diff --git a/include/swift/APIDigester/ModuleAnalyzerNodes.h b/include/swift/APIDigester/ModuleAnalyzerNodes.h index fc33958e210b9..964f09c26bceb 100644 --- a/include/swift/APIDigester/ModuleAnalyzerNodes.h +++ b/include/swift/APIDigester/ModuleAnalyzerNodes.h @@ -23,6 +23,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/FileSystem.h" @@ -787,6 +788,8 @@ class SwiftDeclCollector: public VisibleDeclConsumer { void lookupVisibleDecls(ArrayRef Modules); }; +void detectRename(SDKNode *L, SDKNode *R); + int dumpSwiftModules(const CompilerInvocation &InitInvok, const llvm::StringSet<> &ModuleNames, StringRef OutputDir, @@ -805,6 +808,8 @@ int dumpSDKContent(const CompilerInvocation &InitInvok, const llvm::StringSet<> &ModuleNames, StringRef OutputFile, CheckerOptions Opts); +void dumpModuleContent(ModuleDecl *MD, StringRef OutputFile, bool ABI); + /// Mostly for testing purposes, this function de-serializes the SDK dump in /// dumpPath and re-serialize them to OutputPath. If the tool performs correctly, /// the contents in dumpPath and OutputPath should be identical. diff --git a/lib/APIDigester/ModuleAnalyzerNodes.cpp b/lib/APIDigester/ModuleAnalyzerNodes.cpp index 1426a821b9ef4..81f20ca5cc880 100644 --- a/lib/APIDigester/ModuleAnalyzerNodes.cpp +++ b/lib/APIDigester/ModuleAnalyzerNodes.cpp @@ -2294,6 +2294,22 @@ int swift::ide::api::deserializeSDKDump(StringRef dumpPath, StringRef OutputPath return 0; } +void swift::ide::api::dumpModuleContent(ModuleDecl *MD, StringRef OutputFile, + bool ABI) { + CheckerOptions opts; + opts.ABI = ABI; + opts.SwiftOnly = true; + opts.AvoidLocation = true; + opts.AvoidToolArgs = true; + opts.Migrator = false; + opts.SkipOSCheck = false; + opts.Verbose = false; + SDKContext ctx(opts); + SwiftDeclCollector collector(ctx); + collector.lookupVisibleDecls({MD}); + dumpSDKRoot(collector.getSDKRoot(), OutputFile); +} + int swift::ide::api::findDeclUsr(StringRef dumpPath, CheckerOptions Opts) { std::error_code EC; if (!fs::exists(dumpPath)) { @@ -2323,3 +2339,301 @@ int swift::ide::api::findDeclUsr(StringRef dumpPath, CheckerOptions Opts) { } return 0; } + +void swift::ide::api::SDKNodeDeclType::diagnose(SDKNode *Right) { + SDKNodeDecl::diagnose(Right); + auto *R = dyn_cast(Right); + if (!R) + return; + auto Loc = R->getLoc(); + if (getDeclKind() != R->getDeclKind()) { + emitDiag(Loc, diag::decl_kind_changed, getDeclKindStr(R->getDeclKind(), + getSDKContext().getOpts().CompilerStyle)); + return; + } + + assert(getDeclKind() == R->getDeclKind()); + auto DKind = getDeclKind(); + switch (DKind) { + case DeclKind::Class: { + auto LSuperClass = getSuperClassName(); + auto RSuperClass = R->getSuperClassName(); + if (!LSuperClass.empty() && LSuperClass != RSuperClass) { + if (RSuperClass.empty()) { + emitDiag(Loc, diag::super_class_removed, LSuperClass); + } else if (!llvm::is_contained(R->getClassInheritanceChain(), LSuperClass)) { + emitDiag(Loc, diag::super_class_changed, LSuperClass, RSuperClass); + } + } + + // Check for @_hasMissingDesignatedInitializers and + // @_inheritsConvenienceInitializers changes. + if (isOpen() && R->isOpen()) { + // It's not safe to add new, invisible designated inits to open + // classes. + if (!hasMissingDesignatedInitializers() && + R->hasMissingDesignatedInitializers()) + R->emitDiag(R->getLoc(), diag::added_invisible_designated_init); + } + + // It's not safe to stop inheriting convenience inits, it changes + // the set of initializers that are available. + if (!Ctx.checkingABI() && + inheritsConvenienceInitializers() && + !R->inheritsConvenienceInitializers()) + R->emitDiag(R->getLoc(), diag::not_inheriting_convenience_inits); + break; + } + default: + break; + } +} + +void swift::ide::api::SDKNodeDeclAbstractFunc::diagnose(SDKNode *Right) { + SDKNodeDecl::diagnose(Right); + auto *R = dyn_cast(Right); + if (!R) + return; + auto Loc = R->getLoc(); + if (!isThrowing() && R->isThrowing()) { + emitDiag(Loc, diag::decl_new_attr, Ctx.buffer("throwing")); + } + if (Ctx.checkingABI()) { + if (reqNewWitnessTableEntry() != R->reqNewWitnessTableEntry()) { + emitDiag(Loc, diag::decl_new_witness_table_entry, reqNewWitnessTableEntry()); + } + } +} + +void swift::ide::api::SDKNodeDeclFunction::diagnose(SDKNode *Right) { + SDKNodeDeclAbstractFunc::diagnose(Right); + auto *R = dyn_cast(Right); + if (!R) + return; + auto Loc = R->getLoc(); + if (getSelfAccessKind() != R->getSelfAccessKind()) { + emitDiag(Loc, diag::func_self_access_change, getSelfAccessKind(), + R->getSelfAccessKind()); + } + if (Ctx.checkingABI()) { + if (hasFixedBinaryOrder() != R->hasFixedBinaryOrder()) { + emitDiag(Loc, diag::func_has_fixed_order_change, hasFixedBinaryOrder()); + } + } +} + +static StringRef getAttrName(DeclAttrKind Kind) { + switch (Kind) { +#define DECL_ATTR(NAME, CLASS, ...) \ + case DAK_##CLASS: \ + return DeclAttribute::isDeclModifier(DAK_##CLASS) ? #NAME : "@"#NAME; +#include "swift/AST/Attr.def" + case DAK_Count: + llvm_unreachable("unrecognized attribute kind."); + } + llvm_unreachable("covered switch"); +} + +static bool shouldDiagnoseAddingAttribute(SDKNodeDecl *D, DeclAttrKind Kind) { + return true; +} + +static bool shouldDiagnoseRemovingAttribute(SDKNodeDecl *D, DeclAttrKind Kind) { + return true; +} + +static bool isOwnershipEquivalent(ReferenceOwnership Left, + ReferenceOwnership Right) { + if (Left == Right) + return true; + if (Left == ReferenceOwnership::Unowned && Right == ReferenceOwnership::Weak) + return true; + if (Left == ReferenceOwnership::Weak && Right == ReferenceOwnership::Unowned) + return true; + return false; +} + +void swift::ide::api::detectRename(SDKNode *L, SDKNode *R) { + if (L->getKind() == R->getKind() && isa(L) && + L->getPrintedName() != R->getPrintedName()) { + L->annotate(NodeAnnotation::Rename); + L->annotate(NodeAnnotation::RenameOldName, L->getPrintedName()); + L->annotate(NodeAnnotation::RenameNewName, R->getPrintedName()); + } +} + +void swift::ide::api::SDKNodeDecl::diagnose(SDKNode *Right) { + SDKNode::diagnose(Right); + auto *RD = dyn_cast(Right); + if (!RD) + return; + detectRename(this, RD); + auto Loc = RD->getLoc(); + if (isOpen() && !RD->isOpen()) { + emitDiag(Loc, diag::no_longer_open); + } + + // Diagnose static attribute change. + if (isStatic() ^ RD->isStatic()) { + emitDiag(Loc, diag::decl_new_attr, Ctx.buffer(isStatic() ? "not static" : + "static")); + } + + // Diagnose ownership change. + if (!isOwnershipEquivalent(getReferenceOwnership(), + RD->getReferenceOwnership())) { + auto getOwnershipDescription = [&](swift::ReferenceOwnership O) { + if (O == ReferenceOwnership::Strong) + return Ctx.buffer("strong"); + return keywordOf(O); + }; + emitDiag(Loc, diag::decl_attr_change, + getOwnershipDescription(getReferenceOwnership()), + getOwnershipDescription(RD->getReferenceOwnership())); + } + // Diagnose generic signature change + if (getGenericSignature() != RD->getGenericSignature()) { + // Prefer sugared signature in diagnostics to be more user-friendly. + if (Ctx.commonVersionAtLeast(2) && + getSugaredGenericSignature() != RD->getSugaredGenericSignature()) { + emitDiag(Loc, diag::generic_sig_change, + getSugaredGenericSignature(), RD->getSugaredGenericSignature()); + } else { + emitDiag(Loc, diag::generic_sig_change, + getGenericSignature(), RD->getGenericSignature()); + } + } + + // ObjC name changes are considered breakage + if (getObjCName() != RD->getObjCName()) { + if (Ctx.commonVersionAtLeast(4)) { + emitDiag(Loc, diag::objc_name_change, getObjCName(), RD->getObjCName()); + } + } + + if (isOptional() != RD->isOptional()) { + if (Ctx.checkingABI()) { + // Both adding/removing optional is ABI-breaking. + emitDiag(Loc, diag::optional_req_changed, isOptional()); + } else if (isOptional()) { + // Removing optional is source-breaking. + emitDiag(Loc, diag::optional_req_changed, isOptional()); + } + } + + // Diagnose removing attributes. + for (auto Kind: getDeclAttributes()) { + if (!RD->hasDeclAttribute(Kind)) { + if ((Ctx.checkingABI() ? DeclAttribute::isRemovingBreakingABI(Kind) : + DeclAttribute::isRemovingBreakingAPI(Kind)) && + shouldDiagnoseRemovingAttribute(this, Kind)) { + emitDiag(Loc, diag::decl_new_attr, + Ctx.buffer((llvm::Twine("without ") + getAttrName(Kind)).str())); + } + } + } + + // Diagnose adding attributes. + for (auto Kind: RD->getDeclAttributes()) { + if (!hasDeclAttribute(Kind)) { + if ((Ctx.checkingABI() ? DeclAttribute::isAddingBreakingABI(Kind) : + DeclAttribute::isAddingBreakingAPI(Kind)) && + shouldDiagnoseAddingAttribute(this, Kind)) { + emitDiag(Loc, diag::decl_new_attr, + Ctx.buffer((llvm::Twine("with ") + getAttrName(Kind)).str())); + } + } + } + + if (Ctx.checkingABI()) { + if (hasFixedBinaryOrder() && RD->hasFixedBinaryOrder() && + getFixedBinaryOrder() != RD->getFixedBinaryOrder()) { + emitDiag(Loc, diag::decl_reorder, getFixedBinaryOrder(), + RD->getFixedBinaryOrder()); + } + } +} + +void swift::ide::api::SDKNodeDeclOperator::diagnose(SDKNode *Right) { + SDKNodeDecl::diagnose(Right); + auto *RO = dyn_cast(Right); + if (!RO) + return; + auto Loc = RO->getLoc(); + if (getDeclKind() != RO->getDeclKind()) { + emitDiag(Loc, diag::decl_kind_changed, getDeclKindStr(RO->getDeclKind(), + getSDKContext().getOpts().CompilerStyle)); + } +} + +void swift::ide::api::SDKNodeDeclVar::diagnose(SDKNode *Right) { + SDKNodeDecl::diagnose(Right); + auto *RV = dyn_cast(Right); + if (!RV) + return; + auto Loc = RV->getLoc(); + if (Ctx.checkingABI()) { + if (hasFixedBinaryOrder() != RV->hasFixedBinaryOrder()) { + emitDiag(Loc, diag::var_has_fixed_order_change, hasFixedBinaryOrder()); + } + } +} + +static bool shouldDiagnoseType(SDKNodeType *T) { + return T->isTopLevelType(); +} + +void swift::ide::api::SDKNodeType::diagnose(SDKNode *Right) { + SDKNode::diagnose(Right); + auto *RT = dyn_cast(Right); + if (!RT || !shouldDiagnoseType(this)) + return; + assert(isTopLevelType()); + + // Diagnose type witness changes when diagnosing ABI breakages. + if (auto *Wit = dyn_cast(getParent())) { + auto *Conform = Wit->getParent()->getAs(); + if (Ctx.checkingABI() && getPrintedName() != RT->getPrintedName()) { + auto *LD = Conform->getNominalTypeDecl(); + LD->emitDiag(SourceLoc(), diag::type_witness_change, + Wit->getWitnessedTypeName(), + getPrintedName(), RT->getPrintedName()); + } + return; + } + + StringRef Descriptor = getTypeRoleDescription(); + assert(isa(getParent())); + auto LParent = cast(getParent()); + assert(LParent->getKind() == RT->getParent()->getAs()->getKind()); + auto Loc = RT->getParent()->getAs()->getLoc(); + if (getPrintedName() != RT->getPrintedName()) { + LParent->emitDiag(Loc, diag::decl_type_change, + Descriptor, getPrintedName(), RT->getPrintedName()); + } + + if (hasDefaultArgument() && !RT->hasDefaultArgument()) { + LParent->emitDiag(Loc, diag::default_arg_removed, Descriptor); + } + if (getParamValueOwnership() != RT->getParamValueOwnership()) { + LParent->emitDiag(Loc, diag::param_ownership_change, + getTypeRoleDescription(), + getParamValueOwnership(), + RT->getParamValueOwnership()); + } +} + +void swift::ide::api::SDKNodeTypeFunc::diagnose(SDKNode *Right) { + SDKNodeType::diagnose(Right); + auto *RT = dyn_cast(Right); + if (!RT || !shouldDiagnoseType(this)) + return; + assert(isTopLevelType()); + auto Loc = RT->getParent()->getAs()->getLoc(); + if (Ctx.checkingABI() && isEscaping() != RT->isEscaping()) { + getParent()->getAs()->emitDiag(Loc, + diag::func_type_escaping_changed, + getTypeRoleDescription(), + isEscaping()); + } +} diff --git a/lib/DriverTool/swift_api_digester_main.cpp b/lib/DriverTool/swift_api_digester_main.cpp index 3bea7f3676ca9..60ba731bb5ef9 100644 --- a/lib/DriverTool/swift_api_digester_main.cpp +++ b/lib/DriverTool/swift_api_digester_main.cpp @@ -76,16 +76,6 @@ struct MatchedNodeListener { virtual ~MatchedNodeListener() = default; }; -template -bool contains(std::vector &container, T *instance) { - return std::find(container.begin(), container.end(), instance) != container.end(); -} - -template -bool contains(ArrayRef container, T instance) { - return std::find(container.begin(), container.end(), instance) != container.end(); -} - static void singleMatch(SDKNode* Left, SDKNode *Right, MatchedNodeListener &Listener) { @@ -184,7 +174,7 @@ class RemovedAddedNodeMatcher : public NodeMatcher, public MatchedNodeListener { void handleUnmatch(NodeVector &Matched, NodeVector &All, bool Left) { for (auto A : All) { - if (contains(Matched, A)) + if (llvm::is_contained(Matched, A)) continue; if (Left) Listener.foundMatch(A, nullptr, NodeMatchReason::Removed); @@ -381,12 +371,12 @@ class RemovedAddedNodeMatcher : public NodeMatcher, public MatchedNodeListener { NodeVector RenameRight; for (auto Remain : Removed) { - if (!contains(RemovedMatched, Remain)) + if (!llvm::is_contained(RemovedMatched, Remain)) RenameLeft.push_back(Remain); } for (auto Remain : Added) { - if (!contains(AddedMatched, Remain)) + if (!llvm::is_contained(AddedMatched, Remain)) RenameRight.push_back(Remain); } @@ -488,7 +478,7 @@ void SameNameNodeMatcher::match() { for (auto *RN : Right) { // If RN has matched before, ignore it. - if (contains(MatchedRight, RN)) + if (llvm::is_contained(MatchedRight, RN)) continue; // If LN and RN have the same name for some reason, keep track of RN. @@ -507,7 +497,7 @@ void SameNameNodeMatcher::match() { } } for (auto &R : Right) { - if (!contains(MatchedRight, R)) { + if (!llvm::is_contained(MatchedRight, R)) { Added.push_back(R); } } @@ -550,306 +540,8 @@ class SDKTreeDiffPass { virtual void pass(NodePtr Left, NodePtr Right) = 0; virtual ~SDKTreeDiffPass() {} }; - -static void detectRename(SDKNode *L, SDKNode *R) { - if (L->getKind() == R->getKind() && isa(L) && - L->getPrintedName() != R->getPrintedName()) { - L->annotate(NodeAnnotation::Rename); - L->annotate(NodeAnnotation::RenameOldName, L->getPrintedName()); - L->annotate(NodeAnnotation::RenameNewName, R->getPrintedName()); - } -} - -static bool isOwnershipEquivalent(ReferenceOwnership Left, - ReferenceOwnership Right) { - if (Left == Right) - return true; - if (Left == ReferenceOwnership::Unowned && Right == ReferenceOwnership::Weak) - return true; - if (Left == ReferenceOwnership::Weak && Right == ReferenceOwnership::Unowned) - return true; - return false; -} }// End of anonymous namespace -void swift::ide::api::SDKNodeDeclType::diagnose(SDKNode *Right) { - SDKNodeDecl::diagnose(Right); - auto *R = dyn_cast(Right); - if (!R) - return; - auto Loc = R->getLoc(); - if (getDeclKind() != R->getDeclKind()) { - emitDiag(Loc, diag::decl_kind_changed, getDeclKindStr(R->getDeclKind(), - getSDKContext().getOpts().CompilerStyle)); - return; - } - - assert(getDeclKind() == R->getDeclKind()); - auto DKind = getDeclKind(); - switch (DKind) { - case DeclKind::Class: { - auto LSuperClass = getSuperClassName(); - auto RSuperClass = R->getSuperClassName(); - if (!LSuperClass.empty() && LSuperClass != RSuperClass) { - if (RSuperClass.empty()) { - emitDiag(Loc, diag::super_class_removed, LSuperClass); - } else if (!contains(R->getClassInheritanceChain(), LSuperClass)) { - emitDiag(Loc, diag::super_class_changed, LSuperClass, RSuperClass); - } - } - - // Check for @_hasMissingDesignatedInitializers and - // @_inheritsConvenienceInitializers changes. - if (isOpen() && R->isOpen()) { - // It's not safe to add new, invisible designated inits to open - // classes. - if (!hasMissingDesignatedInitializers() && - R->hasMissingDesignatedInitializers()) - R->emitDiag(R->getLoc(), diag::added_invisible_designated_init); - } - - // It's not safe to stop inheriting convenience inits, it changes - // the set of initializers that are available. - if (!Ctx.checkingABI() && - inheritsConvenienceInitializers() && - !R->inheritsConvenienceInitializers()) - R->emitDiag(R->getLoc(), diag::not_inheriting_convenience_inits); - break; - } - default: - break; - } -} - -void swift::ide::api::SDKNodeDeclAbstractFunc::diagnose(SDKNode *Right) { - SDKNodeDecl::diagnose(Right); - auto *R = dyn_cast(Right); - if (!R) - return; - auto Loc = R->getLoc(); - if (!isThrowing() && R->isThrowing()) { - emitDiag(Loc, diag::decl_new_attr, Ctx.buffer("throwing")); - } - if (Ctx.checkingABI()) { - if (reqNewWitnessTableEntry() != R->reqNewWitnessTableEntry()) { - emitDiag(Loc, diag::decl_new_witness_table_entry, reqNewWitnessTableEntry()); - } - } -} - -void swift::ide::api::SDKNodeDeclFunction::diagnose(SDKNode *Right) { - SDKNodeDeclAbstractFunc::diagnose(Right); - auto *R = dyn_cast(Right); - if (!R) - return; - auto Loc = R->getLoc(); - if (getSelfAccessKind() != R->getSelfAccessKind()) { - emitDiag(Loc, diag::func_self_access_change, getSelfAccessKind(), - R->getSelfAccessKind()); - } - if (Ctx.checkingABI()) { - if (hasFixedBinaryOrder() != R->hasFixedBinaryOrder()) { - emitDiag(Loc, diag::func_has_fixed_order_change, hasFixedBinaryOrder()); - } - } -} - -static StringRef getAttrName(DeclAttrKind Kind) { - switch (Kind) { -#define DECL_ATTR(NAME, CLASS, ...) \ - case DAK_##CLASS: \ - return DeclAttribute::isDeclModifier(DAK_##CLASS) ? #NAME : "@"#NAME; -#include "swift/AST/Attr.def" - case DAK_Count: - llvm_unreachable("unrecognized attribute kind."); - } - llvm_unreachable("covered switch"); -} - -static bool shouldDiagnoseAddingAttribute(SDKNodeDecl *D, DeclAttrKind Kind) { - return true; -} - -static bool shouldDiagnoseRemovingAttribute(SDKNodeDecl *D, DeclAttrKind Kind) { - return true; -} - -void swift::ide::api::SDKNodeDecl::diagnose(SDKNode *Right) { - SDKNode::diagnose(Right); - auto *RD = dyn_cast(Right); - if (!RD) - return; - detectRename(this, RD); - auto Loc = RD->getLoc(); - if (isOpen() && !RD->isOpen()) { - emitDiag(Loc, diag::no_longer_open); - } - - // Diagnose static attribute change. - if (isStatic() ^ RD->isStatic()) { - emitDiag(Loc, diag::decl_new_attr, Ctx.buffer(isStatic() ? "not static" : - "static")); - } - - // Diagnose ownership change. - if (!isOwnershipEquivalent(getReferenceOwnership(), - RD->getReferenceOwnership())) { - auto getOwnershipDescription = [&](swift::ReferenceOwnership O) { - if (O == ReferenceOwnership::Strong) - return Ctx.buffer("strong"); - return keywordOf(O); - }; - emitDiag(Loc, diag::decl_attr_change, - getOwnershipDescription(getReferenceOwnership()), - getOwnershipDescription(RD->getReferenceOwnership())); - } - // Diagnose generic signature change - if (getGenericSignature() != RD->getGenericSignature()) { - // Prefer sugared signature in diagnostics to be more user-friendly. - if (Ctx.commonVersionAtLeast(2) && - getSugaredGenericSignature() != RD->getSugaredGenericSignature()) { - emitDiag(Loc, diag::generic_sig_change, - getSugaredGenericSignature(), RD->getSugaredGenericSignature()); - } else { - emitDiag(Loc, diag::generic_sig_change, - getGenericSignature(), RD->getGenericSignature()); - } - } - - // ObjC name changes are considered breakage - if (getObjCName() != RD->getObjCName()) { - if (Ctx.commonVersionAtLeast(4)) { - emitDiag(Loc, diag::objc_name_change, getObjCName(), RD->getObjCName()); - } - } - - if (isOptional() != RD->isOptional()) { - if (Ctx.checkingABI()) { - // Both adding/removing optional is ABI-breaking. - emitDiag(Loc, diag::optional_req_changed, isOptional()); - } else if (isOptional()) { - // Removing optional is source-breaking. - emitDiag(Loc, diag::optional_req_changed, isOptional()); - } - } - - // Diagnose removing attributes. - for (auto Kind: getDeclAttributes()) { - if (!RD->hasDeclAttribute(Kind)) { - if ((Ctx.checkingABI() ? DeclAttribute::isRemovingBreakingABI(Kind) : - DeclAttribute::isRemovingBreakingAPI(Kind)) && - shouldDiagnoseRemovingAttribute(this, Kind)) { - emitDiag(Loc, diag::decl_new_attr, - Ctx.buffer((llvm::Twine("without ") + getAttrName(Kind)).str())); - } - } - } - - // Diagnose adding attributes. - for (auto Kind: RD->getDeclAttributes()) { - if (!hasDeclAttribute(Kind)) { - if ((Ctx.checkingABI() ? DeclAttribute::isAddingBreakingABI(Kind) : - DeclAttribute::isAddingBreakingAPI(Kind)) && - shouldDiagnoseAddingAttribute(this, Kind)) { - emitDiag(Loc, diag::decl_new_attr, - Ctx.buffer((llvm::Twine("with ") + getAttrName(Kind)).str())); - } - } - } - - if (Ctx.checkingABI()) { - if (hasFixedBinaryOrder() && RD->hasFixedBinaryOrder() && - getFixedBinaryOrder() != RD->getFixedBinaryOrder()) { - emitDiag(Loc, diag::decl_reorder, getFixedBinaryOrder(), - RD->getFixedBinaryOrder()); - } - } -} - -void swift::ide::api::SDKNodeDeclOperator::diagnose(SDKNode *Right) { - SDKNodeDecl::diagnose(Right); - auto *RO = dyn_cast(Right); - if (!RO) - return; - auto Loc = RO->getLoc(); - if (getDeclKind() != RO->getDeclKind()) { - emitDiag(Loc, diag::decl_kind_changed, getDeclKindStr(RO->getDeclKind(), - getSDKContext().getOpts().CompilerStyle)); - } -} - -void swift::ide::api::SDKNodeDeclVar::diagnose(SDKNode *Right) { - SDKNodeDecl::diagnose(Right); - auto *RV = dyn_cast(Right); - if (!RV) - return; - auto Loc = RV->getLoc(); - if (Ctx.checkingABI()) { - if (hasFixedBinaryOrder() != RV->hasFixedBinaryOrder()) { - emitDiag(Loc, diag::var_has_fixed_order_change, hasFixedBinaryOrder()); - } - } -} - -static bool shouldDiagnoseType(SDKNodeType *T) { - return T->isTopLevelType(); -} - -void swift::ide::api::SDKNodeType::diagnose(SDKNode *Right) { - SDKNode::diagnose(Right); - auto *RT = dyn_cast(Right); - if (!RT || !shouldDiagnoseType(this)) - return; - assert(isTopLevelType()); - - // Diagnose type witness changes when diagnosing ABI breakages. - if (auto *Wit = dyn_cast(getParent())) { - auto *Conform = Wit->getParent()->getAs(); - if (Ctx.checkingABI() && getPrintedName() != RT->getPrintedName()) { - auto *LD = Conform->getNominalTypeDecl(); - LD->emitDiag(SourceLoc(), diag::type_witness_change, - Wit->getWitnessedTypeName(), - getPrintedName(), RT->getPrintedName()); - } - return; - } - - StringRef Descriptor = getTypeRoleDescription(); - assert(isa(getParent())); - auto LParent = cast(getParent()); - assert(LParent->getKind() == RT->getParent()->getAs()->getKind()); - auto Loc = RT->getParent()->getAs()->getLoc(); - if (getPrintedName() != RT->getPrintedName()) { - LParent->emitDiag(Loc, diag::decl_type_change, - Descriptor, getPrintedName(), RT->getPrintedName()); - } - - if (hasDefaultArgument() && !RT->hasDefaultArgument()) { - LParent->emitDiag(Loc, diag::default_arg_removed, Descriptor); - } - if (getParamValueOwnership() != RT->getParamValueOwnership()) { - LParent->emitDiag(Loc, diag::param_ownership_change, - getTypeRoleDescription(), - getParamValueOwnership(), - RT->getParamValueOwnership()); - } -} - -void swift::ide::api::SDKNodeTypeFunc::diagnose(SDKNode *Right) { - SDKNodeType::diagnose(Right); - auto *RT = dyn_cast(Right); - if (!RT || !shouldDiagnoseType(this)) - return; - assert(isTopLevelType()); - auto Loc = RT->getParent()->getAs()->getLoc(); - if (Ctx.checkingABI() && isEscaping() != RT->isEscaping()) { - getParent()->getAs()->emitDiag(Loc, - diag::func_type_escaping_changed, - getTypeRoleDescription(), - isEscaping()); - } -} - namespace { static void diagnoseRemovedDecl(const SDKNodeDecl *D) { if (D->getSDKContext().checkingABI()) { @@ -2046,7 +1738,7 @@ class RenameDetectorForMemberDiff : public MatchedNodeListener { void foundMatch(NodePtr Left, NodePtr Right, NodeMatchReason Reason) override { if (!Left || !Right) return; - detectRename(Left, Right); + swift::ide::api::detectRename(Left, Right); LeftDetector.detect(Left, Right); RightDetector.detect(Right, Left); } diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 042de40c4f06a..b883676afe17f 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -27,6 +27,7 @@ target_link_libraries(swiftFrontend PRIVATE swiftLocalization swiftSema swiftSerialization - swiftTBDGen) + swiftTBDGen + swiftAPIDigester) set_swift_llvm_is_available(swiftFrontend) diff --git a/lib/Frontend/ModuleInterfaceBuilder.cpp b/lib/Frontend/ModuleInterfaceBuilder.cpp index a8a00bdae4562..26d91613a93cb 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.cpp +++ b/lib/Frontend/ModuleInterfaceBuilder.cpp @@ -24,6 +24,7 @@ #include "swift/Frontend/ModuleInterfaceSupport.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/Serialization/SerializationOptions.h" +#include "swift/APIDigester/ModuleAnalyzerNodes.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/Hashing.h"