From 36e4ae3e57bcb97eb39bfc7580da100f4f6ca1e5 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Thu, 14 Apr 2011 00:46:47 +0000 Subject: [PATCH] When creating an implicit member expression through a qualified-id, check that the class named by the nested-name-specifier is same or base of the class in which the member expression appears. It seems we also had an ill-formed test case, mon dieu! Fixes rdar://8576107. llvm-svn: 129493 --- clang/lib/Sema/SemaExpr.cpp | 18 +++++++++++++++--- .../class.mfct/class.mfct.non-static/p3.cpp | 17 +++++++++++------ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index eb84cff99929..8ccb9b818044 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1318,12 +1318,24 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, return IMA_Error_StaticContext; } + CXXRecordDecl * + contextClass = cast(DC)->getParent()->getCanonicalDecl(); + + // [class.mfct.non-static]p3: + // ...is used in the body of a non-static member function of class X, + // if name lookup (3.4.1) resolves the name in the id-expression to a + // non-static non-type member of some class C [...] + // ...if C is not X or a base class of X, the class member access expression + // is ill-formed. + if (R.getNamingClass() && + contextClass != R.getNamingClass()->getCanonicalDecl() && + contextClass->isProvablyNotDerivedFrom(R.getNamingClass())) + return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + // If we can prove that the current context is unrelated to all the // declaring classes, it can't be an implicit member reference (in // which case it's an error if any of those members are selected). - if (IsProvablyNotDerivedFrom(SemaRef, - cast(DC)->getParent(), - Classes)) + if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); return (hasNonInstance ? IMA_Mixed : IMA_Instance); diff --git a/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp index c81e4ef1b1b8..9116e7146f81 100644 --- a/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp +++ b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp @@ -35,17 +35,22 @@ namespace test1 { struct A { void foo(Opaque1); // expected-note {{candidate}} void foo(Opaque2); // expected-note {{candidate}} - void test(); }; struct B : A { - + void test(); }; - void A::test() { - B::foo(Opaque1()); - B::foo(Opaque2()); - B::foo(Opaque3()); // expected-error {{no matching member function}} + struct C1 : A { }; + struct C2 : B { }; + + void B::test() { + A::foo(Opaque1()); + A::foo(Opaque2()); + A::foo(Opaque3()); // expected-error {{no matching member function}} + + C1::foo(Opaque1()); // expected-error {{call to non-static member function without an object argument}} + C2::foo(Opaque1()); // expected-error {{call to non-static member function without an object argument}} } }