From ffa73cb4f85cff6607ee385d4b67446df167c2da Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Thu, 8 Nov 2018 15:42:59 -0800 Subject: [PATCH] Verify that a GenericTypeParamDecl's depth and index are correct Re-applied after fixing a bug in Serialization where the DeclContext wasn't being set correctly for extensions with nested parameters. I was unable to come up with a reduced test case, but the CoreStore project in the source compatibility suite was failing without the Serialization change, and now it isn't. --- lib/AST/ASTVerifier.cpp | 42 +++++++++++++++++++++++++++ lib/Serialization/Deserialization.cpp | 9 ++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index 37155a7f9692a..ac0416ec98f1b 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -2738,6 +2738,48 @@ class Verifier : public ASTWalker { verifyCheckedBase(nominal); } + void verifyCheckedAlways(GenericTypeParamDecl *GTPD) { + PrettyStackTraceDecl debugStack("verifying GenericTypeParamDecl", GTPD); + + const DeclContext *DC = GTPD->getDeclContext(); + if (!GTPD->getDeclContext()->isInnermostContextGeneric()) { + Out << "DeclContext of GenericTypeParamDecl does not have " + "generic params\n"; + abort(); + } + + GenericParamList *paramList = + static_cast(DC)->getGenericParams(); + if (!paramList) { + Out << "DeclContext of GenericTypeParamDecl does not have " + "generic params\n"; + abort(); + } + + unsigned currentDepth = paramList->getDepth(); + if (currentDepth < GTPD->getDepth()) { + Out << "GenericTypeParamDecl has incorrect depth\n"; + abort(); + } + while (currentDepth > GTPD->getDepth()) { + paramList = paramList->getOuterParameters(); + --currentDepth; + } + assert(paramList && "this is guaranteed by the parameter list's depth"); + + if (paramList->size() <= GTPD->getIndex() || + paramList->getParams()[GTPD->getIndex()] != GTPD) { + if (llvm::is_contained(paramList->getParams(), GTPD)) + Out << "GenericTypeParamDecl has incorrect index\n"; + else + Out << "GenericTypeParamDecl not found in GenericParamList; " + "incorrect depth or wrong DeclContext\n"; + abort(); + } + + verifyCheckedBase(GTPD); + } + void verifyChecked(ExtensionDecl *ext) { // Make sure that the protocol conformances are complete. for (auto conformance : ext->getLocalConformances()) { diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 74b39c9acbc5e..838d2e36163a2 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -2674,7 +2674,7 @@ ModuleFile::getDeclCheckedImpl(DeclID DID) { index); // Always create GenericTypeParamDecls in the associated module; - // maybeReadGenericParams() will reparent them. + // the real context will reparent them. auto DC = getAssociatedModule(); auto genericParam = createDecl(DC, getIdentifier(nameID), @@ -3936,9 +3936,12 @@ ModuleFile::getDeclCheckedImpl(DeclID DID) { // Generic parameter lists are written from outermost to innermost. // Keep reading until we run out of generic parameter lists. GenericParamList *outerParams = nullptr; - while (auto *genericParams = maybeReadGenericParams(DC, outerParams)) + while (auto *genericParams = maybeReadGenericParams(DC, outerParams)) { + // We do this repeatedly to set up the correct DeclContexts for the + // GenericTypeParamDecls in the list. + extension->setGenericParams(genericParams); outerParams = genericParams; - extension->setGenericParams(outerParams); + } configureGenericEnvironment(extension, genericEnvID);