ziangwan created this revision.
ziangwan added reviewers: rsmith, nickdesaulniers, kongyi, pirama, stephenkelly.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This is a continuation of https://reviews.llvm.org/D44844 and a potential fix 
for https://bugs.llvm.org/show_bug.cgi?id=36880.

  template <typename A>
  class Variant {
  public:
    Variant() {
      [this](auto value) { Construct(value); }(5); // false positive warning 
about "this" capture unused.
    }
  
  
    template <typename Arg>
    void Construct(Arg value) {}
  };
  
  
  int main() {
    Variant<int> v;
    return 0;
  }

Whenever we see a `UnresolvedMemberExpr`, we always mark a this capture 
ODR-used, even if later on it may be resolved to a static member function. The 
trade-off of this fix is that it will leads to false negative in the following 
case:

  template <typename A>
  class OverloadedMixFalseNegative {
  public:
    OverloadedMixFalseNegative() {
      [this](auto value) { Construct(value); }(5); // warning disappears but 
should happen
    }
  
    static void Construct(int value) {}
    void Construct(float value) {}
  };


Repository:
  rC Clang

https://reviews.llvm.org/D65549

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/SemaCXX/warn-unused-lambda-capture-this.cpp

Index: clang/test/SemaCXX/warn-unused-lambda-capture-this.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/warn-unused-lambda-capture-this.cpp
@@ -0,0 +1,80 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused-lambda-capture -verify %s
+
+template <typename A>
+class TemplatedStatic {
+public:
+  TemplatedStatic() {
+    [this](auto value) { Construct(value); }(5); // expected-warning {{lambda capture 'this' is not used}}
+  }
+
+  template <typename Arg>
+  static void Construct(Arg value) {}
+};
+
+template <typename A>
+class TemplatedMember {
+public:
+  TemplatedMember() {
+    [this](auto value) { Construct(value); }(5);
+  }
+
+  template <typename Arg>
+  void Construct(Arg value) {}
+};
+
+template <typename A>
+class OverloadedStatic {
+public:
+  OverloadedStatic() {
+    [this](auto value) { Construct(value); }(5); // expected-warning {{lambda capture 'this' is not used}}
+  }
+
+  static void Construct(int value) {}
+  static void Construct(float value) {}
+};
+
+template <typename A>
+class OverloadedMember {
+public:
+  OverloadedMember() {
+    [this](auto value) { Construct(value); }(5);
+  }
+
+  void Construct(int value) {}
+  void Construct(float value) {}
+};
+
+template <typename A>
+class OverloadedMixTrueNegative {
+public:
+  OverloadedMixTrueNegative() {
+    [this](auto value) { Construct(value); }(5);
+  }
+
+  void Construct(int value) {}
+  static void Construct(float value) {}
+};
+
+template <typename A>
+class OverloadedMixFalseNegative {
+public:
+  OverloadedMixFalseNegative() {
+    // Currently we mark this capture as used whenever UnresolvedMemberExpr
+    // happens, even if "Construct" will be resolved to the static one.
+    // Ideally we should issue 'this' not used warning.
+    [this](auto value) { Construct(value); }(5);
+  }
+
+  static void Construct(int value) {}
+  void Construct(float value) {}
+};
+
+int main() {
+  TemplatedStatic<int> t1; // expected-note {{in instantiation of member function 'TemplatedStatic<int>::TemplatedStatic' requested here}}
+  TemplatedMember<int> t2;
+  OverloadedStatic<int> t3; // expected-note {{in instantiation of member function 'OverloadedStatic<int>::OverloadedStatic' requested here}}
+  OverloadedMember<int> t4;
+  OverloadedMixTrueNegative<int> t5;
+  OverloadedMixFalseNegative<int> t6;
+  return 0;
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -5619,6 +5619,17 @@
             *this, dyn_cast<UnresolvedMemberExpr>(Fn->IgnoreParens()),
             Fn->getBeginLoc());
 
+        // Mark this capture as ODR-used if we are in a lambda
+        // expression and the callee is UnresolvedMemberExpr.
+        LambdaScopeInfo *CurLSI = getCurLambda();
+        if (CurLSI && isa<UnresolvedMemberExpr>(Fn->IgnoreParens())) {
+          for (auto &Capture : CurLSI->Captures) {
+            if (Capture.isThisCapture()) {
+              Capture.markUsed(/*IsODRUse=*/true);
+            }
+          }
+        }
+
         return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
                                 VK_RValue, RParenLoc);
       }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to