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