diff options
author | Francois Pichet <pichet2000@gmail.com> | 2011-05-31 11:44:00 +0000 |
---|---|---|
committer | Francois Pichet <pichet2000@gmail.com> | 2011-05-31 11:44:00 +0000 |
commit | 8adc227de934e23c72eb8d9abf5c0e3dfffec131 (patch) | |
tree | 3a4272584e5463a2671bed9d408c766b3880ff03 /lib | |
parent | 8155910a192dafa423d6b932b7d127d48e4641e8 (diff) |
For compatibility with MSVC, a friend declaration also act as a forward declaration if the tag name is not already declared. The tag name is declared in the next outermost non record scope.
Example:
class A {
friend class B;
B* b;
};
B* global_b;
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132332 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 5a3f6328ca..878c21776d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6631,6 +6631,40 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, return false; } +/// InjectMicrosoftFriendForwardDeclaration - For compatibility with MSVC, +/// a friend declaration also act as a forward declaration if the tag name +/// is not already declared. The tag name is declared in the next outermost +/// non record scope. +/// Example: +/// +/// class A { +/// friend class B; +/// B* b; +/// }; +/// B* global_b; + +void Sema::InjectMicrosoftFriendForwardDeclaration(unsigned TagSpec, + SourceLocation KWLoc, + IdentifierInfo *Name, + SourceLocation NameLoc) { + NamedDecl *N = LookupSingleName(getCurScope(), Name, NameLoc, + Sema::LookupTagName); + if (!N) { + DeclContext *ContextToAdd = CurContext; + while (ContextToAdd->isRecord()) + ContextToAdd = ContextToAdd->getParent(); + + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + TagDecl *New = CXXRecordDecl::Create(Context, Kind, ContextToAdd, KWLoc, + NameLoc, Name, 0); + if (getCurScope()->getFnParent()) + PushOnScopeChains(New, getScopeForContext(ContextToAdd), true); + else + ContextToAdd->addDecl(New); + } +} + + /// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the /// former case, Name will be non-null. In the later case, Name will be null. /// TagSpec indicates what kind of tag this is. TUK indicates whether this is a @@ -6648,6 +6682,9 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, "Nameless record must be a definition!"); assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference); + if (getLangOptions().Microsoft && TUK == Sema::TUK_Friend) + InjectMicrosoftFriendForwardDeclaration(TagSpec, KWLoc, Name, NameLoc); + OwnedDecl = false; TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); |