forked from OSchip/llvm-project
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. llvm-svn: 100633
This commit is contained in:
parent
f2351a7a6e
commit
afb9bc10fa
|
@ -2530,6 +2530,8 @@ public:
|
||||||
ExprArg AssertExpr,
|
ExprArg AssertExpr,
|
||||||
ExprArg AssertMessageExpr);
|
ExprArg AssertMessageExpr);
|
||||||
|
|
||||||
|
FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc,
|
||||||
|
TypeSourceInfo *TSInfo);
|
||||||
DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
||||||
MultiTemplateParamsArg TemplateParams);
|
MultiTemplateParamsArg TemplateParams);
|
||||||
DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
|
DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
|
||||||
|
|
|
@ -5318,6 +5318,53 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
|
||||||
return DeclPtrTy::make(Decl);
|
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
|
/// Handle a friend type declaration. This works in tandem with
|
||||||
/// ActOnTag.
|
/// ActOnTag.
|
||||||
///
|
///
|
||||||
|
@ -5351,6 +5398,9 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
||||||
if (TheDeclarator.isInvalidType())
|
if (TheDeclarator.isInvalidType())
|
||||||
return DeclPtrTy();
|
return DeclPtrTy();
|
||||||
|
|
||||||
|
if (!TSI)
|
||||||
|
TSI = Context.getTrivialTypeSourceInfo(T, DS.getSourceRange().getBegin());
|
||||||
|
|
||||||
// This is definitely an error in C++98. It's probably meant to
|
// This is definitely an error in C++98. It's probably meant to
|
||||||
// be forbidden in C++0x, too, but the specification is just
|
// be forbidden in C++0x, too, but the specification is just
|
||||||
// poorly written.
|
// poorly written.
|
||||||
|
@ -5371,35 +5421,8 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
||||||
return DeclPtrTy();
|
return DeclPtrTy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// C++ [class.friend]p2:
|
// Enum templates cannot be friends.
|
||||||
// An elaborated-type-specifier shall be used in a friend declaration
|
if (TempParams.size() && T->getAs<EnumType>()) {
|
||||||
// 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>()) {
|
|
||||||
Diag(DS.getTypeSpecTypeLoc(), diag::err_enum_friend)
|
Diag(DS.getTypeSpecTypeLoc(), diag::err_enum_friend)
|
||||||
<< SourceRange(DS.getFriendSpecLoc());
|
<< SourceRange(DS.getFriendSpecLoc());
|
||||||
return DeclPtrTy();
|
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).
|
// friend a member of an arbitrary specialization of your template).
|
||||||
|
|
||||||
Decl *D;
|
Decl *D;
|
||||||
if (TempParams.size())
|
if (unsigned NumTempParamLists = TempParams.size())
|
||||||
D = FriendTemplateDecl::Create(Context, CurContext, Loc,
|
D = FriendTemplateDecl::Create(Context, CurContext, Loc,
|
||||||
TempParams.size(),
|
NumTempParamLists,
|
||||||
(TemplateParameterList**) TempParams.release(),
|
(TemplateParameterList**) TempParams.release(),
|
||||||
TSI,
|
TSI,
|
||||||
DS.getFriendSpecLoc());
|
DS.getFriendSpecLoc());
|
||||||
else
|
else
|
||||||
D = FriendDecl::Create(Context, CurContext, Loc, TSI,
|
D = CheckFriendTypeDecl(DS.getFriendSpecLoc(), TSI);
|
||||||
DS.getFriendSpecLoc());
|
|
||||||
|
if (!D)
|
||||||
|
return DeclPtrTy();
|
||||||
|
|
||||||
D->setAccess(AS_public);
|
D->setAccess(AS_public);
|
||||||
CurContext->addDecl(D);
|
CurContext->addDecl(D);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue