[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