r228485 - [modules] Treat friend declarations that are lexically within a dependent

Richard Smith richard-llvm at metafoo.co.uk
Fri Feb 6 19:11:12 PST 2015


Author: rsmith
Date: Fri Feb  6 21:11:11 2015
New Revision: 228485

URL: http://llvm.org/viewvc/llvm-project?rev=228485&view=rev
Log:
[modules] Treat friend declarations that are lexically within a dependent
context as anonymous for merging purposes. They can't be found by their names,
so we merge them based on their position within the surrounding context.

Added:
    cfe/trunk/test/Modules/Inputs/merge-dependent-friends/
    cfe/trunk/test/Modules/Inputs/merge-dependent-friends/a.h
    cfe/trunk/test/Modules/Inputs/merge-dependent-friends/b.h
    cfe/trunk/test/Modules/Inputs/merge-dependent-friends/c.h
    cfe/trunk/test/Modules/Inputs/merge-dependent-friends/d.h
    cfe/trunk/test/Modules/Inputs/merge-dependent-friends/module.modulemap
    cfe/trunk/test/Modules/merge-dependent-friends.cpp
Modified:
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Serialization/ASTCommon.cpp
    cfe/trunk/lib/Serialization/ASTCommon.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=228485&r1=228484&r2=228485&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Fri Feb  6 21:11:11 2015
@@ -846,6 +846,10 @@ bool DeclContext::isDependentContext() c
       return getLexicalParent()->isDependentContext();
   }
 
+  // FIXME: A variable template is a dependent context, but is not a
+  // DeclContext. A context within it (such as a lambda-expression)
+  // should be considered dependent.
+
   return getParent() && getParent()->isDependentContext();
 }
 

Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=228485&r1=228484&r2=228485&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.cpp Fri Feb  6 21:11:11 2015
@@ -223,6 +223,24 @@ bool serialization::isRedeclarableDeclKi
 }
 
 bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) {
+  // Friend declarations in dependent contexts aren't anonymous in the usual
+  // sense, but they cannot be found by name lookup in their semantic context
+  // (or indeed in any context), so we treat them as anonymous.
+  //
+  // This doesn't apply to friend tag decls; Sema makes those available to name
+  // lookup in the surrounding context.
+  if (D->getFriendObjectKind() &&
+      D->getLexicalDeclContext()->isDependentContext() && !isa<TagDecl>(D)) {
+    // For function templates and class templates, the template is numbered and
+    // not its pattern.
+    if (auto *FD = dyn_cast<FunctionDecl>(D))
+      return !FD->getDescribedFunctionTemplate();
+    if (auto *RD = dyn_cast<CXXRecordDecl>(D))
+      return !RD->getDescribedClassTemplate();
+    return true;
+  }
+
+  // Otherwise, we only care about anonymous class members.
   if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext()))
     return false;
   return isa<TagDecl>(D) || isa<FieldDecl>(D);

Modified: cfe/trunk/lib/Serialization/ASTCommon.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.h?rev=228485&r1=228484&r2=228485&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.h (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.h Fri Feb  6 21:11:11 2015
@@ -15,6 +15,7 @@
 #define LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H
 
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclFriend.h"
 #include "clang/Serialization/ASTBitCodes.h"
 
 namespace clang {
@@ -85,6 +86,24 @@ bool isRedeclarableDeclKind(unsigned Kin
 /// declaration number.
 bool needsAnonymousDeclarationNumber(const NamedDecl *D);
 
+/// \brief Visit each declaration within \c DC that needs an anonymous
+/// declaration number and call \p Visit with the declaration and its number.
+template<typename Fn> void numberAnonymousDeclsWithin(const DeclContext *DC,
+                                                      Fn Visit) {
+  unsigned Index = 0;
+  for (Decl *LexicalD : DC->decls()) {
+    // For a friend decl, we care about the declaration within it, if any.
+    if (auto *FD = dyn_cast<FriendDecl>(LexicalD))
+      LexicalD = FD->getFriendDecl();
+
+    auto *ND = dyn_cast_or_null<NamedDecl>(LexicalD);
+    if (!ND || !needsAnonymousDeclarationNumber(ND))
+      continue;
+
+    Visit(ND, Index++);
+  }
+}
+
 } // namespace serialization
 
 } // namespace clang

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=228485&r1=228484&r2=228485&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Feb  6 21:11:11 2015
@@ -478,8 +478,7 @@ void ASTDeclReader::VisitTranslationUnit
 void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) {
   VisitDecl(ND);
   ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx));
-  if (needsAnonymousDeclarationNumber(ND))
-    AnonymousDeclNumber = Record[Idx++];
+  AnonymousDeclNumber = Record[Idx++];
 }
 
 void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
@@ -2631,8 +2630,7 @@ ASTDeclReader::FindExistingResult::~Find
 
   DeclarationName Name = New->getDeclName();
   DeclContext *DC = New->getDeclContext()->getRedeclContext();
-  if (!Name) {
-    assert(needsAnonymousDeclarationNumber(New));
+  if (needsAnonymousDeclarationNumber(New)) {
     setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(),
                                AnonymousDeclNumber, New);
   } else if (DC->isTranslationUnit() && Reader.SemaObj) {
@@ -2681,17 +2679,12 @@ NamedDecl *ASTDeclReader::getAnonymousDe
   // If this is the first time, but we have parsed a declaration of the context,
   // build the anonymous declaration list from the parsed declaration.
   if (!cast<Decl>(DC)->isFromASTFile()) {
-    unsigned Index = 0;
-    for (Decl *LexicalD : DC->decls()) {
-      auto *ND = dyn_cast<NamedDecl>(LexicalD);
-      if (!ND || !needsAnonymousDeclarationNumber(ND))
-        continue;
-      if (Previous.size() == Index)
+    numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) {
+      if (Previous.size() == Number)
         Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl()));
       else
-        Previous[Index] = cast<NamedDecl>(ND->getCanonicalDecl());
-      ++Index;
-    }
+        Previous[Number] = cast<NamedDecl>(ND->getCanonicalDecl());
+    });
   }
 
   return Index < Previous.size() ? Previous[Index] : nullptr;
@@ -2740,10 +2733,9 @@ ASTDeclReader::FindExistingResult ASTDec
     // was not imported.
   }
 
-  if (!Name) {
+  if (needsAnonymousDeclarationNumber(D)) {
     // This is an anonymous declaration that we may need to merge. Look it up
     // in its context by number.
-    assert(needsAnonymousDeclarationNumber(D));
     if (auto *Existing = getAnonymousDeclForMerging(
             Reader, D->getLexicalDeclContext(), AnonymousDeclNumber))
       if (isSameEntity(Existing, D))

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=228485&r1=228484&r2=228485&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Feb  6 21:11:11 2015
@@ -5226,13 +5226,10 @@ unsigned ASTWriter::getAnonymousDeclarat
   // already done so.
   auto It = AnonymousDeclarationNumbers.find(D);
   if (It == AnonymousDeclarationNumbers.end()) {
-    unsigned Index = 0;
-    for (Decl *LexicalD : D->getLexicalDeclContext()->decls()) {
-      auto *ND = dyn_cast<NamedDecl>(LexicalD);
-      if (!ND || !needsAnonymousDeclarationNumber(ND))
-        continue;
-      AnonymousDeclarationNumbers[ND] = Index++;
-    }
+    auto *DC = D->getLexicalDeclContext();
+    numberAnonymousDeclsWithin(DC, [&](const NamedDecl *ND, unsigned Number) {
+      AnonymousDeclarationNumbers[ND] = Number;
+    });
 
     It = AnonymousDeclarationNumbers.find(D);
     assert(It != AnonymousDeclarationNumbers.end() &&

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=228485&r1=228484&r2=228485&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Feb  6 21:11:11 2015
@@ -203,8 +203,9 @@ void ASTDeclWriter::VisitTranslationUnit
 void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) {
   VisitDecl(D);
   Writer.AddDeclarationName(D->getDeclName(), Record);
-  if (needsAnonymousDeclarationNumber(D))
-    Record.push_back(Writer.getAnonymousDeclarationNumber(D));
+  Record.push_back(needsAnonymousDeclarationNumber(D)
+                       ? Writer.getAnonymousDeclarationNumber(D)
+                       : 0);
 }
 
 void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
@@ -1521,6 +1522,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
   // ValueDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
   // DeclaratorDecl
@@ -1553,6 +1555,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
   // ValueDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
   // DeclaratorDecl
@@ -1590,6 +1593,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
   // TypeDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
@@ -1637,6 +1641,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
   // TypeDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
@@ -1679,6 +1684,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
   // ValueDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
   // DeclaratorDecl
@@ -1732,6 +1738,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
   // TypeDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
@@ -1760,6 +1767,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
   // ValueDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
   // DeclaratorDecl
@@ -1805,6 +1813,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // Identifier
+  Abv->Add(BitCodeAbbrevOp(0));                         // AnonDeclNumber
   // ValueDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // Type
   // DeclaratorDecl

Added: cfe/trunk/test/Modules/Inputs/merge-dependent-friends/a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/merge-dependent-friends/a.h?rev=228485&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/merge-dependent-friends/a.h (added)
+++ cfe/trunk/test/Modules/Inputs/merge-dependent-friends/a.h Fri Feb  6 21:11:11 2015
@@ -0,0 +1,2 @@
+namespace N { template<typename T> struct A { friend int f(A); }; }
+int a = f(N::A<int>());

Added: cfe/trunk/test/Modules/Inputs/merge-dependent-friends/b.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/merge-dependent-friends/b.h?rev=228485&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/merge-dependent-friends/b.h (added)
+++ cfe/trunk/test/Modules/Inputs/merge-dependent-friends/b.h Fri Feb  6 21:11:11 2015
@@ -0,0 +1,2 @@
+namespace N { template<typename T> struct A { friend int f(A); }; }
+int b = f(N::A<int>());

Added: cfe/trunk/test/Modules/Inputs/merge-dependent-friends/c.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/merge-dependent-friends/c.h?rev=228485&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/merge-dependent-friends/c.h (added)
+++ cfe/trunk/test/Modules/Inputs/merge-dependent-friends/c.h Fri Feb  6 21:11:11 2015
@@ -0,0 +1,6 @@
+namespace N { template<typename T> struct A { friend int f(A); }; }
+// It would seem like this variable should be called 'c'.
+// But that makes the original problem disappear...
+int e = f(N::A<int>());
+#include "a.h"
+#include "b.h"

Added: cfe/trunk/test/Modules/Inputs/merge-dependent-friends/d.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/merge-dependent-friends/d.h?rev=228485&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/merge-dependent-friends/d.h (added)
+++ cfe/trunk/test/Modules/Inputs/merge-dependent-friends/d.h Fri Feb  6 21:11:11 2015
@@ -0,0 +1,2 @@
+namespace N { template<typename T> struct A { friend int f(A); }; }
+#include "c.h"

Added: cfe/trunk/test/Modules/Inputs/merge-dependent-friends/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/merge-dependent-friends/module.modulemap?rev=228485&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/merge-dependent-friends/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/merge-dependent-friends/module.modulemap Fri Feb  6 21:11:11 2015
@@ -0,0 +1,4 @@
+module a { header "a.h" export * }
+module b { header "b.h" export * }
+module c { header "c.h" export * }
+module d { header "d.h" export * }

Added: cfe/trunk/test/Modules/merge-dependent-friends.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/merge-dependent-friends.cpp?rev=228485&view=auto
==============================================================================
--- cfe/trunk/test/Modules/merge-dependent-friends.cpp (added)
+++ cfe/trunk/test/Modules/merge-dependent-friends.cpp Fri Feb  6 21:11:11 2015
@@ -0,0 +1,4 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I%S/Inputs/merge-dependent-friends -verify %s
+// expected-no-diagnostics
+#include "d.h"





More information about the cfe-commits mailing list