forked from OSchip/llvm-project
Address http://bugs.llvm.org/pr30994 so that a non-friend can properly replace a friend, and a visible friend can properly replace an invisible friend but not vice verse, and definitions are not replaced. This fixes the two FIXME in SemaTemplate/friend-template.cpp.
The code implements Richard Smith suggestion in comment 3 of the PR. reviewer: Vassil Vassilev Differential Revision: https://reviews.llvm.org/D31540 llvm-svn: 300443
This commit is contained in:
parent
11d9c4f691
commit
27e2ff964f
|
@ -417,6 +417,8 @@ public:
|
|||
return const_cast<Decl*>(this)->getTranslationUnitDecl();
|
||||
}
|
||||
|
||||
bool isThisDeclarationADefinition() const;
|
||||
|
||||
bool isInAnonymousNamespace() const;
|
||||
|
||||
bool isInStdNamespace() const;
|
||||
|
|
|
@ -1536,6 +1536,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
|
|||
if (isa<ObjCMethodDecl>(this))
|
||||
return false;
|
||||
|
||||
if (getFriendObjectKind() > OldD->getFriendObjectKind() &&
|
||||
!isThisDeclarationADefinition())
|
||||
return false;
|
||||
|
||||
// For parameters, pick the newer one. This is either an error or (in
|
||||
// Objective-C) permitted as an extension.
|
||||
if (isa<ParmVarDecl>(this))
|
||||
|
|
|
@ -861,6 +861,21 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
|
|||
return Ty->getAs<FunctionType>();
|
||||
}
|
||||
|
||||
bool Decl::isThisDeclarationADefinition() const {
|
||||
if (auto *TD = dyn_cast<TagDecl>(this))
|
||||
return TD->isThisDeclarationADefinition();
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(this))
|
||||
return FD->isThisDeclarationADefinition();
|
||||
if (auto *VD = dyn_cast<VarDecl>(this))
|
||||
return VD->isThisDeclarationADefinition();
|
||||
if (auto *CTD = dyn_cast<ClassTemplateDecl>(this))
|
||||
return CTD->isThisDeclarationADefinition();
|
||||
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this))
|
||||
return FTD->isThisDeclarationADefinition();
|
||||
if (auto *VTD = dyn_cast<VarTemplateDecl>(this))
|
||||
return VTD->isThisDeclarationADefinition();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Starting at a given context (a Decl or DeclContext), look for a
|
||||
/// code context that is not a closure (a lambda, block, etc.).
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
|
||||
// PR5057
|
||||
namespace test0 {
|
||||
namespace std {
|
||||
|
@ -68,17 +68,12 @@ namespace test3 {
|
|||
Foo<int> foo;
|
||||
|
||||
template<typename T, T Value> struct X2a;
|
||||
|
||||
template<typename T, int Size> struct X2b;
|
||||
template<typename T, int Size> struct X2b; // expected-note {{previous non-type template parameter with type 'int' is here}}
|
||||
|
||||
template<typename T>
|
||||
class X3 {
|
||||
template<typename U, U Value> friend struct X2a;
|
||||
|
||||
// FIXME: the redeclaration note ends up here because redeclaration
|
||||
// lookup ends up finding the friend target from X3<int>.
|
||||
template<typename U, T Value> friend struct X2b; // expected-error {{template non-type parameter has a different type 'long' in template redeclaration}} \
|
||||
// expected-note {{previous non-type template parameter with type 'int' is here}}
|
||||
template<typename U, T Value> friend struct X2b; // expected-error {{template non-type parameter has a different type 'long' in template redeclaration}}
|
||||
};
|
||||
|
||||
X3<int> x3i; // okay
|
||||
|
@ -297,14 +292,11 @@ namespace PR12585 {
|
|||
int n = C::D<void*>().f();
|
||||
|
||||
struct F {
|
||||
template<int> struct G;
|
||||
template<int> struct G; // expected-note {{previous}}
|
||||
};
|
||||
template<typename T> struct H {
|
||||
// FIXME: As with cases above, the note here is on an unhelpful declaration,
|
||||
// and should point to the declaration of G within F.
|
||||
template<T> friend struct F::G; // \
|
||||
// expected-error {{different type 'char' in template redeclaration}} \
|
||||
// expected-note {{previous}}
|
||||
// expected-error {{different type 'char' in template redeclaration}}
|
||||
};
|
||||
H<int> h1; // ok
|
||||
H<char> h2; // expected-note {{instantiation}}
|
||||
|
@ -329,3 +321,11 @@ namespace rdar12350696 {
|
|||
foo(b); // expected-note {{in instantiation}}
|
||||
}
|
||||
}
|
||||
namespace PR30994 {
|
||||
void f();
|
||||
struct A {
|
||||
[[deprecated]] friend void f() {} // \
|
||||
expected-note {{has been explicitly marked deprecated here}}
|
||||
};
|
||||
void g() { f(); } // expected-warning {{is deprecated}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue