[cfe-commits] r160395 - in /cfe/trunk: include/clang/AST/ASTImporter.h lib/AST/ASTImporter.cpp lib/AST/DeclBase.cpp

Douglas Gregor dgregor at apple.com
Tue Jul 17 14:16:27 PDT 2012


Author: dgregor
Date: Tue Jul 17 16:16:27 2012
New Revision: 160395

URL: http://llvm.org/viewvc/llvm-project?rev=160395&view=rev
Log:
Teach the ASTImporter how to handle anonymous structs/unions
better. Fixes <rdar://problem/11466212>; the test (and back-ported
version of this code) were committed to LLDB in r160186.

Modified:
    cfe/trunk/include/clang/AST/ASTImporter.h
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclBase.cpp

Modified: cfe/trunk/include/clang/AST/ASTImporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=160395&r1=160394&r2=160395&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTImporter.h (original)
+++ cfe/trunk/include/clang/AST/ASTImporter.h Tue Jul 17 16:16:27 2012
@@ -271,7 +271,8 @@
     
     /// \brief Determine whether the given types are structurally
     /// equivalent.
-    bool IsStructurallyEquivalent(QualType From, QualType To);    
+    bool IsStructurallyEquivalent(QualType From, QualType To,
+                                  bool Complain = true);
   };
 }
 

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=160395&r1=160394&r2=160395&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Jul 17 16:16:27 2012
@@ -119,7 +119,8 @@
     bool ImportTemplateArguments(const TemplateArgument *FromArgs,
                                  unsigned NumFromArgs,
                                SmallVectorImpl<TemplateArgument> &ToArgs);
-    bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord);
+    bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
+                           bool Complain = true);
     bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
     bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
     Decl *VisitDecl(Decl *D);
@@ -201,12 +202,16 @@
     /// \brief Whether we're being strict about the spelling of types when 
     /// unifying two types.
     bool StrictTypeSpelling;
-    
+
+    /// \brief Whether to complain about failures.
+    bool Complain;
+
     StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2,
                llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls,
-                                 bool StrictTypeSpelling = false)
+                                 bool StrictTypeSpelling = false,
+                                 bool Complain = true)
       : C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls),
-        StrictTypeSpelling(StrictTypeSpelling) { }
+        StrictTypeSpelling(StrictTypeSpelling), Complain(Complain) { }
 
     /// \brief Determine whether the two declarations are structurally
     /// equivalent.
@@ -223,10 +228,16 @@
     
   public:
     DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) {
+      if (!Complain)
+        return DiagnosticBuilder::getEmpty();
+
       return C1.getDiagnostics().Report(Loc, DiagID);
     }
 
     DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) {
+      if (!Complain)
+        return DiagnosticBuilder::getEmpty();
+
       return C2.getDiagnostics().Report(Loc, DiagID);
     }
   };
@@ -2008,10 +2019,11 @@
 }
 
 bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, 
-                                        RecordDecl *ToRecord) {
+                                        RecordDecl *ToRecord, bool Complain) {
   StructuralEquivalenceContext Ctx(Importer.getFromContext(),
                                    Importer.getToContext(),
-                                   Importer.getNonEquivalentDecls());
+                                   Importer.getNonEquivalentDecls(),
+                                   false, Complain);
   return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord);
 }
 
@@ -2291,7 +2303,7 @@
 
   // We may already have a record of the same name; try to find and match it.
   RecordDecl *AdoptDecl = 0;
-  if (!DC->isFunctionOrMethod() && SearchName) {
+  if (!DC->isFunctionOrMethod()) {
     SmallVector<NamedDecl *, 4> ConflictingDecls;
     llvm::SmallVector<NamedDecl *, 2> FoundDecls;
     DC->localUncachedLookup(SearchName, FoundDecls);
@@ -2307,25 +2319,31 @@
       
       if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) {
         if (RecordDecl *FoundDef = FoundRecord->getDefinition()) {
-          if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) {
+          if ((SearchName && !D->isCompleteDefinition())
+              || (D->isCompleteDefinition() &&
+                  D->isAnonymousStructOrUnion()
+                    == FoundDef->isAnonymousStructOrUnion() &&
+                  IsStructuralMatch(D, FoundDef))) {
             // The record types structurally match, or the "from" translation
             // unit only had a forward declaration anyway; call it the same
             // function.
             // FIXME: For C++, we should also merge methods here.
             return Importer.Imported(D, FoundDef);
           }
-        } else {
+        } else if (!D->isCompleteDefinition()) {
           // We have a forward declaration of this type, so adopt that forward
           // declaration rather than building a new one.
           AdoptDecl = FoundRecord;
           continue;
-        }          
+        } else if (!SearchName) {
+          continue;
+        }
       }
       
       ConflictingDecls.push_back(FoundDecls[I]);
     }
     
-    if (!ConflictingDecls.empty()) {
+    if (!ConflictingDecls.empty() && SearchName) {
       Name = Importer.HandleNameConflict(Name, DC, IDNS,
                                          ConflictingDecls.data(), 
                                          ConflictingDecls.size());
@@ -2351,6 +2369,8 @@
     D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
     D2->setLexicalDeclContext(LexicalDC);
     LexicalDC->addDeclInternal(D2);
+    if (D->isAnonymousStructOrUnion())
+      D2->setAnonymousStructOrUnion(true);
   }
   
   Importer.Imported(D, D2);
@@ -2642,11 +2662,16 @@
     if (IndirectFieldDecl *FoundField 
                                 = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
       if (Importer.IsStructurallyEquivalent(D->getType(), 
-                                            FoundField->getType())) {
+                                            FoundField->getType(),
+                                            Name)) {
         Importer.Imported(D, FoundField);
         return FoundField;
       }
-      
+
+      // If there are more anonymous fields to check, continue.
+      if (!Name && I < N-1)
+        continue;
+
       Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent)
         << Name << D->getType() << FoundField->getType();
       Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
@@ -4621,12 +4646,14 @@
   return To;
 }
 
-bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To) {
+bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To,
+                                           bool Complain) {
   llvm::DenseMap<const Type *, const Type *>::iterator Pos
    = ImportedTypes.find(From.getTypePtr());
   if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To))
     return true;
       
-  StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls);
+  StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls,
+                                   false, Complain);
   return Ctx.IsStructurallyEquivalent(From, To);
 }

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=160395&r1=160394&r2=160395&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Jul 17 16:16:27 2012
@@ -1196,23 +1196,25 @@
   
   // If there's no external storage, just perform a normal lookup and copy
   // the results.
-  if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage()) {
+  if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage() && Name) {
     lookup_result LookupResults = lookup(Name);
     Results.insert(Results.end(), LookupResults.first, LookupResults.second);
     return;
   }
 
   // If we have a lookup table, check there first. Maybe we'll get lucky.
-  if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
-    StoredDeclsMap::iterator Pos = Map->find(Name);
-    if (Pos != Map->end()) {
-      Results.insert(Results.end(),
-                     Pos->second.getLookupResult().first,
-                     Pos->second.getLookupResult().second);
-      return;
+  if (Name) {
+    if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+      StoredDeclsMap::iterator Pos = Map->find(Name);
+      if (Pos != Map->end()) {
+        Results.insert(Results.end(),
+                       Pos->second.getLookupResult().first,
+                       Pos->second.getLookupResult().second);
+        return;
+      }
     }
   }
-  
+
   // Slow case: grovel through the declarations in our chain looking for 
   // matches.
   for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) {





More information about the cfe-commits mailing list