aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AST/DeclBase.cpp5
-rw-r--r--lib/AST/DeclPrinter.cpp4
-rw-r--r--lib/Sema/SemaDecl.cpp10
-rw-r--r--test/CXX/class/class.friend/p1.cpp2
-rw-r--r--test/SemaCXX/friend-class-nodecl.cpp10
5 files changed, 20 insertions, 11 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index c24dac9104..acdbdbe422 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -385,11 +385,6 @@ void Decl::CheckAccessDeclContext() const {
!isa<CXXRecordDecl>(getDeclContext()))
return;
- // FIXME: This check should not be necessary - If a friend decl refers to an
- // undeclared decl, then that decl shouldn't be in any decl context.
- if (getFriendObjectKind() == FOK_Undeclared)
- return;
-
assert(Access != AS_none &&
"Access specifier is AS_none inside a record decl");
}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 275f2db82b..275fa69723 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -203,9 +203,7 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
if (PrintAccess) {
AccessSpecifier AS = D->getAccess();
- if (AS != CurAS &&
- // FIXME: This check shouldn't be necessary.
- D->getFriendObjectKind() == Decl::FOK_Undeclared) {
+ if (AS != CurAS) {
Print(AS);
Out << ":\n";
CurAS = AS;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 8eb2c717b4..86222ffe14 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4328,7 +4328,15 @@ CreateNewDecl:
New->startDefinition();
// If this has an identifier, add it to the scope stack.
- if (Name && TUK != TUK_Friend) {
+ if (TUK == TUK_Friend) {
+ // Friend tag decls are visible in fairly strange ways.
+ if (!CurContext->isDependentContext()) {
+ DeclContext *DC = New->getDeclContext()->getLookupContext();
+ DC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+ if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+ PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
+ }
+ } else if (Name) {
S = getNonFieldDeclScope(S);
PushOnScopeChains(New, S);
} else {
diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp
index 5a9114006f..9ba02727a0 100644
--- a/test/CXX/class/class.friend/p1.cpp
+++ b/test/CXX/class/class.friend/p1.cpp
@@ -63,8 +63,6 @@ class A {
friend ftypedef typedeffed_function; // okay (because it's not declared as a member)
};
-class UndeclaredSoFar { };
-
A::UndeclaredSoFar y; // expected-error {{ unknown type name 'UndeclaredSoFar' }}
class PreDeclared;
diff --git a/test/SemaCXX/friend-class-nodecl.cpp b/test/SemaCXX/friend-class-nodecl.cpp
new file mode 100644
index 0000000000..de12eaf741
--- /dev/null
+++ b/test/SemaCXX/friend-class-nodecl.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -ast-print %s -o %t &&
+// RUN: not grep '^ *class B' %t
+
+// Tests that the tag decls in friend declarations aren't added to the
+// declaring class's decl chain.
+
+class A {
+ friend class B;
+};
+