Skip to content

Commit

Permalink
Merge pull request apple#96 from graydon/rdar-30851899-bridging-pch-m…
Browse files Browse the repository at this point in the history
…ergemodule-mismatch-swift-4.0-branch

Rdar 30851899 bridging pch mergemodule mismatch swift 4.0 branch
  • Loading branch information
graydon authored Jun 30, 2017
2 parents 2eb543a + 8108058 commit 1b4e1a7
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 14 deletions.
54 changes: 54 additions & 0 deletions include/clang/AST/Redeclarable.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,60 @@
namespace clang {
class ASTContext;

// Some notes on redeclarables:
//
// - Every redeclarable is on a circular linked list.
//
// - Every decl has a pointer to the first element of the chain _and_ a
// DeclLink that may point to one of 3 possible states:
// - the "previous" (temporal) element in the chain
// - the "latest" (temporal) element in the chain
// - the an "uninitialized-latest" value (when newly-constructed)
//
// - The first element is also often called the canonical element. Every
// element has a pointer to it so that "getCanonical" can be fast.
//
// - Most links in the chain point to previous, except the link out of
// the first; it points to latest.
//
// - Elements are called "first", "previous", "latest" or
// "most-recent" when referring to temporal order: order of addition
// to the chain.
//
// - To make matters confusing, the DeclLink type uses the term "next"
// for its pointer-storage internally (thus functions like
// NextIsPrevious). It's easiest to just ignore the implementation of
// DeclLink when making sense of the redeclaration chain.
//
// - There's also a "definition" link for several types of
// redeclarable, where only one definition should exist at any given
// time (and the defn pointer is stored in the decl's "data" which
// is copied to every element on the chain when it's changed).
//
// Here is some ASCII art:
//
// "first" "latest"
// "canonical" "most recent"
// +------------+ first +--------------+
// | | <--------------------------- | |
// | | | |
// | | | |
// | | +--------------+ | |
// | | first | | | |
// | | <---- | | | |
// | | | | | |
// | @class A | link | @interface A | link | @class A |
// | seen first | <---- | seen second | <---- | seen third |
// | | | | | |
// +------------+ +--------------+ +--------------+
// | data | defn | data | defn | data |
// | | ----> | | <---- | |
// +------------+ +--------------+ +--------------+
// | | ^ ^
// | |defn | |
// | link +-----+ |
// +-->-------------------------------------------+

/// \brief Provides common interface for the Decls that can be redeclared.
template<typename decl_type>
class Redeclarable {
Expand Down
49 changes: 35 additions & 14 deletions lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ namespace clang {
void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data);
void MergeDefinitionData(ObjCInterfaceDecl *D,
struct ObjCInterfaceDecl::DefinitionData &&NewDD);
void ReadObjCDefinitionData(struct ObjCProtocolDecl::DefinitionData &Data);
void MergeDefinitionData(ObjCProtocolDecl *D,
struct ObjCProtocolDecl::DefinitionData &&NewDD);

static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
DeclContext *DC,
Expand Down Expand Up @@ -1032,18 +1035,8 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
IVD->setSynthesize(synth);
}

void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
RedeclarableResult Redecl = VisitRedeclarable(PD);
VisitObjCContainerDecl(PD);
mergeRedeclarable(PD, Redecl);

if (Record.readInt()) {
// Read the definition.
PD->allocateDefinitionData();

// Set the definition data of the canonical declaration, so other
// redeclarations will see it.
PD->getCanonicalDecl()->Data = PD->Data;
void ASTDeclReader::ReadObjCDefinitionData(
struct ObjCProtocolDecl::DefinitionData &Data) {

unsigned NumProtoRefs = Record.readInt();
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
Expand All @@ -1054,9 +1047,37 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
ProtoLocs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoLocs.push_back(ReadSourceLocation());
PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
Reader.getContext());
Data.ReferencedProtocols.set(ProtoRefs.data(), NumProtoRefs,
ProtoLocs.data(), Reader.getContext());
}

void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D,
struct ObjCProtocolDecl::DefinitionData &&NewDD) {
// FIXME: odr checking?
}

void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
RedeclarableResult Redecl = VisitRedeclarable(PD);
VisitObjCContainerDecl(PD);
mergeRedeclarable(PD, Redecl);

if (Record.readInt()) {
// Read the definition.
PD->allocateDefinitionData();

ReadObjCDefinitionData(PD->data());

ObjCProtocolDecl *Canon = PD->getCanonicalDecl();
if (Canon->Data.getPointer()) {
// If we already have a definition, keep the definition invariant and
// merge the data.
MergeDefinitionData(Canon, std::move(PD->data()));
PD->Data = Canon->Data;
} else {
// Set the definition data of the canonical declaration, so other
// redeclarations will see it.
PD->getCanonicalDecl()->Data = PD->Data;
}
// Note that we have deserialized a definition.
Reader.PendingDefinitions.insert(PD);
} else {
Expand Down
3 changes: 3 additions & 0 deletions test/Modules/Inputs/lookup-assert-protocol/Base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@protocol BaseProtocol
- (void) test;
@end
4 changes: 4 additions & 0 deletions test/Modules/Inputs/lookup-assert-protocol/Derive.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "Base.h"
@protocol DerivedProtocol<BaseProtocol>
- (void) test2;
@end
1 change: 1 addition & 0 deletions test/Modules/Inputs/lookup-assert-protocol/H3.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "Base.h"
4 changes: 4 additions & 0 deletions test/Modules/Inputs/lookup-assert-protocol/module.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module X {
header "H3.h"
export *
}
17 changes: 17 additions & 0 deletions test/Modules/lookup-assert-protocol.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/lookup-assert-protocol %s -verify
// expected-no-diagnostics

#include "Derive.h"
#import <H3.h>

__attribute__((objc_root_class))
@interface Thing<DerivedProtocol>
@end

@implementation Thing
- (void)test {
}
- (void)test2 {
}
@end

0 comments on commit 1b4e1a7

Please sign in to comment.