mirror of https://github.com/microsoft/clang.git
Re-land r250592 without rejecting field refs in unevaluated contexts
This time, I went with the first approach from http://reviews.llvm.org/D6700, where clang actually attempts to form an implicit member reference from an UnresolvedLookupExpr. We know that there are only two possible outcomes at this point, a DeclRefExpr of the FieldDecl or an error, but its safer to reuse the existing machinery for this. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@250856 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5552f5c7ce
commit
d903d33591
|
@ -9127,9 +9127,20 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
|
|||
SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc();
|
||||
|
||||
// If we have neither explicit template arguments, nor the template keyword,
|
||||
// it's a normal declaration name.
|
||||
if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid())
|
||||
// it's a normal declaration name or member reference.
|
||||
if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) {
|
||||
NamedDecl *D = R.getAsSingle<NamedDecl>();
|
||||
// In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an
|
||||
// instance member. In other contexts, BuildPossibleImplicitMemberExpr will
|
||||
// give a good diagnostic.
|
||||
if (D && D->isCXXInstanceMember()) {
|
||||
return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R,
|
||||
/*TemplateArgs=*/nullptr,
|
||||
/*Scope=*/nullptr);
|
||||
}
|
||||
|
||||
return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());
|
||||
}
|
||||
|
||||
// If we have template arguments, rebuild them, then rebuild the
|
||||
// templateid expression.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s
|
||||
|
||||
namespace test0 {
|
||||
namespace N { }
|
||||
|
@ -104,3 +105,65 @@ namespace PR16936 {
|
|||
x.f();
|
||||
}
|
||||
}
|
||||
|
||||
namespace pr21923 {
|
||||
template <typename> struct Base {
|
||||
int field;
|
||||
void method();
|
||||
};
|
||||
template <typename Scalar> struct Derived : Base<Scalar> {
|
||||
using Base<Scalar>::field;
|
||||
using Base<Scalar>::method;
|
||||
static void m_fn1() {
|
||||
// expected-error@+1 {{invalid use of member 'field' in static member function}}
|
||||
(void)field;
|
||||
// expected-error@+1 {{invalid use of member 'field' in static member function}}
|
||||
(void)&field;
|
||||
// expected-error@+1 {{call to non-static member function without an object argument}}
|
||||
(void)method;
|
||||
// expected-error@+1 {{call to non-static member function without an object argument}}
|
||||
(void)&method;
|
||||
// expected-error@+1 {{call to non-static member function without an object argument}}
|
||||
method();
|
||||
(void)&Base<Scalar>::field;
|
||||
(void)&Base<Scalar>::method;
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
// These usages are OK in C++11 due to the unevaluated context.
|
||||
enum { TheSize = sizeof(field) };
|
||||
typedef decltype(field) U;
|
||||
#else
|
||||
// expected-error@+1 {{invalid use of non-static data member 'field'}}
|
||||
enum { TheSize = sizeof(field) };
|
||||
#endif
|
||||
};
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
// C++98 has an extra note for TheSize.
|
||||
// expected-note@+2 {{requested here}}
|
||||
#endif
|
||||
template class Derived<int>; // expected-note {{requested here}}
|
||||
|
||||
// This is interesting because we form an UnresolvedLookupExpr in the static
|
||||
// function template and an UnresolvedMemberExpr in the instance function
|
||||
// template. As a result, we get slightly different behavior.
|
||||
struct UnresolvedTemplateNames {
|
||||
template <typename> void maybe_static();
|
||||
#if __cplusplus < 201103L
|
||||
// expected-warning@+2 {{default template arguments for a function template are a C++11 extension}}
|
||||
#endif
|
||||
template <typename T, typename T::type = 0> static void maybe_static();
|
||||
|
||||
template <typename T>
|
||||
void instance_method() { (void)maybe_static<T>(); }
|
||||
template <typename T>
|
||||
static void static_method() {
|
||||
// expected-error@+1 {{call to non-static member function without an object argument}}
|
||||
(void)maybe_static<T>();
|
||||
}
|
||||
};
|
||||
void force_instantiation(UnresolvedTemplateNames x) {
|
||||
x.instance_method<int>();
|
||||
UnresolvedTemplateNames::static_method<int>(); // expected-note {{requested here}}
|
||||
}
|
||||
} // pr21923
|
||||
|
|
Loading…
Reference in New Issue