[Parse] Stop ignoring private decls for incremental purposes. (#3352)

We'd really like to say that private decls can't affect other files,
but we don't have enough information at parse-time:

- Private members of non-private classes still show up in vtables,
  which affects subclasses and callers in other files.

- Private stored properties of non-private structs change the
  layout of the struct.

- Private types may be used in private stored properties, affecting
  the layout of the containing struct.

- Private decls of /any kind/ can be used as the initial value of a
  stored property without an explicit type.

    private class Evil {
      class func defaultAlignment() -> Alignment { return .evil }
    }
    public struct Character {
      // Inferred type here!
      private var alignment = Evil.defaultAlignment()
    }

To be safe and correct, go back to only ignoring method bodies.

https://bugs.swift.org/browse/SR-1030
This commit is contained in:
Jordan Rose
2016-07-06 12:32:06 -07:00
committed by GitHub
parent 64d998d4d8
commit 396c9f23b4
10 changed files with 173 additions and 39 deletions

View File

@@ -170,40 +170,6 @@ namespace {
P.markWasHandled(D);
}
};
/// An RAII type to exclude tokens contributing to private decls from the
/// interface hash of the source file. On destruct, it checks if the set of
/// attributes includes the "private" attribute; if so, it resets the MD5
/// hash of the source file to what it was when the IgnorePrivateDeclTokens
/// instance was created, thus excluding from the interface hash all tokens
/// parsed in the meantime.
struct IgnorePrivateDeclTokens {
Parser &TheParser;
DeclAttributes &Attributes;
Optional<llvm::MD5> SavedHashState;
IgnorePrivateDeclTokens(Parser &P, DeclAttributes &Attrs)
: TheParser(P), Attributes(Attrs) {
// NOTE: It's generally not safe to ignore private decls in nominal
// types. Such private decls may affect the data layout of a class/struct
// or the vtable layout of a class. So only ignore global private decls.
if (TheParser.IsParsingInterfaceTokens &&
TheParser.CurDeclContext->isModuleScopeContext()) {
SavedHashState = TheParser.SF.getInterfaceHashState();
}
}
~IgnorePrivateDeclTokens() {
if (!SavedHashState)
return;
if (auto *attr = Attributes.getAttribute<AbstractAccessibilityAttr>()) {
if (attr->getAccess() == Accessibility::Private) {
TheParser.SF.setInterfaceHashState(*SavedHashState);
}
}
}
};
}
/// \brief Main entrypoint for the parser.
@@ -1905,6 +1871,7 @@ ParserStatus Parser::parseDecl(ParseDeclOptions Flags,
LastDecl = D;
Handler(D);
};
ParserPosition BeginParserPosition;
if (isCodeCompletionFirstPass())
BeginParserPosition = getParserPosition();
@@ -1917,7 +1884,6 @@ ParserStatus Parser::parseDecl(ParseDeclOptions Flags,
StructureMarkerKind::Declaration);
DeclAttributes Attributes;
IgnorePrivateDeclTokens IgnoreTokens(*this, Attributes);
if (Tok.hasComment())
Attributes.add(new (Context) RawDocCommentAttr(Tok.getCommentRange()));
bool FoundCCTokenInAttr;