File tree 6 files changed +49
-8
lines changed
6 files changed +49
-8
lines changed Original file line number Diff line number Diff line change @@ -1212,6 +1212,10 @@ class CXXRecordDecl : public RecordDecl {
1212
1212
// / if this is a closure type.
1213
1213
CXXMethodDecl *getLambdaCallOperator () const ;
1214
1214
1215
+ // / Retrieve the dependent lambda call operator of the closure type
1216
+ // / if this is a templated closure type.
1217
+ FunctionTemplateDecl *getDependentLambdaCallOperator () const ;
1218
+
1215
1219
// / Retrieve the lambda static invoker, the address of which
1216
1220
// / is returned by the conversion operator, and the body of which
1217
1221
// / is forwarded to the lambda call operator.
Original file line number Diff line number Diff line change @@ -1902,6 +1902,10 @@ class LambdaExpr final : public Expr,
1902
1902
// / lambda expression.
1903
1903
CXXMethodDecl *getCallOperator () const ;
1904
1904
1905
+ // / Retrieve the function template call operator associated with this
1906
+ // / lambda expression.
1907
+ FunctionTemplateDecl *getDependentCallOperator () const ;
1908
+
1905
1909
// / If this is a generic lambda expression, retrieve the template
1906
1910
// / parameter list associated with it, or else return null.
1907
1911
TemplateParameterList *getTemplateParameterList () const ;
Original file line number Diff line number Diff line change @@ -1369,17 +1369,25 @@ static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) {
1369
1369
}
1370
1370
#endif
1371
1371
1372
- CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator () const {
1373
- if (!isLambda ()) return nullptr ;
1372
+ NamedDecl* getLambdaCallOperatorHelper ( const CXXRecordDecl &RD) {
1373
+ if (!RD. isLambda ()) return nullptr ;
1374
1374
DeclarationName Name =
1375
- getASTContext ().DeclarationNames .getCXXOperatorName (OO_Call);
1376
- DeclContext::lookup_result Calls = lookup (Name);
1375
+ RD. getASTContext ().DeclarationNames .getCXXOperatorName (OO_Call);
1376
+ DeclContext::lookup_result Calls = RD. lookup (Name);
1377
1377
1378
1378
assert (!Calls.empty () && " Missing lambda call operator!" );
1379
1379
assert (allLookupResultsAreTheSame (Calls) &&
1380
1380
" More than one lambda call operator!" );
1381
+ return Calls.front ();
1382
+ }
1383
+
1384
+ FunctionTemplateDecl* CXXRecordDecl::getDependentLambdaCallOperator () const {
1385
+ NamedDecl *CallOp = getLambdaCallOperatorHelper (*this );
1386
+ return dyn_cast<FunctionTemplateDecl>(CallOp);
1387
+ }
1381
1388
1382
- NamedDecl *CallOp = Calls.front ();
1389
+ CXXMethodDecl *CXXRecordDecl::getLambdaCallOperator () const {
1390
+ NamedDecl *CallOp = getLambdaCallOperatorHelper (*this );
1383
1391
if (const auto *CallOpTmpl = dyn_cast<FunctionTemplateDecl>(CallOp))
1384
1392
return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl ());
1385
1393
Original file line number Diff line number Diff line change @@ -1205,6 +1205,11 @@ CXXMethodDecl *LambdaExpr::getCallOperator() const {
1205
1205
return Record->getLambdaCallOperator ();
1206
1206
}
1207
1207
1208
+ FunctionTemplateDecl *LambdaExpr::getDependentCallOperator () const {
1209
+ CXXRecordDecl *Record = getLambdaClass ();
1210
+ return Record->getDependentLambdaCallOperator ();
1211
+ }
1212
+
1208
1213
TemplateParameterList *LambdaExpr::getTemplateParameterList () const {
1209
1214
CXXRecordDecl *Record = getLambdaClass ();
1210
1215
return Record->getGenericLambdaTemplateParameterList ();
Original file line number Diff line number Diff line change @@ -80,7 +80,10 @@ class CGBuilder : public StmtVisitor<CGBuilder> {
80
80
}
81
81
82
82
void VisitLambdaExpr (LambdaExpr *LE) {
83
- if (CXXMethodDecl *MD = LE->getCallOperator ())
83
+ if (FunctionTemplateDecl *FTD = LE->getDependentCallOperator ())
84
+ for (FunctionDecl *FD : FTD->specializations ())
85
+ G->VisitFunctionDecl (FD);
86
+ else if (CXXMethodDecl *MD = LE->getCallOperator ())
84
87
G->VisitFunctionDecl (MD);
85
88
}
86
89
Original file line number Diff line number Diff line change 1
- // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCallGraph %s -fblocks 2>&1 | FileCheck %s
1
+ // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCallGraph %s -fblocks -std=c++14 2>&1 | FileCheck %s
2
2
3
3
int get5 () {
4
4
return 5 ;
@@ -68,8 +68,25 @@ void templUser() {
68
68
}
69
69
}
70
70
71
+ namespace Lambdas {
72
+ void Callee (){}
73
+
74
+ void f1 () {
75
+ [](int i) {
76
+ Callee ();
77
+ }(1 );
78
+ [](auto i) {
79
+ Callee ();
80
+ }(1 );
81
+ }
82
+ }
83
+
71
84
// CHECK:--- Call graph Dump ---
72
- // 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 $}}
85
+ // 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\(\) $}}
86
+ // CHECK-NEXT: {{Function: Lambdas::f1 calls: Lambdas::f1\(\)::\(anonymous class\)::operator\(\) Lambdas::f1\(\)::\(anonymous class\)::operator\(\) $}}
87
+ // CHECK-NEXT: {{Function: Lambdas::f1\(\)::\(anonymous class\)::operator\(\) calls: Lambdas::Callee $}}
88
+ // CHECK-NEXT: {{Function: Lambdas::f1\(\)::\(anonymous class\)::operator\(\) calls: Lambdas::Callee $}}
89
+ // CHECK-NEXT: {{Function: Lambdas::Callee calls: $}}
73
90
// CHECK-NEXT: {{Function: SomeNS::templUser calls: SomeNS::templ SomeNS::templ $}}
74
91
// CHECK-NEXT: {{Function: SomeNS::templ calls: eee $}}
75
92
// CHECK-NEXT: {{Function: SomeNS::templ calls: ccc $}}
You can’t perform that action at this time.
0 commit comments