Skip to content

Commit a603fcb

Browse files
authored
swift-api-digester: More strict conditions when detecting member hoist API changes. [SR-5498] (#11091)
We observed several false positives of function hoist API changes. This patch strictly checks the new module doesn't contain a declaration with the identical name of the old function before hoisting to eliminate such false positives. This case is too complex to come up with an actual test case.
1 parent c45e85f commit a603fcb

File tree

1 file changed

+26
-65
lines changed

1 file changed

+26
-65
lines changed

tools/swift-api-digester/swift-api-digester.cpp

Lines changed: 26 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ class SDKNodeDecl : public SDKNode {
394394

395395
class SDKNodeRoot :public SDKNode {
396396
/// This keeps track of all decl descendants with USRs.
397-
llvm::StringMap<SDKNodeDecl*> DescendantDeclTable;
397+
llvm::StringMap<llvm::SmallSetVector<SDKNodeDecl*, 2>> DescendantDeclTable;
398398

399399
public:
400400
SDKNodeRoot(SDKNodeInitInfo Info) : SDKNode(Info, SDKNodeKind::Root) {}
@@ -403,13 +403,11 @@ class SDKNodeRoot :public SDKNode {
403403
void registerDescendant(SDKNode *D) {
404404
if (auto DD = dyn_cast<SDKNodeDecl>(D)) {
405405
assert(!DD->getUsr().empty());
406-
DescendantDeclTable[DD->getUsr()] = DD;
406+
DescendantDeclTable[DD->getUsr()].insert(DD);
407407
}
408408
}
409-
Optional<SDKNodeDecl*> getDescendantByUsr(StringRef Usr) {
410-
if (DescendantDeclTable.count(Usr))
411-
return DescendantDeclTable[Usr];
412-
return None;
409+
ArrayRef<SDKNodeDecl*> getDescendantsByUsr(StringRef Usr) {
410+
return DescendantDeclTable[Usr].getArrayRef();
413411
}
414412
};
415413

@@ -729,8 +727,9 @@ class SDKNodeTypeDecl : public SDKNodeDecl {
729727
Optional<SDKNodeTypeDecl*> getSuperclass() const {
730728
if (SuperclassUsr.empty())
731729
return None;
732-
if (auto SC = getRootNode()->getDescendantByUsr(SuperclassUsr)) {
733-
return (*SC)->getAs<SDKNodeTypeDecl>();
730+
auto Descendants = getRootNode()->getDescendantsByUsr(SuperclassUsr);
731+
if (!Descendants.empty()) {
732+
return Descendants.front()->getAs<SDKNodeTypeDecl>();
734733
}
735734
return None;
736735
}
@@ -2197,43 +2196,13 @@ class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass {
21972196
}
21982197
};
21992198

2200-
// For a given SDK node tree, this will build up a mapping from USR to node
2201-
using USRToNodeMap = llvm::StringMap<NodePtr, llvm::BumpPtrAllocator>;
2202-
2203-
// Class to build up mappings from USR to SDKNode
2204-
class MapUSRToNode : public SDKNodeVisitor {
2205-
friend class SDKNode; // for visit()
2206-
USRToNodeMap usrMap;
2207-
2208-
void visit(NodePtr ptr) override {
2209-
if (auto D = dyn_cast<SDKNodeDecl>(ptr)) {
2210-
usrMap[D->getUsr()] = ptr;
2211-
}
2212-
}
2213-
2214-
public:
2215-
MapUSRToNode() = default;
2216-
2217-
const USRToNodeMap &getMap() const { return usrMap; }
2218-
2219-
void map(NodePtr ptr) {
2220-
SDKNode::preorderVisit(ptr, *this);
2221-
}
2222-
2223-
void dump(llvm::raw_ostream &) const;
2224-
void dump() const { dump(llvm::errs()); }
2225-
2226-
private:
2227-
MapUSRToNode(MapUSRToNode &) = delete;
2228-
MapUSRToNode &operator=(MapUSRToNode &) = delete;
2229-
};
22302199

22312200
// Class to build up a diff of structurally different nodes, based on the given
22322201
// USR map for the left (original) side of the diff, based on parent types.
22332202
class TypeMemberDiffFinder : public SDKNodeVisitor {
22342203
friend class SDKNode; // for visit()
22352204

2236-
const USRToNodeMap &diffAgainst;
2205+
SDKNodeRoot *diffAgainst;
22372206

22382207
// Vector of {givenNodePtr, diffAgainstPtr}
22392208
NodePairVector TypeMemberDiffs;
@@ -2245,10 +2214,22 @@ class TypeMemberDiffFinder : public SDKNodeVisitor {
22452214
return;
22462215
auto usr = declNode->getUsr();
22472216
auto &usrName = usr;
2248-
if (!diffAgainst.count(usrName))
2217+
2218+
// If we can find no nodes in the other tree with the same usr, abort.
2219+
auto candidates = diffAgainst->getDescendantsByUsr(usrName);
2220+
if (candidates.empty())
22492221
return;
22502222

2251-
auto diffNode = diffAgainst.lookup(usrName);
2223+
// If any of the candidates has the same kind and name with the node, we
2224+
// shouldn't continue.
2225+
for (auto Can : candidates) {
2226+
if (Can->getKind() == declNode->getKind() &&
2227+
Can->getAs<SDKNodeDecl>()->getFullyQualifiedName() ==
2228+
declNode->getFullyQualifiedName())
2229+
return;
2230+
}
2231+
2232+
auto diffNode = candidates.front();
22522233
assert(node && diffNode && "nullptr visited?");
22532234
auto nodeParent = node->getParent();
22542235
auto diffParent = diffNode->getParent();
@@ -2261,9 +2242,7 @@ class TypeMemberDiffFinder : public SDKNodeVisitor {
22612242
// Move from a member variable to another member variable
22622243
if (nodeParent->getKind() == SDKNodeKind::TypeDecl &&
22632244
diffParent->getKind() == SDKNodeKind::TypeDecl &&
2264-
declNode->isStatic() &&
2265-
nodeParent->getAs<SDKNodeDecl>()->getFullyQualifiedName() !=
2266-
diffParent->getAs<SDKNodeDecl>()->getFullyQualifiedName())
2245+
declNode->isStatic())
22672246
TypeMemberDiffs.insert({diffNode, node});
22682247
// Move from a getter/setter function to a property
22692248
else if (node->getKind() == SDKNodeKind::Getter &&
@@ -2280,8 +2259,8 @@ class TypeMemberDiffFinder : public SDKNodeVisitor {
22802259
}
22812260

22822261
public:
2283-
TypeMemberDiffFinder(const USRToNodeMap &rightUSRMap)
2284-
: diffAgainst(rightUSRMap) {}
2262+
TypeMemberDiffFinder(SDKNodeRoot *diffAgainst):
2263+
diffAgainst(diffAgainst) {}
22852264

22862265
void findDiffsFor(NodePtr ptr) { SDKNode::preorderVisit(ptr, *this); }
22872266

@@ -2446,19 +2425,6 @@ static void printNode(llvm::raw_ostream &os, NodePtr node) {
24462425
os << "}";
24472426
}
24482427

2449-
void MapUSRToNode::dump(llvm::raw_ostream &os) const {
2450-
for (auto &elt : usrMap) {
2451-
auto &node = elt.getValue();
2452-
os << elt.getKey() << " ==> ";
2453-
printNode(os, node);
2454-
if (node->getParent()) {
2455-
os << " parent: ";
2456-
printNode(os, node->getParent());
2457-
}
2458-
os << "\n";
2459-
}
2460-
}
2461-
24622428
void TypeMemberDiffFinder::dump(llvm::raw_ostream &os) const {
24632429
for (auto pair : getDiffs()) {
24642430
os << " - ";
@@ -3102,12 +3068,7 @@ static Optional<uint8_t> findSelfIndex(SDKNode* Node) {
31023068
/// Find cases where a diff is due to a change to being a type member
31033069
static void findTypeMemberDiffs(NodePtr leftSDKRoot, NodePtr rightSDKRoot,
31043070
TypeMemberDiffVector &out) {
3105-
// Mapping from USR to SDKNode
3106-
MapUSRToNode leftMapper;
3107-
leftMapper.map(leftSDKRoot);
3108-
auto &leftMap = leftMapper.getMap();
3109-
3110-
TypeMemberDiffFinder diffFinder(leftMap);
3071+
TypeMemberDiffFinder diffFinder(cast<SDKNodeRoot>(leftSDKRoot));
31113072
diffFinder.findDiffsFor(rightSDKRoot);
31123073
RenameDetectorForMemberDiff Detector;
31133074
for (auto pair : diffFinder.getDiffs()) {

0 commit comments

Comments
 (0)