summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-05 01:13:04 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-05 01:13:04 +0000
commita85cf39786fffd6860a940523be01eb02a4935c0 (patch)
tree49e6b78abb519f6ddf1db6d7a31f3fbd66ea43c7
parent4fd05dc4062580acea72f8b8231fb0ea3ee49032 (diff)
Improve diagnostics for invalid use of non-static members / this:
* s/nonstatic/non-static/ in the diagnostics, since the latter form outvoted the former by 28-2 in our diagnostics. * Fix the "use of member in static member function" diagnostic to correctly detect this situation inside a block or lambda. * Produce a more specific "invalid use of non-static member" diagnostic for the case where a nested class member refers to a member of a lexically-surrounding class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154073 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td7
-rw-r--r--lib/Sema/SemaExprMember.cpp46
-rw-r--r--test/CXX/class/class.nest/p1.cpp4
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp2
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp4
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp2
-rw-r--r--test/CXX/special/class.free/p1.cpp4
-rw-r--r--test/CXX/special/class.free/p6.cpp4
-rw-r--r--test/Parser/cxx-typeof.cpp2
-rw-r--r--test/SemaCXX/class.cpp10
-rw-r--r--test/SemaCXX/default2.cpp10
-rw-r--r--test/SemaCXX/qual-id-test.cpp2
-rw-r--r--test/SemaCXX/this.cpp4
13 files changed, 57 insertions, 44 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 3ecb4a7c80..a89217c472 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3769,7 +3769,7 @@ def warn_null_in_comparison_operation : Warning<
InGroup<DiagGroup<"null-arithmetic">>;
def err_invalid_this_use : Error<
- "invalid use of 'this' outside of a nonstatic member function">;
+ "invalid use of 'this' outside of a non-static member function">;
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<
@@ -3785,7 +3785,10 @@ def err_ref_qualifier_overload : Error<
"without a ref-qualifier|with ref-qualifier '&'|with ref-qualifier '&&'}1">;
def err_invalid_non_static_member_use : Error<
- "invalid use of nonstatic data member %0">;
+ "invalid use of non-static data member %0">;
+def err_nested_non_static_member_use : Error<
+ "%select{call to non-static member function|use of non-static data member}0 "
+ "%2 of %1 from nested type %3">;
def warn_cxx98_compat_non_static_member_use : Warning<
"use of non-static data member %0 in an unevaluated context is "
"incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 4155fdb9db..26b88a2a7e 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -194,30 +194,38 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
}
/// Diagnose a reference to a field with no object available.
-static void DiagnoseInstanceReference(Sema &SemaRef,
+static void diagnoseInstanceReference(Sema &SemaRef,
const CXXScopeSpec &SS,
- NamedDecl *rep,
+ NamedDecl *Rep,
const DeclarationNameInfo &nameInfo) {
SourceLocation Loc = nameInfo.getLoc();
SourceRange Range(Loc);
if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
-
- if (isa<FieldDecl>(rep) || isa<IndirectFieldDecl>(rep)) {
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) {
- if (MD->isStatic()) {
- // "invalid use of member 'x' in static member function"
- SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
- << Range << nameInfo.getName();
- return;
- }
- }
+ DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();
+ CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);
+ CXXRecordDecl *ContextClass = Method ? Method->getParent() : 0;
+ CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());
+
+ bool InStaticMethod = Method && Method->isStatic();
+ bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep);
+
+ if (IsField && InStaticMethod)
+ // "invalid use of member 'x' in static member function"
+ SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
+ << Range << nameInfo.getName();
+ else if (ContextClass && RepClass && SS.isEmpty() && !InStaticMethod &&
+ !RepClass->Equals(ContextClass) && RepClass->Encloses(ContextClass))
+ // Unqualified lookup in a non-static member function found a member of an
+ // enclosing class.
+ SemaRef.Diag(Loc, diag::err_nested_non_static_member_use)
+ << IsField << RepClass << nameInfo.getName() << ContextClass << Range;
+ else if (IsField)
SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
- << nameInfo.getName() << Range;
- return;
- }
-
- SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range;
+ << nameInfo.getName() << Range;
+ else
+ SemaRef.Diag(Loc, diag::err_member_call_without_object)
+ << Range;
}
/// Builds an expression which might be an implicit member expression.
@@ -248,7 +256,7 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
case IMA_Error_StaticContext:
case IMA_Error_Unrelated:
- DiagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
+ diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
R.getLookupNameInfo());
return ExprError();
}
@@ -468,7 +476,7 @@ static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
// If this is an implicit member access, use a different set of
// diagnostics.
if (!BaseExpr)
- return DiagnoseInstanceReference(SemaRef, SS, rep, nameInfo);
+ return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo);
SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated)
<< SS.getRange() << rep << BaseType;
diff --git a/test/CXX/class/class.nest/p1.cpp b/test/CXX/class/class.nest/p1.cpp
index 9eaeff0734..b0341da7c2 100644
--- a/test/CXX/class/class.nest/p1.cpp
+++ b/test/CXX/class/class.nest/p1.cpp
@@ -5,9 +5,9 @@ class Outer {
static int sx;
int f();
- // C++0x does relax this rule (see 5.1.1.10) in the first case, but we need to enforce it in C++03 mode.
+ // C++11 does relax this rule (see 5.1.1.10) in the first case, but we need to enforce it in C++03 mode.
class Inner {
- static char a[sizeof(x)]; // expected-error {{invalid use of nonstatic data member 'x'}}
+ static char a[sizeof(x)]; // expected-error {{invalid use of non-static data member 'x'}}
static char b[sizeof(sx)]; // okay
static char c[sizeof(f)]; // expected-error {{call to non-static member function without an object argument}}
};
diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp
index 606300b1b2..249c976460 100644
--- a/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp
@@ -26,7 +26,7 @@ namespace std {
}
class Poly { virtual ~Poly(); };
const std::type_info& k = typeid(S::m);
-const std::type_info& m = typeid(*(Poly*)S::m); // expected-error {{invalid use of nonstatic data member}}
+const std::type_info& m = typeid(*(Poly*)S::m); // expected-error {{invalid use of non-static data member}}
const std::type_info& n = typeid(*(Poly*)(0*sizeof S::m));
namespace PR11956 {
diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp
index b9f0414e91..4e57b74f08 100644
--- a/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp
@@ -2,9 +2,9 @@
struct S {
S *p = this; // ok
- decltype(this) q; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ decltype(this) q; // expected-error {{invalid use of 'this' outside of a non-static member function}}
- int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a non-static member function}}
int sz = sizeof(this); // ok
};
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
index 9da9fcea1f..4a2a4f3d73 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
@@ -27,7 +27,7 @@ struct ReachingThis {
static void static_bar() {
(void)[this](){}; // expected-error{{'this' cannot be captured in this context}}
- (void)[&](){i = 7; }; // expected-error{{invalid use of nonstatic data member 'i'}}
+ (void)[&](){i = 7; }; // expected-error{{invalid use of member 'i' in static member function}}
}
};
}
diff --git a/test/CXX/special/class.free/p1.cpp b/test/CXX/special/class.free/p1.cpp
index e4fe127f9f..5c0240b5da 100644
--- a/test/CXX/special/class.free/p1.cpp
+++ b/test/CXX/special/class.free/p1.cpp
@@ -3,9 +3,9 @@
struct A {
void *operator new(size_t) {
- return this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ return this; // expected-error {{invalid use of 'this' outside of a non-static member function}}
}
void *operator new[](size_t) {
- return this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ return this; // expected-error {{invalid use of 'this' outside of a non-static member function}}
}
};
diff --git a/test/CXX/special/class.free/p6.cpp b/test/CXX/special/class.free/p6.cpp
index 555d4e9cfa..fc4b2ae1ac 100644
--- a/test/CXX/special/class.free/p6.cpp
+++ b/test/CXX/special/class.free/p6.cpp
@@ -3,9 +3,9 @@
struct A {
void operator delete(void*) {
- (void)this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ (void)this; // expected-error {{invalid use of 'this' outside of a non-static member function}}
}
void operator delete[](void*) {
- (void)this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ (void)this; // expected-error {{invalid use of 'this' outside of a non-static member function}}
}
};
diff --git a/test/Parser/cxx-typeof.cpp b/test/Parser/cxx-typeof.cpp
index 4c598e9517..1ec6e29b13 100644
--- a/test/Parser/cxx-typeof.cpp
+++ b/test/Parser/cxx-typeof.cpp
@@ -9,5 +9,5 @@ static void test() {
// Part of rdar://problem/8347416; from the gcc test suite.
struct S {
int i;
- __typeof(S::i) foo(); // expected-error {{invalid use of nonstatic data member 'i'}}
+ __typeof(S::i) foo(); // expected-error {{invalid use of non-static data member 'i'}}
};
diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp
index e079d0cc17..ec82925fe4 100644
--- a/test/SemaCXX/class.cpp
+++ b/test/SemaCXX/class.cpp
@@ -7,16 +7,18 @@ public:
static void sm() {
sx = 0;
- this->x = 0; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ this->x = 0; // expected-error {{invalid use of 'this' outside of a non-static member function}}
x = 0; // expected-error {{invalid use of member 'x' in static member function}}
}
class NestedC {
public:
NestedC(int);
- void m() {
+ void f() {
sx = 0;
- x = 0; // expected-error {{invalid use of nonstatic data member 'x'}}
+ x = 0; // expected-error {{use of non-static data member 'x' of 'C' from nested type 'NestedC'}}
+ sm();
+ m(); // expected-error {{call to non-static member function 'm' of 'C' from nested type 'NestedC'}}
}
};
@@ -186,7 +188,7 @@ struct S {
};
void f() {
- S::c; // expected-error {{invalid use of nonstatic data member}}
+ S::c; // expected-error {{invalid use of non-static data member}}
}
}
diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp
index 20763229cf..16260449d4 100644
--- a/test/SemaCXX/default2.cpp
+++ b/test/SemaCXX/default2.cpp
@@ -28,7 +28,7 @@ void g(int x, int y = x); // expected-error {{default argument references parame
void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}}
class X {
- void f(X* x = this); // expected-error{{invalid use of 'this' outside of a nonstatic member function}}
+ void f(X* x = this); // expected-error{{invalid use of 'this' outside of a non-static member function}}
void g() {
int f(X* x = this); // expected-error{{default argument references 'this'}}
@@ -55,7 +55,7 @@ void C::h() {
// C++ [dcl.fct.default]p9
struct Y {
int a;
- int mem1(int i = a); // expected-error{{invalid use of nonstatic data member 'a'}}
+ int mem1(int i = a); // expected-error{{invalid use of non-static data member 'a'}}
int mem2(int i = b); // OK; use Y::b
int mem3(int i);
int mem4(int i);
@@ -64,8 +64,8 @@ struct Y {
int mem5(int i = b, // OK; use Y::b
int j = c, // OK; use Y::Nested::c
int k = j, // expected-error{{default argument references parameter 'j'}}
- int l = a, // expected-error{{invalid use of nonstatic data member 'a'}}
- Nested* self = this, // expected-error{{invalid use of 'this' outside of a nonstatic member function}}
+ int l = a, // expected-error{{invalid use of non-static data member 'a'}}
+ Nested* self = this, // expected-error{{invalid use of 'this' outside of a non-static member function}}
int m); // expected-error{{missing default argument on parameter 'm'}}
static int c;
Nested(int i = 42);
@@ -78,7 +78,7 @@ struct Y {
int Y::mem3(int i = b) { return i; } // OK; use X::b
-int Y::mem4(int i = a) // expected-error{{invalid use of nonstatic data member 'a'}}
+int Y::mem4(int i = a) // expected-error{{invalid use of non-static data member 'a'}}
{ return i; }
diff --git a/test/SemaCXX/qual-id-test.cpp b/test/SemaCXX/qual-id-test.cpp
index e5c7306775..e43e6887c4 100644
--- a/test/SemaCXX/qual-id-test.cpp
+++ b/test/SemaCXX/qual-id-test.cpp
@@ -137,7 +137,7 @@ struct a {
a a;
-int a::sa = a.a; // expected-error {{invalid use of nonstatic data member 'a'}}
+int a::sa = a.a; // expected-error {{invalid use of non-static data member 'a'}}
namespace PR6645 {
diff --git a/test/SemaCXX/this.cpp b/test/SemaCXX/this.cpp
index 13158b93a4..27ee1e84a7 100644
--- a/test/SemaCXX/this.cpp
+++ b/test/SemaCXX/this.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-int x = this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+int x = this; // expected-error {{invalid use of 'this' outside of a non-static member function}}
void f() {
- int x = this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ int x = this; // expected-error {{invalid use of 'this' outside of a non-static member function}}
}