forked from OSchip/llvm-project
Preserve type-source information in friend declarations.
llvm-svn: 99525
This commit is contained in:
parent
49e121d5e4
commit
15ad0962dc
|
@ -36,7 +36,7 @@ namespace clang {
|
|||
/// The semantic context of a friend decl is its declaring class.
|
||||
class FriendDecl : public Decl {
|
||||
public:
|
||||
typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
|
||||
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
|
||||
|
||||
private:
|
||||
// The declaration that's a friend of this class.
|
||||
|
@ -73,8 +73,8 @@ public:
|
|||
/// possibly dependent) type, return the type; otherwise
|
||||
/// return null. This is used only for C++0x's unelaborated
|
||||
/// friend type declarations.
|
||||
Type *getFriendType() const {
|
||||
return Friend.dyn_cast<Type*>();
|
||||
TypeSourceInfo *getFriendType() const {
|
||||
return Friend.dyn_cast<TypeSourceInfo*>();
|
||||
}
|
||||
|
||||
/// If this friend declaration doesn't name an unelaborated
|
||||
|
|
|
@ -1238,7 +1238,7 @@ public:
|
|||
/// template <typename U> friend class Foo<T>::Nested; // friend template
|
||||
class FriendTemplateDecl : public Decl {
|
||||
public:
|
||||
typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
|
||||
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
|
||||
|
||||
private:
|
||||
// The number of template parameters; always non-zero.
|
||||
|
@ -1277,8 +1277,8 @@ public:
|
|||
/// If this friend declaration names a templated type (or
|
||||
/// a dependent member type of a templated type), return that
|
||||
/// type; otherwise return null.
|
||||
Type *getFriendType() const {
|
||||
return Friend.dyn_cast<Type*>();
|
||||
TypeSourceInfo *getFriendType() const {
|
||||
return Friend.dyn_cast<TypeSourceInfo*>();
|
||||
}
|
||||
|
||||
/// If this friend declaration names a templated function (or
|
||||
|
|
|
@ -330,8 +330,8 @@ static Sema::AccessResult MatchesFriend(Sema &S,
|
|||
static Sema::AccessResult MatchesFriend(Sema &S,
|
||||
const EffectiveContext &EC,
|
||||
FriendDecl *FriendD) {
|
||||
if (Type *T = FriendD->getFriendType())
|
||||
return MatchesFriend(S, EC, T->getCanonicalTypeUnqualified());
|
||||
if (TypeSourceInfo *T = FriendD->getFriendType())
|
||||
return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
|
||||
|
||||
NamedDecl *Friend
|
||||
= cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
|
||||
|
|
|
@ -5372,7 +5372,8 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
|||
// friend templates because ActOnTag never produces a ClassTemplateDecl
|
||||
// for a TUK_Friend.
|
||||
Declarator TheDeclarator(DS, Declarator::MemberContext);
|
||||
QualType T = GetTypeForDeclarator(TheDeclarator, S);
|
||||
TypeSourceInfo *TSI;
|
||||
QualType T = GetTypeForDeclarator(TheDeclarator, S, &TSI);
|
||||
if (TheDeclarator.isInvalidType())
|
||||
return DeclPtrTy();
|
||||
|
||||
|
@ -5437,16 +5438,20 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
|||
// deadline. It's also a very silly restriction that seriously
|
||||
// affects inner classes and which nobody else seems to implement;
|
||||
// thus we never diagnose it, not even in -pedantic.
|
||||
//
|
||||
// But note that we could warn about it: it's always useless to
|
||||
// friend one of your own members (it's not, however, worthless to
|
||||
// friend a member of an arbitrary specialization of your template).
|
||||
|
||||
Decl *D;
|
||||
if (TempParams.size())
|
||||
D = FriendTemplateDecl::Create(Context, CurContext, Loc,
|
||||
TempParams.size(),
|
||||
(TemplateParameterList**) TempParams.release(),
|
||||
T.getTypePtr(),
|
||||
TSI,
|
||||
DS.getFriendSpecLoc());
|
||||
else
|
||||
D = FriendDecl::Create(Context, CurContext, Loc, T.getTypePtr(),
|
||||
D = FriendDecl::Create(Context, CurContext, Loc, TSI,
|
||||
DS.getFriendSpecLoc());
|
||||
D->setAccess(AS_public);
|
||||
CurContext->addDecl(D);
|
||||
|
|
|
@ -3644,7 +3644,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
|
|||
if (TUK == TUK_Friend) {
|
||||
FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
|
||||
TemplateNameLoc,
|
||||
WrittenTy->getType().getTypePtr(),
|
||||
WrittenTy,
|
||||
/*FIXME:*/KWLoc);
|
||||
Friend->setAccess(AS_public);
|
||||
CurContext->addDecl(Friend);
|
||||
|
|
|
@ -480,13 +480,17 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
|
|||
|
||||
// Handle friend type expressions by simply substituting template
|
||||
// parameters into the pattern type.
|
||||
if (Type *Ty = D->getFriendType()) {
|
||||
QualType T = SemaRef.SubstType(QualType(Ty,0), TemplateArgs,
|
||||
D->getLocation(), DeclarationName());
|
||||
if (T.isNull()) return 0;
|
||||
if (TypeSourceInfo *Ty = D->getFriendType()) {
|
||||
TypeSourceInfo *InstTy =
|
||||
SemaRef.SubstType(Ty, TemplateArgs,
|
||||
D->getLocation(), DeclarationName());
|
||||
if (!InstTy) return 0;
|
||||
|
||||
assert(getLangOptions().CPlusPlus0x || T->isRecordType());
|
||||
FU = T.getTypePtr();
|
||||
// This assertion is valid because the source type was necessarily
|
||||
// an elaborated-type-specifier with a record tag.
|
||||
assert(getLangOptions().CPlusPlus0x || InstTy->getType()->isRecordType());
|
||||
|
||||
FU = InstTy;
|
||||
|
||||
// Handle everything else by appropriate substitution.
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue