[cfe-commits] r147488 - in /cfe/trunk: lib/Serialization/ASTReaderDecl.cpp test/Modules/Inputs/redecl-merge-bottom.h test/Modules/Inputs/redecl-merge-left.h test/Modules/Inputs/redecl-merge-right.h test/Modules/Inputs/redecl-merge-top.h test/Modules/redecl-merge.m
Douglas Gregor
dgregor at apple.com
Tue Jan 3 14:46:00 PST 2012
Author: dgregor
Date: Tue Jan 3 16:46:00 2012
New Revision: 147488
URL: http://llvm.org/viewvc/llvm-project?rev=147488&view=rev
Log:
Implement cross-module declaration merging for tag declarations, so
that if two modules A and B both contain a declaration of a tag such
as
struct X;
and those two modules are unrelated, the two declarations of X will be
merged into a single redeclaration chain.
Modified:
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h
cfe/trunk/test/Modules/Inputs/redecl-merge-left.h
cfe/trunk/test/Modules/Inputs/redecl-merge-right.h
cfe/trunk/test/Modules/Inputs/redecl-merge-top.h
cfe/trunk/test/Modules/redecl-merge.m
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=147488&r1=147487&r2=147488&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Jan 3 16:46:00 2012
@@ -182,6 +182,10 @@
~FindExistingResult();
+ /// \brief Suppress the addition of this result into the known set of
+ /// names.
+ void suppress() { AddResult = false; }
+
operator NamedDecl*() const { return Existing; }
template<typename T>
@@ -412,20 +416,27 @@
}
void ASTDeclReader::VisitTagDecl(TagDecl *TD) {
- VisitRedeclarable(TD);
+ // Record the declaration -> global ID mapping.
+ Reader.DeclToID[TD] = ThisDeclID;
+
+ RedeclarableResult Redecl = VisitRedeclarable(TD);
VisitTypeDecl(TD);
+
TD->IdentifierNamespace = Record[Idx++];
TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
TD->setCompleteDefinition(Record[Idx++]);
TD->setEmbeddedInDeclarator(Record[Idx++]);
TD->setFreeStanding(Record[Idx++]);
TD->setRBraceLoc(ReadSourceLocation(Record, Idx));
+
if (Record[Idx++]) { // hasExtInfo
TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo();
ReadQualifierInfo(*Info, Record, Idx);
TD->TypedefNameDeclOrQualifier = Info;
} else
TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx));
+
+ mergeRedeclarable(TD, Redecl);
}
void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
@@ -1547,6 +1558,14 @@
if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
== Merged.end())
Merged.push_back(Redecl.getFirstID());
+
+ // If ExistingCanon did not come from a module file, introduce the
+ // first declaration that *does* come from a module file is in the
+ // set of pending declaration chains, so that we merge this
+ // declaration.
+ if (!ExistingCanon->isFromASTFile() &&
+ Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID()))
+ Reader.PendingDeclChains.push_back(Merged[0]);
}
}
}
@@ -1662,6 +1681,15 @@
if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
return true;
+ // Compatible tags match.
+ if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
+ TagDecl *TagY = cast<TagDecl>(Y);
+ if ((TagX->getTagKind() == TagY->getTagKind()) ||
+ ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class)&&
+ (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class)))
+ return true;
+ }
+
// FIXME: Many other cases to implement.
return false;
}
@@ -1679,13 +1707,21 @@
}
ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
+ DeclarationName Name = D->getDeclName();
+ if (!Name) {
+ // Don't bother trying to find unnamed declarations.
+ FindExistingResult Result(Reader, D, /*Existing=*/0);
+ Result.suppress();
+ return Result;
+ }
+
DeclContext *DC = D->getDeclContext()->getRedeclContext();
if (!DC->isFileContext())
return FindExistingResult(Reader);
if (DC->isTranslationUnit() && Reader.SemaObj) {
IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
- for (IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()),
+ for (IdentifierResolver::iterator I = IdResolver.begin(Name),
IEnd = IdResolver.end();
I != IEnd; ++I) {
if (isSameEntity(*I, D))
Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h?rev=147488&r1=147487&r2=147488&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h Tue Jan 3 16:46:00 2012
@@ -13,6 +13,9 @@
@protocol P1;
+struct S1;
+struct S3;
+
void refers_to_C4(C4*);
#ifdef __cplusplus
Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-left.h?rev=147488&r1=147487&r2=147488&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-left.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-left.h Tue Jan 3 16:46:00 2012
@@ -15,6 +15,14 @@
- (void)protoMethod2;
@end
+struct S1;
+struct S2 {
+ int field;
+};
+
+struct S1 *produce_S1(void);
+void consume_S2(struct S2*);
+
// Test declarations in different modules with no common initial
// declaration.
@class C;
@@ -39,6 +47,15 @@
@protocol P3;
+struct S3;
+struct S3;
+struct S4 {
+ int field;
+};
+
+struct S3 *produce_S3(void);
+void consume_S4(struct S4*);
+
#ifdef __cplusplus
template<typename T> class Vector;
Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-right.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-right.h?rev=147488&r1=147487&r2=147488&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-right.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-right.h Tue Jan 3 16:46:00 2012
@@ -21,6 +21,12 @@
@protocol P2;
+struct S1;
+struct S2;
+
+void consume_S1(struct S1*);
+struct S2 *produce_S2(void);
+
// Test declarations in different modules with no common initial
// declaration.
@class C;
@@ -47,6 +53,12 @@
@protocol P3;
@protocol P3;
+struct S3;
+struct S4;
+
+void consume_S3(struct S3*);
+struct S4 *produce_S4(void);
+
#ifdef __cplusplus
template<typename T> class Vector {
public:
Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-top.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-top.h?rev=147488&r1=147487&r2=147488&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-top.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-top.h Tue Jan 3 16:46:00 2012
@@ -11,6 +11,10 @@
@protocol P2;
@protocol P2;
+struct S1;
+struct S2;
+struct S2;
+
#ifdef __cplusplus
template<typename T> class Vector;
#endif
Modified: cfe/trunk/test/Modules/redecl-merge.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/redecl-merge.m?rev=147488&r1=147487&r2=147488&view=diff
==============================================================================
--- cfe/trunk/test/Modules/redecl-merge.m (original)
+++ cfe/trunk/test/Modules/redecl-merge.m Tue Jan 3 16:46:00 2012
@@ -32,6 +32,29 @@
[p2 protoMethod2];
}
+struct S1 {
+ int s1_field;
+};
+
+struct S3 {
+ int s3_field;
+};
+
+void testTagMerge() {
+ consume_S1(produce_S1());
+ struct S2 s2;
+ s2.field = 0;
+ consume_S2(produce_S2());
+ struct S1 s1;
+ s1.s1_field = 0;
+ consume_S3(produce_S3());
+ struct S4 s4;
+ s4.field = 0;
+ consume_S4(produce_S4());
+ struct S3 s3;
+ s3.s3_field = 0;
+}
+
// Test redeclarations of entities in explicit submodules, to make
// sure we're maintaining the declaration chains even when normal name
// lookup can't see what we're looking for.
More information about the cfe-commits
mailing list