From: Sebastian Redl Date: Fri, 26 Nov 2010 16:28:07 +0000 (+0000) Subject: Allow access to non-static members without an object in sizeof expressions, in C... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f9780007a9c31a46a025bdd3eaf5c2be31eb4c0e;p=clang Allow access to non-static members without an object in sizeof expressions, in C++0x. Patch by Jakub Wieczorek. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120182 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 2daeed1257..087314fbcb 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1038,11 +1038,15 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // Collect all the declaring classes of instance members we find. bool hasNonInstance = false; + bool hasField = false; llvm::SmallPtrSet Classes; for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *D = *I; if (D->isCXXInstanceMember()) { + if (dyn_cast(D)) + hasField = true; + CXXRecordDecl *R = cast(D->getDeclContext()); Classes.insert(R->getCanonicalDecl()); } @@ -1057,8 +1061,24 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // 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 diff --git a/test/CXX/class/class.nest/p1.cpp b/test/CXX/class/class.nest/p1.cpp index f1f5496d56..350cc814e9 100644 --- a/test/CXX/class/class.nest/p1.cpp +++ b/test/CXX/class/class.nest/p1.cpp @@ -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 }} }; };