Skip to content

Add "whole SDK" validation test #69928

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions include/swift/APIDigester/ModuleAnalyzerNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,7 @@ class SDKContext {
ArrayRef<BreakingAttributeInfo> getBreakingAttributeInfo() const { return BreakingAttrs; }
llvm::Optional<uint8_t> getFixedBinaryOrder(ValueDecl *VD) const;

CompilerInstance &newCompilerInstance() {
CIs.emplace_back(new CompilerInstance());
return *CIs.back();
}
CompilerInstance &newCompilerInstance();
template<class YAMLNodeTy, typename ...ArgTypes>
void diagnose(YAMLNodeTy node, Diag<ArgTypes...> ID,
typename detail::PassArgument<ArgTypes>::type... args) {
Expand Down Expand Up @@ -856,6 +853,36 @@ void nodeSetDifference(ArrayRef<SDKNode*> Left, ArrayRef<SDKNode*> Right,
NodeVector &LeftMinusRight, NodeVector &RightMinusLeft);

bool hasValidParentPtr(SDKNodeKind kind);

/// A PrettyStackTraceEntry for performing an action involving an SDKNode.
///
/// The message is:
/// While <action> "<Node name>"\n
class PrettyStackTraceSDKNode : public llvm::PrettyStackTraceEntry {
protected:
const char *Action;
NodePtr Node;
public:
PrettyStackTraceSDKNode(const char *action, NodePtr node)
: Action(action), Node(node) {}

void print(llvm::raw_ostream &OS) const override;
void printNode(NodePtr node, llvm::raw_ostream &OS) const;
};

/// A PrettyStackTraceEntry for performing an action involving a pair of SDKNodes.
///
/// The message is:
/// While <action> "<Node name>" and "<Other node name>"\n
class PrettyStackTraceSDKNodes : public PrettyStackTraceSDKNode {
NodePtr OtherNode;
public:
PrettyStackTraceSDKNodes(const char *action, NodePtr node, NodePtr otherNode)
: PrettyStackTraceSDKNode(action, node), OtherNode(otherNode) {}

void print(llvm::raw_ostream &OS) const override;
};

} // end of abi namespace
} // end of ide namespace
} // end of Swift namespace
Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/DiagnosticsCommon.def
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ ERROR(sdk_node_unrecognized_node_kind,none,
"unrecognized SDK node kind '%0'", (StringRef))
ERROR(sdk_node_unrecognized_type_attr_kind,none,
"unrecognized type attribute '%0' in SDK node", (StringRef))
ERROR(sdk_node_unrecognized_decl_attr_kind,none,
"unrecognized declaration attribute '%0' in SDK node", (StringRef))
WARNING(sdk_node_unrecognized_decl_attr_kind,none,
"unrecognized declaration attribute '%0' in SDK node", (StringRef))
ERROR(sdk_node_unrecognized_decl_kind,none,
"unrecognized declaration kind '%0' in SDK node", (StringRef))
ERROR(sdk_node_unrecognized_accessor_kind,none,
Expand Down
77 changes: 77 additions & 0 deletions lib/APIDigester/ModuleAnalyzerNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ void SDKContext::addDiagConsumer(DiagnosticConsumer &Consumer) {
}
}

CompilerInstance &SDKContext::newCompilerInstance() {
CIs.emplace_back(new CompilerInstance());

// Add our existing diagnostic consumers to this new compiler instance.
// (Note that we do the opposite in addDiagConsumer().)
for (auto &consumer : Diags.getConsumers())
CIs.back()->addDiagnosticConsumer(consumer);

return *CIs.back();
}

void SDKNodeRoot::registerDescendant(SDKNode *D) {
// Operator doesn't have usr
if (isa<SDKNodeDeclOperator>(D))
Expand Down Expand Up @@ -728,6 +739,10 @@ SDKNode* SDKNode::constructSDKNode(SDKContext &Ctx,
auto Result = llvm::StringSwitch<DeclAttrKind>(GetScalarString(&N))
#define DECL_ATTR(_, NAME, ...) .Case(#NAME, DeclAttrKind::DAK_##NAME)
#include "swift/AST/Attr.def"
// BackDeployAttr was renamed to BackDeployedAttr, but not before a
// compiler shipped which used the old name in digests. Make the old
// name equivalent to the new one.
.Case("BackDeploy", DeclAttrKind::DAK_BackDeployed)
.Default(DeclAttrKind::DAK_Count);
if (Result == DAK_Count)
Ctx.diagnose(&N, diag::sdk_node_unrecognized_decl_attr_kind,
Expand Down Expand Up @@ -2608,6 +2623,8 @@ int swift::ide::api::deserializeSDKDump(StringRef dumpPath, StringRef OutputPath

SwiftDeclCollector Collector(Ctx);
Collector.deSerialize(dumpPath);
if (Ctx.getDiags().hadAnyError())
return 1;
Collector.serialize(FS);
return 0;
}
Expand Down Expand Up @@ -2672,6 +2689,9 @@ int swift::ide::api::findDeclUsr(StringRef dumpPath, CheckerOptions Opts) {
}

void swift::ide::api::SDKNodeDeclType::diagnose(SDKNode *Right) {
PrettyStackTraceSDKNodes trace(
"diagnosing changes between SDK nodes for type decls", this, Right);

SDKNodeDecl::diagnose(Right);
auto *R = dyn_cast<SDKNodeDeclType>(Right);
if (!R)
Expand Down Expand Up @@ -2721,6 +2741,10 @@ void swift::ide::api::SDKNodeDeclType::diagnose(SDKNode *Right) {
}

void swift::ide::api::SDKNodeDeclAbstractFunc::diagnose(SDKNode *Right) {
PrettyStackTraceSDKNodes trace(
"diagnosing changes between SDK nodes for abstract function decls",
this, Right);

SDKNodeDecl::diagnose(Right);
auto *R = dyn_cast<SDKNodeDeclAbstractFunc>(Right);
if (!R)
Expand Down Expand Up @@ -2754,6 +2778,9 @@ void swift::ide::api::SDKNodeDeclAbstractFunc::diagnose(SDKNode *Right) {
}

void swift::ide::api::SDKNodeDeclFunction::diagnose(SDKNode *Right) {
PrettyStackTraceSDKNodes trace(
"diagnosing changes between SDK nodes for func decls", this, Right);

SDKNodeDeclAbstractFunc::diagnose(Right);
auto *R = dyn_cast<SDKNodeDeclFunction>(Right);
if (!R)
Expand Down Expand Up @@ -2811,6 +2838,9 @@ void swift::ide::api::detectRename(SDKNode *L, SDKNode *R) {
}

void swift::ide::api::SDKNodeDecl::diagnose(SDKNode *Right) {
PrettyStackTraceSDKNodes trace(
"diagnosing changes between SDK nodes for decls", this, Right);

SDKNode::diagnose(Right);
auto *RD = dyn_cast<SDKNodeDecl>(Right);
if (!RD)
Expand Down Expand Up @@ -2871,6 +2901,10 @@ void swift::ide::api::SDKNodeDecl::diagnose(SDKNode *Right) {

// Diagnose removing attributes.
for (auto Kind: getDeclAttributes()) {
if (Kind == swift::DAK_Count)
// Unknown attribute, diagnosed elsewhere.
continue;

if (!RD->hasDeclAttribute(Kind)) {
if ((Ctx.checkingABI() ? DeclAttribute::isRemovingBreakingABI(Kind) :
DeclAttribute::isRemovingBreakingAPI(Kind)) &&
Expand All @@ -2883,6 +2917,10 @@ void swift::ide::api::SDKNodeDecl::diagnose(SDKNode *Right) {

// Diagnose adding attributes.
for (auto Kind: RD->getDeclAttributes()) {
if (Kind == swift::DAK_Count)
// Unknown attribute, diagnosed elsewhere.
continue;

if (!hasDeclAttribute(Kind)) {
if ((Ctx.checkingABI() ? DeclAttribute::isAddingBreakingABI(Kind) :
DeclAttribute::isAddingBreakingAPI(Kind)) &&
Expand Down Expand Up @@ -2910,10 +2948,14 @@ void swift::ide::api::SDKNodeDecl::diagnose(SDKNode *Right) {
}

void swift::ide::api::SDKNodeDeclOperator::diagnose(SDKNode *Right) {
PrettyStackTraceSDKNodes trace(
"diagnosing changes between SDK nodes for operators", this, Right);

SDKNodeDecl::diagnose(Right);
auto *RO = dyn_cast<SDKNodeDeclOperator>(Right);
if (!RO)
return;

auto Loc = RO->getLoc();
if (getDeclKind() != RO->getDeclKind()) {
emitDiag(Loc, diag::decl_kind_changed, getDeclKindStr(RO->getDeclKind(),
Expand All @@ -2922,6 +2964,9 @@ void swift::ide::api::SDKNodeDeclOperator::diagnose(SDKNode *Right) {
}

void swift::ide::api::SDKNodeDeclVar::diagnose(SDKNode *Right) {
PrettyStackTraceSDKNodes trace(
"diagnosing changes between SDK nodes for vars", this, Right);

SDKNodeDecl::diagnose(Right);
auto *RV = dyn_cast<SDKNodeDeclVar>(Right);
if (!RV)
Expand All @@ -2939,6 +2984,9 @@ static bool shouldDiagnoseType(SDKNodeType *T) {
}

void swift::ide::api::SDKNodeType::diagnose(SDKNode *Right) {
PrettyStackTraceSDKNodes trace(
"diagnosing changes between SDK nodes for types", this, Right);

SDKNode::diagnose(Right);
auto *RT = dyn_cast<SDKNodeType>(Right);
if (!RT || !shouldDiagnoseType(this))
Expand Down Expand Up @@ -2979,6 +3027,9 @@ void swift::ide::api::SDKNodeType::diagnose(SDKNode *Right) {
}

void swift::ide::api::SDKNodeTypeFunc::diagnose(SDKNode *Right) {
PrettyStackTraceSDKNodes trace(
"diagnosing changes between SDK nodes for func types", this, Right);

SDKNodeType::diagnose(Right);
auto *RT = dyn_cast<SDKNodeTypeFunc>(Right);
if (!RT || !shouldDiagnoseType(this))
Expand All @@ -2992,3 +3043,29 @@ void swift::ide::api::SDKNodeTypeFunc::diagnose(SDKNode *Right) {
isEscaping());
}
}

void PrettyStackTraceSDKNode::print(llvm::raw_ostream &out) const {
out << "While " << Action << ' ';
printNode(Node, out);
out << '\n';
}

void PrettyStackTraceSDKNode::printNode(NodePtr node, llvm::raw_ostream &out) const {
if (!node)
out << "<null>";
else if (auto declNode = dyn_cast<SDKNodeDecl>(node)) {
out << '"';
declNode->printFullyQualifiedName(out);
out << '"';
}
else
out << QuotedString(node->getPrintedName());
}

void PrettyStackTraceSDKNodes::print(llvm::raw_ostream &out) const {
out << "While " << Action << ' ';
printNode(Node, out);
out << " and ";
printNode(OtherNode, out);
out << '\n';
}
8 changes: 8 additions & 0 deletions lib/APIDigester/ModuleDiagsConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
//===----------------------------------------------------------------------===//

#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsClangImporter.h"
#include "swift/AST/DiagnosticsModuleDiffer.h"
#include "swift/APIDigester/ModuleDiagsConsumer.h"

Expand Down Expand Up @@ -145,6 +146,13 @@ bool swift::ide::api::FilteringDiagnosticConsumer::finishProcessing() {
}

bool swift::ide::api::FilteringDiagnosticConsumer::shouldProceed(const DiagnosticInfo &Info) {
// Suppress spurious warnings from imported headers. These were traditionally
// ignored because they were emitted before the diagnostic consumer was ready.
if (Info.ID == diag::warning_from_clang.ID ||
Info.ID == diag::remark_from_clang.ID ||
Info.ID == diag::note_from_clang.ID)
return false;

if (allowedBreakages->empty()) {
return true;
}
Expand Down
Loading