r187639 - When merging redeclaration chains across modules, if a declaration is visible

Richard Smith richard-llvm at metafoo.co.uk
Thu Aug 1 18:09:12 PDT 2013


Author: rsmith
Date: Thu Aug  1 20:09:12 2013
New Revision: 187639

URL: http://llvm.org/viewvc/llvm-project?rev=187639&view=rev
Log:
When merging redeclaration chains across modules, if a declaration is visible
in one module but is only declared as a friend in another module, keep it
visible in the result of the merge.

This is incomplete on two axes:

1) Our handling of local extern declarations is basically broken (we put them
in the wrong decl context, and don't find them in redeclaration lookup, unless
they've previously been declared), and this results in them making friends
visible after a merge.

2) Eventually we'll need to mark that this has happened, and more carefully
check whether a declaration should be visible if it was only visible in some
of the modules in which it was declared. Fortunately it's rare for the
identifier namespace of a declaration to change along its redeclaration chain.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/Modules/Inputs/cxx-templates-a.h
    cfe/trunk/test/Modules/Inputs/cxx-templates-b.h
    cfe/trunk/test/Modules/cxx-templates.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=187639&r1=187638&r2=187639&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Aug  1 20:09:12 2013
@@ -3424,6 +3424,8 @@ void Redeclarable<decl_type>::setPreviou
 
     // If the declaration was previously visible, a redeclaration of it remains
     // visible even if it wouldn't be visible by itself.
+    // FIXME: Once we handle local extern decls properly, this should inherit
+    // the visibility from MostRecent, not from PrevDecl.
     static_cast<decl_type*>(this)->IdentifierNamespace |=
       PrevDecl->getIdentifierNamespace() &
       (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=187639&r1=187638&r2=187639&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Thu Aug  1 20:09:12 2013
@@ -907,9 +907,6 @@ private:
   /// the given canonical declaration.
   MergedDeclsMap::iterator
   combineStoredMergedDecls(Decl *Canon, serialization::GlobalDeclID CanonID);
-  
-  /// \brief Ready to load the previous declaration of the given Decl.
-  void loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID);
 
   /// \brief When reading a Stmt tree, Stmt operands are placed in this stack.
   SmallVector<Stmt *, 16> StmtStack;

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=187639&r1=187638&r2=187639&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Aug  1 20:09:12 2013
@@ -2003,6 +2003,17 @@ void ASTDeclReader::attachPreviousDecl(D
     RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
     TD->RedeclLink.setNext(cast<RedeclarableTemplateDecl>(previous));
   }
+
+  // If the declaration was visible in one module, a redeclaration of it in
+  // another module remains visible even if it wouldn't be visible by itself.
+  //
+  // FIXME: In this case, the declaration should only be visible if a module
+  //        that makes it visible has been imported.
+  // FIXME: This is not correct in the case where previous is a local extern
+  //        declaration and D is a friend declaraton.
+  D->IdentifierNamespace |=
+      previous->IdentifierNamespace &
+      (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
 }
 
 void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
@@ -2063,11 +2074,6 @@ ASTReader::combineStoredMergedDecls(Decl
   return Pos;
 }
 
-void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) {
-  Decl *previous = GetDecl(ID);
-  ASTDeclReader::attachPreviousDecl(D, previous);
-}
-
 /// \brief Read the declaration at the given offset from the AST file.
 Decl *ASTReader::ReadDeclRecord(DeclID ID) {
   unsigned Index = ID - NUM_PREDEF_DECL_IDS;
@@ -2499,7 +2505,7 @@ void ASTReader::loadPendingDeclChain(ser
   for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
     if (Chain[I] == CanonDecl)
       continue;
-    
+
     ASTDeclReader::attachPreviousDecl(Chain[I], MostRecent);
     MostRecent = Chain[I];
   }

Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-a.h?rev=187639&r1=187638&r2=187639&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-a.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-a.h Thu Aug  1 20:09:12 2013
@@ -22,3 +22,5 @@ template<typename T> void PerformDelayed
 }
 
 template<typename T> void PerformDelayedLookupInDefaultArgument(T &t, int a = (FoundByADL(T()), 0)) {}
+
+template<typename T> struct RedeclaredAsFriend {};

Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-b.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-b.h?rev=187639&r1=187638&r2=187639&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-b.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-b.h Thu Aug  1 20:09:12 2013
@@ -29,6 +29,12 @@ template<typename T> void UseDefinedInBI
 
 extern DefinedInBImpl &defined_in_b_impl;
 
+template<typename T>
+struct RedeclareTemplateAsFriend {
+  template<typename U>
+  friend struct RedeclaredAsFriend;
+};
+
 @import cxx_templates_a;
 template<typename T> void UseDefinedInBImplIndirectly(T &v) {
   PerformDelayedLookup(v);

Modified: cfe/trunk/test/Modules/cxx-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-templates.cpp?rev=187639&r1=187638&r2=187639&view=diff
==============================================================================
--- cfe/trunk/test/Modules/cxx-templates.cpp (original)
+++ cfe/trunk/test/Modules/cxx-templates.cpp Thu Aug  1 20:09:12 2013
@@ -71,6 +71,10 @@ void g() {
   PerformDelayedLookup(defined_in_b_impl); // expected-note {{in instantiation of}}
 }
 
+RedeclaredAsFriend<int> raf1;
+RedeclareTemplateAsFriend<double> rtaf;
+RedeclaredAsFriend<double> raf2;
+
 @import cxx_templates_common;
 
 typedef SomeTemplate<int*> SomeTemplateIntPtr;





More information about the cfe-commits mailing list