forked from OSchip/llvm-project
Issue a diagnostic if we see a templated friend declaration that we do not
support. llvm-svn: 194273
This commit is contained in:
parent
f7a60a8e01
commit
cd556eb265
|
@ -333,6 +333,7 @@ def UnknownAttributes : DiagGroup<"attributes">;
|
||||||
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
|
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
|
||||||
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
|
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
|
||||||
[CXX98CompatUnnamedTypeTemplateArgs]>;
|
[CXX98CompatUnnamedTypeTemplateArgs]>;
|
||||||
|
def UnsupportedFriend : DiagGroup<"unsupported-friend">;
|
||||||
def UnusedArgument : DiagGroup<"unused-argument">;
|
def UnusedArgument : DiagGroup<"unused-argument">;
|
||||||
def UnusedSanitizeArgument : DiagGroup<"unused-sanitize-argument">;
|
def UnusedSanitizeArgument : DiagGroup<"unused-sanitize-argument">;
|
||||||
def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument",
|
def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument",
|
||||||
|
|
|
@ -914,6 +914,14 @@ def err_friend_not_first_in_declaration : Error<
|
||||||
"'friend' must appear first in a non-function declaration">;
|
"'friend' must appear first in a non-function declaration">;
|
||||||
def err_using_decl_friend : Error<
|
def err_using_decl_friend : Error<
|
||||||
"cannot befriend target of using declaration">;
|
"cannot befriend target of using declaration">;
|
||||||
|
def warn_template_qualified_friend_unsupported : Warning<
|
||||||
|
"dependent nested name specifier '%0' for friend class declaration is "
|
||||||
|
"not supported; turning off access control for %1">,
|
||||||
|
InGroup<UnsupportedFriend>;
|
||||||
|
def warn_template_qualified_friend_ignored : Warning<
|
||||||
|
"dependent nested name specifier '%0' for friend template declaration is "
|
||||||
|
"not supported; ignoring this friend declaration">,
|
||||||
|
InGroup<UnsupportedFriend>;
|
||||||
|
|
||||||
def err_invalid_member_in_interface : Error<
|
def err_invalid_member_in_interface : Error<
|
||||||
"%select{data member |non-public member function |static member function |"
|
"%select{data member |non-public member function |static member function |"
|
||||||
|
|
|
@ -11410,6 +11410,8 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
|
||||||
// Handle the case of a templated-scope friend class. e.g.
|
// Handle the case of a templated-scope friend class. e.g.
|
||||||
// template <class T> class A<T>::B;
|
// template <class T> class A<T>::B;
|
||||||
// FIXME: we don't support these right now.
|
// FIXME: we don't support these right now.
|
||||||
|
Diag(NameLoc, diag::warn_template_qualified_friend_unsupported)
|
||||||
|
<< SS.getScopeRep() << SS.getRange() << cast<CXXRecordDecl>(CurContext);
|
||||||
ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
|
ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
|
||||||
QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
|
QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
|
||||||
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
|
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
|
||||||
|
|
|
@ -877,10 +877,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||||
// FIXME: Horrible, horrible hack! We can't currently represent this
|
// FIXME: Horrible, horrible hack! We can't currently represent this
|
||||||
// in the AST, and historically we have just ignored such friend
|
// in the AST, and historically we have just ignored such friend
|
||||||
// class templates, so don't complain here.
|
// class templates, so don't complain here.
|
||||||
if (TUK != TUK_Friend)
|
Diag(NameLoc, TUK == TUK_Friend
|
||||||
Diag(NameLoc, diag::err_template_qualified_declarator_no_match)
|
? diag::warn_template_qualified_friend_ignored
|
||||||
|
: diag::err_template_qualified_declarator_no_match)
|
||||||
<< SS.getScopeRep() << SS.getRange();
|
<< SS.getScopeRep() << SS.getRange();
|
||||||
return true;
|
return TUK != TUK_Friend;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RequireCompleteDeclContext(SS, SemanticContext))
|
if (RequireCompleteDeclContext(SS, SemanticContext))
|
||||||
|
|
|
@ -36,10 +36,17 @@ class A {
|
||||||
public:
|
public:
|
||||||
class foo {};
|
class foo {};
|
||||||
static int y;
|
static int y;
|
||||||
template <typename S> friend class B<S>::ty;
|
template <typename S> friend class B<S>::ty; // expected-warning {{dependent nested name specifier 'B<S>::' for friend class declaration is not supported}}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> class B { typedef int ty; };
|
template<typename T> class B { typedef int ty; };
|
||||||
|
|
||||||
|
template<> class B<int> {
|
||||||
|
class ty {
|
||||||
|
static int f(A<int> &a) { return a.y; } // ok, befriended
|
||||||
|
};
|
||||||
|
};
|
||||||
|
int f(A<char> &a) { return a.y; } // FIXME: should be an error
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
// Ill-formed
|
// Ill-formed
|
||||||
|
@ -56,7 +63,7 @@ struct {
|
||||||
friend
|
friend
|
||||||
|
|
||||||
float;
|
float;
|
||||||
template<typename T> friend class A<T>::foo;
|
template<typename T> friend class A<T>::foo; // expected-warning {{not supported}}
|
||||||
} a;
|
} a;
|
||||||
|
|
||||||
void testA() { (void)sizeof(A<int>); }
|
void testA() { (void)sizeof(A<int>); }
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
// expected-no-diagnostics
|
|
||||||
|
|
||||||
namespace test0 {
|
namespace test0 {
|
||||||
template <class T> class A {
|
template <class T> class A {
|
||||||
|
@ -7,7 +6,8 @@ namespace test0 {
|
||||||
};
|
};
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
template <class T> friend class A<T>::Member;
|
template <class T> friend class A<T>::Member; // expected-warning {{not supported}}
|
||||||
|
int n;
|
||||||
};
|
};
|
||||||
|
|
||||||
A<int> a;
|
A<int> a;
|
||||||
|
@ -68,7 +68,7 @@ namespace test3 {
|
||||||
|
|
||||||
template <class U> class C {
|
template <class U> class C {
|
||||||
int i;
|
int i;
|
||||||
template <class T> friend struct A<T>::Inner;
|
template <class T> friend struct A<T>::Inner; // expected-warning {{not supported}}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T> int A<T>::Inner::foo() {
|
template <class T> int A<T>::Inner::foo() {
|
||||||
|
|
|
@ -232,16 +232,23 @@ namespace PR10660 {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace rdar11147355 {
|
namespace rdar11147355 {
|
||||||
template <class T>
|
template <class T>
|
||||||
struct A {
|
struct A {
|
||||||
template <class U> class B;
|
template <class U> class B;
|
||||||
template <class S> template <class U> friend class A<S>::B;
|
template <class S> template <class U> friend class A<S>::B; // expected-warning {{dependent nested name specifier 'A<S>::' for friend template declaration is not supported; ignoring this friend declaration}}
|
||||||
|
private:
|
||||||
|
int n; // expected-note {{here}}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class S> template <class U> class A<S>::B {
|
template <class S> template <class U> class A<S>::B {
|
||||||
};
|
public:
|
||||||
|
// FIXME: This should be permitted.
|
||||||
|
int f(A<S*> a) { return a.n; } // expected-error {{private}}
|
||||||
|
};
|
||||||
|
|
||||||
A<double>::B<double> ab;
|
A<double>::B<double> ab;
|
||||||
|
A<double*> a;
|
||||||
|
int k = ab.f(a); // expected-note {{instantiation of}}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace RedeclUnrelated {
|
namespace RedeclUnrelated {
|
||||||
|
|
Loading…
Reference in New Issue