C++ PATCH for c++/84151, wrong volatile load calling static member function

Message ID CADzB+2nKLfc+azaGGktBHxdUCji-oYEKOyoUZ9gH+8a-MF6V2w@mail.gmail.com
State New
Headers show
Series
  • C++ PATCH for c++/84151, wrong volatile load calling static member function
Related show

Commit Message

Jason Merrill Feb. 16, 2018, 8:58 p.m.
In an expression like a.f(), if f is a static member function, a is
still evaluated.  But if a is a volatile lvalue, we don't want to do
the discarded-value load; what's really evaluated is the 'this'
argument, which is the address of a.

Tested x86_64-pc-linux-gnu, applying to trunk and 7.
commit 50db20e0e5254f85f0e37659802dd9807455f74b
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Feb 16 15:43:07 2018 -0500

            PR c++/84151 - unnecessary volatile load with static member.
    
            * call.c (build_new_method_call_1): Avoid loading from a volatile
            lvalue used as the object argument for a static member function.

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d3d0966f65c..7c93c6d8290 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -9284,8 +9284,14 @@  build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
 	      if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
 		  && !is_dummy_object (instance)
 		  && TREE_SIDE_EFFECTS (instance))
-		call = build2 (COMPOUND_EXPR, TREE_TYPE (call),
-			       instance, call);
+		{
+		  /* But avoid the implicit lvalue-rvalue conversion when 'a'
+		     is volatile.  */
+		  tree a = instance;
+		  if (TREE_THIS_VOLATILE (a))
+		    a = build_this (a);
+		  call = build2 (COMPOUND_EXPR, TREE_TYPE (call), a, call);
+		}
 	      else if (call != error_mark_node
 		       && DECL_DESTRUCTOR_P (cand->fn)
 		       && !VOID_TYPE_P (TREE_TYPE (call)))
diff --git a/gcc/testsuite/g++.dg/tree-ssa/volatile1.C b/gcc/testsuite/g++.dg/tree-ssa/volatile1.C
new file mode 100644
index 00000000000..00f04a07d84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/volatile1.C
@@ -0,0 +1,28 @@ 
+// PR c++/84151
+// { dg-additional-options "-fdump-tree-gimple" }
+// { dg-final { scan-tree-dump-not {\*this} "gimple" } }
+
+struct A {
+  static int& bar(int& a) {
+    return a;
+  }
+  static int i;
+
+  int foo() volatile {
+    int v = c;
+    return i + bar(v);
+  }
+
+  int c;
+};
+
+int A::i = 0;
+
+A a;
+
+int main() {
+  a.c = 2;
+  a.foo();
+
+  return 0;
+}