summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-01-06 01:07:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-01-06 01:07:05 +0000
commita263c346e568e15dde95ad2d1417444c5cda134f (patch)
tree5033028c647c91413c416e61e51382bf8202e149
parent0f74d273b009240bd71c10e8e5487f0add521048 (diff)
downloadbcm5719-llvm-a263c346e568e15dde95ad2d1417444c5cda134f.tar.gz
bcm5719-llvm-a263c346e568e15dde95ad2d1417444c5cda134f.zip
Serialize the IDNS for a UsingShadowDecl rather than recomputing it.
Attempting to recompute it are doomed to fail because the IDNS of a declaration is not necessarily preserved across serialization and deserialization (in turn because whether a friend declaration is visible depends on whether some prior non-friend declaration exists). llvm-svn: 321921
-rw-r--r--clang/include/clang/AST/DeclCXX.h8
-rw-r--r--clang/lib/AST/DeclCXX.cpp4
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp3
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp1
-rw-r--r--clang/test/Modules/using-decl-friend-2.cpp39
5 files changed, 50 insertions, 5 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 88dc9a65591..9f19c060f2c 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -3129,10 +3129,14 @@ public:
/// \brief Sets the underlying declaration which has been brought into the
/// local scope.
- void setTargetDecl(NamedDecl* ND) {
+ void setTargetDecl(NamedDecl *ND) {
assert(ND && "Target decl is null!");
Underlying = ND;
- IdentifierNamespace = ND->getIdentifierNamespace();
+ // A UsingShadowDecl is never a friend or local extern declaration, even
+ // if it is a shadow declaration for one.
+ IdentifierNamespace =
+ ND->getIdentifierNamespace() &
+ ~(IDNS_OrdinaryFriend | IDNS_TagFriend | IDNS_LocalExtern);
}
/// \brief Gets the using declaration to which this declaration is tied.
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 41f2449a9d6..afbc3f315f5 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2387,10 +2387,10 @@ UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
SourceLocation Loc, UsingDecl *Using,
NamedDecl *Target)
: NamedDecl(K, DC, Loc, Using ? Using->getDeclName() : DeclarationName()),
- redeclarable_base(C), Underlying(Target),
+ redeclarable_base(C), Underlying(),
UsingOrNextShadow(cast<NamedDecl>(Using)) {
if (Target)
- IdentifierNamespace = Target->getIdentifierNamespace();
+ setTargetDecl(Target);
setImplicit();
}
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index efbaf92a849..0cf9afb0759 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1500,7 +1500,8 @@ void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) {
void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
- D->setTargetDecl(ReadDeclAs<NamedDecl>());
+ D->Underlying = ReadDeclAs<NamedDecl>();
+ D->IdentifierNamespace = Record.readInt();
D->UsingOrNextShadow = ReadDeclAs<NamedDecl>();
UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>();
if (Pattern)
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index bb72a3b383e..341f0e16075 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1192,6 +1192,7 @@ void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
VisitRedeclarable(D);
VisitNamedDecl(D);
Record.AddDeclRef(D->getTargetDecl());
+ Record.push_back(D->getIdentifierNamespace());
Record.AddDeclRef(D->UsingOrNextShadow);
Record.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D));
Code = serialization::DECL_USING_SHADOW;
diff --git a/clang/test/Modules/using-decl-friend-2.cpp b/clang/test/Modules/using-decl-friend-2.cpp
new file mode 100644
index 00000000000..0c71c37765f
--- /dev/null
+++ b/clang/test/Modules/using-decl-friend-2.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fmodules %s -verify
+// expected-no-diagnostics
+
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+namespace N { class X; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+namespace N { class Friendly { friend class X; }; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build C
+module C {}
+#pragma clang module contents
+#pragma clang module begin C
+#pragma clang module import A
+void use_X(N::X *p);
+#pragma clang module import B
+// UsingShadowDecl names the friend declaration
+using N::X;
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import B
+namespace N { class AlsoFriendly { friend class X; }; }
+#pragma clang module import A
+#pragma clang module import C
+// The friend declaration from N::Friendly is now the first in the redecl
+// chain, so is not ordinarily visible. We need the IDNS of the UsingShadowDecl
+// to still consider it to be visible, though.
+X *p;
OpenPOWER on IntegriCloud