Hi,
I'm attaching a patch that makes it possible to access non-static data
members in a static context in unevaluated expressions (such as
sizeof), e.g.:
struct a { int b; };
char c[sizeof(a::b)];
This isn't permitted in C++03 but the rule has been relaxed in C++0x [1].
Best regards,
Jakub Wieczorek
[1] This is covered in the [expr.prim.general] section of the C++0x
draft, point 5.1.1.10.
Index: test/CXX/class/class.nest/p1.cpp
===================================================================
--- test/CXX/class/class.nest/p1.cpp (wersja 119186)
+++ test/CXX/class/class.nest/p1.cpp (kopia robocza)
@@ -3,12 +3,12 @@
class Outer {
int x;
static int sx;
+ int f();
- // C++0x will likely relax this rule in this specific case, but
- // we'll still need to enforce it in C++03 mode. See N2253 (or
- // successor).
+ // 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.
class Inner {
static char a[sizeof(x)]; // expected-error {{ invalid use of nonstatic 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 }}
};
};
Index: test/CXX/class/class.nest/p1-cxx0x.cpp
===================================================================
--- test/CXX/class/class.nest/p1-cxx0x.cpp (wersja 0)
+++ test/CXX/class/class.nest/p1-cxx0x.cpp (wersja 0)
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s
+class Outer {
+ int x;
+ static int sx;
+ int f();
+
+ // The first case is invalid in the C++03 mode but valid in C++0x (see 5.1.1.10).
+ class Inner {
+ static char a[sizeof(x)]; // okay
+ static char b[sizeof(sx)]; // okay
+ static char c[sizeof(f)]; // expected-error {{ call to non-static member function without an object argument }}
+ };
+};
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp (wersja 119186)
+++ lib/Sema/SemaExpr.cpp (kopia robocza)
@@ -1070,10 +1070,14 @@
// Collect all the declaring classes of instance members we find.
bool hasNonInstance = false;
+ bool hasField = false;
llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes;
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
NamedDecl *D = *I;
if (D->isCXXInstanceMember()) {
+ if (dyn_cast<FieldDecl>(D))
+ hasField = true;
+
CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
// If this is a member of an anonymous record, move out to the
@@ -1096,8 +1100,24 @@
// If the current context is not an instance method, it can't be
// an implicit member reference.
- if (isStaticContext)
- return (hasNonInstance ? IMA_Mixed_StaticContext : IMA_Error_StaticContext);
+ if (isStaticContext) {
+ if (hasNonInstance)
+ return IMA_Mixed_StaticContext;
+
+ if (SemaRef.getLangOptions().CPlusPlus0x && hasField) {
+ // C++0x [expr.prim.general]p10:
+ // An id-expression that denotes a non-static data member or non-static
+ // member function of a class can only be used:
+ // (...)
+ // - if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
+ const Sema::ExpressionEvaluationContextRecord& record = SemaRef.ExprEvalContexts.back();
+ bool isUnevaluatedExpression = record.Context == Sema::Unevaluated;
+ if (isUnevaluatedExpression)
+ return IMA_Mixed_StaticContext;
+ }
+
+ return IMA_Error_StaticContext;
+ }
// If we can prove that the current context is unrelated to all the
// declaring classes, it can't be an implicit member reference (in
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits