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))
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.).
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
// PR5057
namespace test0 {
namespace std {
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
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}}
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}}
+}