[PATCH] C++11: if decl-specifier has 'friend' or 'static', do not allow access to 'this' pointer when parsing function declarator.

Ismail Pazarbasi ismail.pazarbasi at gmail.com
Tue Feb 26 14:00:22 PST 2013


ismailp added you to the CC list for the revision "C++11: if decl-specifier has 'friend' or 'static', do not allow access to 'this' pointer when parsing function declarator.".

Hi rsmith, rjmccall,

Hi,

the problem was discovered after bug #15290. My initial patch was merely masking the issue, and offered no real fix. Richard Smith suggested parser doesn't take 'friend' specifier into account when checking whether a method can access 'this' pointer to form a class member access expression.

Operands of decltype and noexcept are unevaluated operands. Unevaluated operands cannot explicitly contain 'this' pointer, but non-static class member may be named ([expr]/p7). This expression should not be transform into a class member access expression, which is the purpose of this patch.

After Richard has shown the problem, I have also added a check for static methods.

http://llvm-reviews.chandlerc.com/D468

Files:
  lib/Parse/ParseDecl.cpp
  test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp

Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -4807,12 +4807,16 @@
       //   "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
       //   and the end of the function-definition, member-declarator, or
       //   declarator.
+      bool IsMemberContext = D.getContext() == Declarator::MemberContext;
       bool IsCXX11MemberFunction =
         getLangOpts().CPlusPlus11 &&
-        (D.getContext() == Declarator::MemberContext ||
+        (IsMemberContext ||
          (D.getContext() == Declarator::FileContext &&
           D.getCXXScopeSpec().isValid() &&
-          Actions.CurContext->isRecord()));
+          Actions.CurContext->isRecord())) &&
+        !(IsMemberContext &&
+         (D.getDeclSpec().isFriendSpecified() ||
+          D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static));
       Sema::CXXThisScopeRAII ThisScope(Actions,
                                dyn_cast<CXXRecordDecl>(Actions.CurContext),
                                DS.getTypeQualifiers() |
Index: test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
===================================================================
--- test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
+++ test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
@@ -64,12 +64,12 @@
 namespace Static {
   struct X1 {
     int m;
-    static auto f() -> decltype(m); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
-    static auto g() -> decltype(this->m); // expected-error{{'this' cannot be used in a static member function declaration}}
+    static auto f() -> decltype(m);
+    static auto g() -> decltype(this->m); // expected-error{{invalid use of 'this' outside of a non-static member function}}
 
     static int h();
     
-    static int i() noexcept(noexcept(m + 2)); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+    static int i() noexcept(noexcept(m + 2));
   };
 
   auto X1::h() -> decltype(m) { return 0; } // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
@@ -99,3 +99,34 @@
     void foo(Derived& d) noexcept(noexcept(d.bar(d))) {} // expected-error {{cannot bind to a value of unrelated type}}
   };
 }
+
+namespace unevaluated_operands {
+  template<typename T>
+  class noexcept_operand_template {
+    T v_;
+    friend int add_to_v(noexcept_operand_template &t) noexcept(noexcept(v_ + 42))
+    {
+      return t.v_ + 42;
+    }
+  public:
+    static int sub_from_v(noexcept_operand_template &t) noexcept(noexcept(v_ - 42))
+    {
+      return t.v_ - 42;
+    }
+  };
+
+  void dont_transform_cxx_member_expr()
+  {
+    noexcept_operand_template<int> t;
+    add_to_v(t);
+    noexcept_operand_template<int>::sub_from_v(t);
+  }
+
+  struct decltype_operand {
+    int v_;
+    friend auto i() -> decltype(v_);
+    static auto j() -> decltype(v_);
+    friend auto f() -> decltype(this); // expected-error{{invalid use of 'this' outside of a non-static member function}}
+    static auto k() -> decltype(this->v_); // expected-error{{invalid use of 'this' outside of a non-static member function}}
+  };
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D468.1.patch
Type: text/x-patch
Size: 3275 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130226/f702c535/attachment.bin>


More information about the cfe-commits mailing list