r373247 - Teach CallGraph to look into Generic Lambdas.

Keane, Erich via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 3 06:27:15 PDT 2019


Yep, I agree.  I tend to figure if I can get it done in ~1-2 hours, that I could just fix it.  Note that this was 1:30 😊

From: Nico Weber <thakis at chromium.org>
Sent: Wednesday, October 2, 2019 4:37 PM
To: Keane, Erich <erich.keane at intel.com>
Cc: cfe-commits <cfe-commits at lists.llvm.org>
Subject: Re: r373247 - Teach CallGraph to look into Generic Lambdas.

Thanks!

If it takes a few hours to investigate, I think it's better to revert first and then investigate while the tree is green.

On Mon, Sep 30, 2019 at 4:43 PM Keane, Erich <erich.keane at intel.com<mailto:erich.keane at intel.com>> wrote:
Should be fixe din r373259

From: Nico Weber <thakis at chromium.org<mailto:thakis at chromium.org>>
Sent: Monday, September 30, 2019 12:50 PM
To: Keane, Erich <erich.keane at intel.com<mailto:erich.keane at intel.com>>
Cc: cfe-commits <cfe-commits at lists.llvm.org<mailto:cfe-commits at lists.llvm.org>>
Subject: Re: r373247 - Teach CallGraph to look into Generic Lambdas.

This broke a few clangd unit tests:

http://lab.llvm.org:8011/builders/clang-ppc64be-linux/builds/38857/steps/ninja%20check%201/logs/FAIL%3A%20Clangd%20Unit%20Tests%3A%3AHover.Structured
http://lab.llvm.org:8011/builders/clang-ppc64be-linux/builds/38857/steps/ninja%20check%201/logs/FAIL%3A%20Clangd%20Unit%20Tests%3A%3AHover.All
http://45.33.8.238/linux/680/step_7.txt

On Mon, Sep 30, 2019 at 3:10 PM Erich Keane via cfe-commits <cfe-commits at lists.llvm.org<mailto:cfe-commits at lists.llvm.org>> wrote:
Author: erichkeane
Date: Mon Sep 30 12:12:29 2019
New Revision: 373247

URL: http://llvm.org/viewvc/llvm-project?rev=373247&view=rev
Log:
Teach CallGraph to look into Generic Lambdas.

CallGraph visited LambdaExpr by getting the Call Operator from
CXXRecordDecl (LambdaExpr::getCallOperator calls
CXXRecordDecl::getLambdaCallOperator), which replaced generic lambda
call operators with the non-instantiated FunctionDecl.  The result was
that the CallGraph would only pick up non-dependent calls.

This patch does a few things:
1- Extend CXXRecordDecl to have a getDependentLambdaCallOperator, which
will get the FunctionTemplateDecl, rather than immediately getting the
TemplateDecl.
2- Define getLambdaCallOperator and getDependentLambdaCallOperator in
terms of a common function.
3- Extend LambdaExpr with a getDependentCallOperator, which just calls
the above function.
4- Changes CallGraph to handle Generic LambdaExprs.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/Analysis/CallGraph.cpp
    cfe/trunk/test/Analysis/debug-CallGraph.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=373247&r1=373246&r2=373247&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Sep 30 12:12:29 2019
@@ -1172,6 +1172,10 @@ public:
   /// if this is a closure type.
   CXXMethodDecl *getLambdaCallOperator() const;

+  /// Retrieve the dependent lambda call operator of the closure type
+  /// if this is a templated closure type.
+  FunctionTemplateDecl *getDependentLambdaCallOperator() const;
+
   /// Retrieve the lambda static invoker, the address of which
   /// is returned by the conversion operator, and the body of which
   /// is forwarded to the lambda call operator.

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=373247&r1=373246&r2=373247&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Sep 30 12:12:29 2019
@@ -1907,6 +1907,10 @@ public:
   /// lambda expression.
   CXXMethodDecl *getCallOperator() const;

+  /// Retrieve the function template call operator associated with this
+  /// lambda expression.
+  FunctionTemplateDecl *getDependentCallOperator() const;
+
   /// If this is a generic lambda expression, retrieve the template
   /// parameter list associated with it, or else return null.
   TemplateParameterList *getTemplateParameterList() const;

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=373247&r1=373246&r2=373247&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Sep 30 12:12:29 2019
@@ -1399,17 +1399,25 @@ static bool allLookupResultsAreTheSame(c
 }
 #endif

-CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
-  if (!isLambda()) return nullptr;
+NamedDecl* getLambdaCallOperatorHelper(const CXXRecordDecl &RD) {
+  if (!RD.isLambda()) return nullptr;
   DeclarationName Name =
-    getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
-  DeclContext::lookup_result Calls = lookup(Name);
+    RD.getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclContext::lookup_result Calls = RD.lookup(Name);

   assert(!Calls.empty() && "Missing lambda call operator!");
   assert(allLookupResultsAreTheSame(Calls) &&
          "More than one lambda call operator!");
+  return Calls.front();
+}
+
+FunctionTemplateDecl* CXXRecordDecl::getDependentLambdaCallOperator() const {
+  NamedDecl *CallOp = getLambdaCallOperatorHelper(*this);
+  return  dyn_cast<FunctionTemplateDecl>(CallOp);
+}

-  NamedDecl *CallOp = Calls.front();
+CXXMethodDecl *CXXRecordDecl::getLambdaCallOperator() const {
+  NamedDecl *CallOp = getLambdaCallOperatorHelper(*this);
   if (const auto *CallOpTmpl = dyn_cast<FunctionTemplateDecl>(CallOp))
     return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());


Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=373247&r1=373246&r2=373247&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Sep 30 12:12:29 2019
@@ -1218,6 +1218,11 @@ CXXMethodDecl *LambdaExpr::getCallOperat
   return Record->getLambdaCallOperator();
 }

+FunctionTemplateDecl *LambdaExpr::getDependentCallOperator() const {
+  CXXRecordDecl *Record = getLambdaClass();
+  return Record->getDependentLambdaCallOperator();
+}
+
 TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
   CXXRecordDecl *Record = getLambdaClass();
   return Record->getGenericLambdaTemplateParameterList();

Modified: cfe/trunk/lib/Analysis/CallGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CallGraph.cpp?rev=373247&r1=373246&r2=373247&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CallGraph.cpp (original)
+++ cfe/trunk/lib/Analysis/CallGraph.cpp Mon Sep 30 12:12:29 2019
@@ -80,7 +80,10 @@ public:
   }

   void VisitLambdaExpr(LambdaExpr *LE) {
-    if (CXXMethodDecl *MD = LE->getCallOperator())
+    if (FunctionTemplateDecl *FTD = LE->getDependentCallOperator())
+      for (FunctionDecl *FD : FTD->specializations())
+        G->VisitFunctionDecl(FD);
+    else if (CXXMethodDecl *MD = LE->getCallOperator())
       G->VisitFunctionDecl(MD);
   }


Modified: cfe/trunk/test/Analysis/debug-CallGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/debug-CallGraph.cpp?rev=373247&r1=373246&r2=373247&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/debug-CallGraph.cpp (original)
+++ cfe/trunk/test/Analysis/debug-CallGraph.cpp Mon Sep 30 12:12:29 2019
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCallGraph %s -fblocks 2>&1 | FileCheck %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCallGraph %s -fblocks -std=c++14 2>&1 | FileCheck %s

 int get5() {
   return 5;
@@ -68,8 +68,25 @@ void templUser() {
 }
 }

+namespace Lambdas {
+  void Callee(){}
+
+  void f1() {
+    [](int i) {
+      Callee();
+    }(1);
+    [](auto i) {
+      Callee();
+    }(1);
+  }
+}
+
 // CHECK:--- Call graph Dump ---
-// CHECK-NEXT: {{Function: < root > calls: get5 add test_add mmm foo aaa < > bbb ddd ccc eee fff do_nothing test_single_call SomeNS::templ SomeNS::templ SomeNS::templUser $}}
+// CHECK-NEXT: {{Function: < root > calls: get5 add test_add mmm foo aaa < > bbb ddd ccc eee fff do_nothing test_single_call SomeNS::templ SomeNS::templ SomeNS::templUser Lambdas::Callee Lambdas::f1 Lambdas::f1\(\)::\(anonymous class\)::operator\(\) Lambdas::f1\(\)::\(anonymous class\)::operator\(\) $}}
+// CHECK-NEXT: {{Function: Lambdas::f1 calls: Lambdas::f1\(\)::\(anonymous class\)::operator\(\) Lambdas::f1\(\)::\(anonymous class\)::operator\(\) $}}
+// CHECK-NEXT: {{Function: Lambdas::f1\(\)::\(anonymous class\)::operator\(\) calls: Lambdas::Callee $}}
+// CHECK-NEXT: {{Function: Lambdas::f1\(\)::\(anonymous class\)::operator\(\) calls: Lambdas::Callee $}}
+// CHECK-NEXT: {{Function: Lambdas::Callee calls: $}}
 // CHECK-NEXT: {{Function: SomeNS::templUser calls: SomeNS::templ SomeNS::templ $}}
 // CHECK-NEXT: {{Function: SomeNS::templ calls: eee $}}
 // CHECK-NEXT: {{Function: SomeNS::templ calls: ccc $}}


_______________________________________________
cfe-commits mailing list
cfe-commits at lists.llvm.org<mailto:cfe-commits at lists.llvm.org>
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191003/3e1099c0/attachment-0001.html>


More information about the cfe-commits mailing list