First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
assert(!isa<NamedDecl>(static_cast<decl_type*>(this)) ||
cast<NamedDecl>(static_cast<decl_type*>(this))->isLinkageValid());
-
- // If the declaration was previously visible, a redeclaration of it remains
- // visible even if it wouldn't be visible by itself.
- static_cast<decl_type*>(this)->IdentifierNamespace |=
- First->getIdentifierNamespace() &
- (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
}
// Inline function definitions.
friend class ASTReader;
friend class LinkageComputer;
- template<typename decl_type> friend class Redeclarable;
-
private:
void CheckAccessDeclContext() const;
/// class, but in the semantic context of the actual entity. This property
/// applies only to a specific decl object; other redeclarations of the
/// same entity may not (and probably don't) share this property.
- void setObjectOfFriendDecl(bool PerformFriendInjection = false) {
+ void setObjectOfFriendDecl(bool PreviouslyDeclared) {
unsigned OldNS = IdentifierNamespace;
assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
"namespace includes other than ordinary or tag");
- Decl *Prev = getPreviousDecl();
IdentifierNamespace = 0;
if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
IdentifierNamespace |= IDNS_TagFriend;
- if (PerformFriendInjection ||
- (Prev && Prev->getIdentifierNamespace() & IDNS_Tag))
- IdentifierNamespace |= IDNS_Tag | IDNS_Type;
+ if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type;
}
if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
IdentifierNamespace |= IDNS_OrdinaryFriend;
- if (PerformFriendInjection ||
- (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary))
- IdentifierNamespace |= IDNS_Ordinary;
+ if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary;
}
}
}
if (isFriend) {
+ // For now, claim that the objects have no previous declaration.
if (FunctionTemplate) {
- FunctionTemplate->setObjectOfFriendDecl();
+ FunctionTemplate->setObjectOfFriendDecl(false);
FunctionTemplate->setAccess(AS_public);
}
- NewFD->setObjectOfFriendDecl();
+ NewFD->setObjectOfFriendDecl(false);
NewFD->setAccess(AS_public);
}
NewFD->setAccess(Access);
if (FunctionTemplate) FunctionTemplate->setAccess(Access);
+
+ PrincipalDecl->setObjectOfFriendDecl(true);
}
if (NewFD->isOverloadedOperator() && !DC->isRecord() &&
// declaration so we always pass true to setObjectOfFriendDecl to make
// the tag name visible.
if (TUK == TUK_Friend)
- New->setObjectOfFriendDecl(!FriendSawTagOutsideEnclosingNamespace &&
- getLangOpts().MicrosoftExt);
+ New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() ||
+ (!FriendSawTagOutsideEnclosingNamespace &&
+ getLangOpts().MicrosoftExt));
// Set the access specifier.
if (!Invalid && SearchDC->isRecord())
// If the only declaration here is an ordinary friend, consider
// it only if it was declared in an associated classes.
if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
- bool DeclaredInAssociatedClass = false;
- for (Decl *DI = D; DI; DI = D->getPreviousDecl()) {
- DeclContext *LexDC = DI->getLexicalDeclContext();
- if (AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) {
- DeclaredInAssociatedClass = true;
- break;
- }
- }
- if (!DeclaredInAssociatedClass)
+ DeclContext *LexDC = D->getLexicalDeclContext();
+ if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)))
continue;
}
NewClass->setAccess(PrevClassTemplate->getAccess());
}
- NewTemplate->setObjectOfFriendDecl();
+ NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */
+ PrevClassTemplate != NULL);
// Friend templates are visible in fairly strange ways.
if (!CurContext->isDependentContext()) {
else
Inst->setAccess(D->getAccess());
- Inst->setObjectOfFriendDecl();
+ Inst->setObjectOfFriendDecl(PrevClassTemplate != 0);
// TODO: do we want to track the instantiation progeny of this
// friend target decl?
} else {
// If the original function was part of a friend declaration,
// inherit its namespace state.
- if (D->getFriendObjectKind())
- Record->setObjectOfFriendDecl();
+ if (Decl::FriendObjectKind FOK = D->getFriendObjectKind())
+ Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared);
// Make sure that anonymous structs and unions are recorded.
if (D->isAnonymousStructOrUnion()) {
assert(isFriend && "non-friend has dependent specialization info?");
// This needs to be set now for future sanity.
- Function->setObjectOfFriendDecl();
+ Function->setObjectOfFriendDecl(/*HasPrevious*/ true);
// Instantiate the explicit template arguments.
TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
// If the original function was part of a friend declaration,
// inherit its namespace state and add it to the owner.
if (isFriend) {
- PrincipalDecl->setObjectOfFriendDecl();
+ NamedDecl *PrevDecl;
+ if (TemplateParams)
+ PrevDecl = FunctionTemplate->getPreviousDecl();
+ else
+ PrevDecl = Function->getPreviousDecl();
+
+ PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
DC->makeDeclVisibleInContext(PrincipalDecl);
bool queuedInstantiation = false;
TemplateParams, Method);
if (isFriend) {
FunctionTemplate->setLexicalDeclContext(Owner);
- FunctionTemplate->setObjectOfFriendDecl();
+ FunctionTemplate->setObjectOfFriendDecl(true);
} else if (D->isOutOfLine())
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
Method->setDescribedFunctionTemplate(FunctionTemplate);
TempParamLists.data());
Method->setLexicalDeclContext(Owner);
- Method->setObjectOfFriendDecl();
+ Method->setObjectOfFriendDecl(true);
} else if (D->isOutOfLine())
Method->setLexicalDeclContext(D->getLexicalDeclContext());
X2<float> xf;
f(xf);
}
-
-template<typename T>
-struct X3 {
- operator int();
-
- friend void h(int x);
-};
-
-int array2[sizeof(X3<int>)];
-int array3[sizeof(X3<float>)];
-
-void i() {
- X3<int> xi;
- h(xi);
- X3<float> xf;
- h(xf);
-}
friend void C::f(int, int, int) {} // expected-error {{no function named 'f' with type 'void (int, int, int)' was found in the specified scope}}
};
}
-
-namespace test10 {
- struct A {
- friend void f10();
- };
- struct B {
- friend void f10();
- };
- void g() {
- f10(); // expected-error {{undeclared identifier}}
- }
-}