diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-07 16:53:43 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-07 16:53:43 +0000 |
commit | 1d8693580133d6c783b9a56808e61f98005e0be1 (patch) | |
tree | 699c87b3f23e7911345fed0fbaf793679d466d30 /lib/Sema | |
parent | beb41281f8355caa05700d0a77539defbdf428f8 (diff) |
Split Sema::ActOnFriendTypeDecl into Sema::CheckFriendTypeDecl (for
semantic analysis) and Sema::ActOnFriendTypeDecl (the action
callback). This is a prerequisite for improving template instantiation
of friend type declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100633 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 96 |
2 files changed, 63 insertions, 35 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 5394f06985..c93acf6946 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2530,6 +2530,8 @@ public: ExprArg AssertExpr, ExprArg AssertMessageExpr); + FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc, + TypeSourceInfo *TSInfo); DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TemplateParams); DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 39e3739878..75dbb46d42 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -5318,6 +5318,53 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, return DeclPtrTy::make(Decl); } +/// \brief Perform semantic analysis of the given friend type declaration. +/// +/// \returns A friend declaration that. +FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc, + TypeSourceInfo *TSInfo) { + assert(TSInfo && "NULL TypeSourceInfo for friend type declaration"); + + QualType T = TSInfo->getType(); + SourceRange TypeRange = TSInfo->getTypeLoc().getSourceRange(); + + // C++03 [class.friend]p2: + // An elaborated-type-specifier shall be used in a friend declaration + // for a class.* + // + // * The class-key of the elaborated-type-specifier is required. + if (!getLangOptions().CPlusPlus0x && !T->isElaboratedTypeSpecifier()) { + // If we evaluated the type to a record type, suggest putting + // a tag in front. + if (const RecordType *RT = T->getAs<RecordType>()) { + RecordDecl *RD = RT->getDecl(); + + std::string InsertionText = std::string(" ") + RD->getKindName(); + + Diag(FriendLoc, diag::err_unelaborated_friend_type) + << (unsigned) RD->getTagKind() + << T + << SourceRange(FriendLoc) + << FixItHint::CreateInsertion(TypeRange.getBegin(), + InsertionText); + return 0; + } else { + Diag(FriendLoc, diag::err_unexpected_friend) + << SourceRange(FriendLoc, TypeRange.getEnd()); + return 0; + } + } + + // Enum types cannot be friends. + if (T->getAs<EnumType>()) { + Diag(FriendLoc, diag::err_enum_friend) + << SourceRange(FriendLoc, TypeRange.getEnd()); + return 0; + } + + return FriendDecl::Create(Context, CurContext, FriendLoc, TSInfo, FriendLoc); +} + /// Handle a friend type declaration. This works in tandem with /// ActOnTag. /// @@ -5351,6 +5398,9 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, if (TheDeclarator.isInvalidType()) return DeclPtrTy(); + if (!TSI) + TSI = Context.getTrivialTypeSourceInfo(T, DS.getSourceRange().getBegin()); + // This is definitely an error in C++98. It's probably meant to // be forbidden in C++0x, too, but the specification is just // poorly written. @@ -5370,38 +5420,11 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, << DS.getSourceRange(); return DeclPtrTy(); } - - // C++ [class.friend]p2: - // An elaborated-type-specifier shall be used in a friend declaration - // for a class.* - // * The class-key of the elaborated-type-specifier is required. - // This is one of the rare places in Clang where it's legitimate to - // ask about the "spelling" of the type. - if (!getLangOptions().CPlusPlus0x && !T->isElaboratedTypeSpecifier()) { - // If we evaluated the type to a record type, suggest putting - // a tag in front. - if (const RecordType *RT = T->getAs<RecordType>()) { - RecordDecl *RD = RT->getDecl(); - - std::string InsertionText = std::string(" ") + RD->getKindName(); - - Diag(DS.getTypeSpecTypeLoc(), diag::err_unelaborated_friend_type) - << (unsigned) RD->getTagKind() - << T - << SourceRange(DS.getFriendSpecLoc()) - << FixItHint::CreateInsertion(DS.getTypeSpecTypeLoc(), InsertionText); - return DeclPtrTy(); - }else { - Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend) - << DS.getSourceRange(); - return DeclPtrTy(); - } - } - - // Enum types cannot be friends. - if (T->getAs<EnumType>()) { + + // Enum templates cannot be friends. + if (TempParams.size() && T->getAs<EnumType>()) { Diag(DS.getTypeSpecTypeLoc(), diag::err_enum_friend) - << SourceRange(DS.getFriendSpecLoc()); + << SourceRange(DS.getFriendSpecLoc()); return DeclPtrTy(); } @@ -5417,15 +5440,18 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // friend a member of an arbitrary specialization of your template). Decl *D; - if (TempParams.size()) + if (unsigned NumTempParamLists = TempParams.size()) D = FriendTemplateDecl::Create(Context, CurContext, Loc, - TempParams.size(), + NumTempParamLists, (TemplateParameterList**) TempParams.release(), TSI, DS.getFriendSpecLoc()); else - D = FriendDecl::Create(Context, CurContext, Loc, TSI, - DS.getFriendSpecLoc()); + D = CheckFriendTypeDecl(DS.getFriendSpecLoc(), TSI); + + if (!D) + return DeclPtrTy(); + D->setAccess(AS_public); CurContext->addDecl(D); |