Hi all,
Looking closer at the differences between 'this' in static member
function declarations, and non-member function declarations, I was able
to come up with a few more cases that highlight the special treatment it
needs, and hopefully prevent others from making the same mistake I did.
I no longer think it makes sense to merge the two separate checks for
'this', at least not right now.
Allowing implicit 'this', as noted in the test suite already, is
trivially done, especially given that the check to see whether the use
is implicit already existed.
I was unfortunately unable to come up with a testcase that uses 'this'
(whether explicitly or implicitly) in a C++11 attribute for a member
function declaration, so I also cannot tell whether
checkThisInStaticMemberFunctionAttributes is still needed. Removing it
doesn't make any test fail, but that isn't telling much.
Alp, is this the sort of test suite modification you were asking for?
Cheers,
Harald van Dijk
> On 17/01/14 01:03, Alp Toker wrote:
>> On 16/01/2014 06:38, Harald van Dijk wrote:
>>> Ah, thanks, you're right. If the in-class declaration doesn't use
>>> 'this', but the definition does, then 'this' would not be diagnosed with
>>> my approach.
>>
>> Hi Harald,
>>
>> If you have the time could you throw together a couple of tests for
>> those cases as well?
>>
>> checkThisInStaticMemberFunctionAttributes() looks like it can be dropped
>> now that RecursiveASTVisitor visits attributes (r198224) so I'm hopeful
>> we can still apply the bulk of the cleanup from your original patch
>> without regressing.
Allow implicit 'this' in static member func decls
C++11 says "[this] shall not appear before the optional cv-qualifier-seq
and it shall not appear within the declaration of a static member
function (although its type and value category are defined within a
static member function as they are within a non-static member function).
This does not prohibit implicit use of 'this' by referring to other
members by unqualified name. The test suite already contains a FIXME
note about that.
Add some tests to the test suite to check that 'static' and 'friend'
functions don't get treated the same way. In static member function
declarations, 'this' exists, but the keyword may not appear. In friend
function declarations, 'this' does not exist.
---
include/clang/Basic/DiagnosticSemaKinds.td | 3 +--
lib/Parse/ParseDecl.cpp | 1 -
lib/Sema/SemaDeclCXX.cpp | 4 ++--
.../CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp | 25 ++++++++++++++++++----
4 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 59ade9e..d8c385a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4660,8 +4660,7 @@ def note_logical_not_silence_with_parens : Note<
def err_invalid_this_use : Error<
"invalid use of 'this' outside of a non-static member function">;
def err_this_static_member_func : Error<
- "'this' cannot be%select{| implicitly}0 used in a static member function "
- "declaration">;
+ "'this' cannot be used in a static member function declaration">;
def err_invalid_member_use_in_static_method : Error<
"invalid use of member %0 in static member function">;
def err_invalid_qualified_function_type : Error<
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e8207bc..cf4a190 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -5152,7 +5152,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
// and the end of the function-definition, member-declarator, or
// declarator.
- // FIXME: currently, "static" case isn't handled correctly.
bool IsCXX11MemberFunction =
getLangOpts().CPlusPlus11 &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 608f11c..128e8ab 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -12625,8 +12625,8 @@ namespace {
explicit FindCXXThisExpr(Sema &S) : S(S) { }
bool VisitCXXThisExpr(CXXThisExpr *E) {
- S.Diag(E->getLocation(), diag::err_this_static_member_func)
- << E->isImplicit();
+ if (!E->isImplicit())
+ S.Diag(E->getLocation(), diag::err_this_static_member_func);
return false;
}
};
diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
index fd90482..96e6c55 100644
--- a/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
@@ -108,16 +108,18 @@ namespace PR15290 {
namespace Static {
struct X1 {
int m;
- // FIXME: This should be accepted.
- static auto f() -> decltype(m); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+ static auto f() -> decltype(m);
static auto g() -> decltype(this->m); // expected-error{{'this' cannot be used in a static member function declaration}}
static int h();
+ static int i();
- static int i() noexcept(noexcept(m + 2)); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+ static int j() noexcept(noexcept(m + 2));
+ static int k() noexcept(noexcept(this->m + 2)); // expected-error{{'this' cannot be used in a static member function declaration}}
};
- auto X1::h() -> decltype(m) { return 0; } // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+ auto X1::h() -> decltype(m) { return 0; }
+ auto X1::i() -> decltype(this->m) { return 0; } // expected-error{{'this' cannot be used in a static member function declaration}}
template<typename T>
struct X2 {
@@ -134,6 +136,21 @@ namespace Static {
}
}
+namespace StaticVsFriend {
+ template <typename T>
+ struct X {
+ int f();
+ static auto g() -> decltype(f());
+ friend auto h() -> decltype(f()); // expected-error{{call to non-static member function without an object argument}}
+ static auto i() -> decltype(this->f()); // expected-error{{'this' cannot be used in a static member function declaration}}
+ friend auto j() -> decltype(this->f()); // expected-error{{invalid use of 'this' outside of a non-static member function}}
+ static void k() noexcept(noexcept(f()));
+ friend void l() noexcept(noexcept(f())); // expected-error{{call to non-static member function without an object argument}}
+ static void m() noexcept(noexcept(this->f())); // expected-error{{'this' cannot be used in a static member function declaration}}
+ friend void n() noexcept(noexcept(this->f())); // expected-error{{invalid use of 'this' outside of a non-static member function}}
+ };
+}
+
namespace PR12564 {
struct Base {
void bar(Base&) {} // FIXME: expected-note {{here}}
--
1.8.5.2
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits