Bug 561128 - [C++17] Semantic support for constexpr lambda expressions
Summary: [C++17] Semantic support for constexpr lambda expressions
Status: NEW
Alias: None
Product: CDT
Classification: Tools
Component: cdt-parser (show other bugs)
Version: Next   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact: Jonah Graham CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 519734
  Show dependency tree
 
Reported: 2020-03-15 11:15 EDT by Marco Stornelli CLA
Modified: 2020-11-21 09:05 EST (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marco Stornelli CLA 2020-03-15 11:15:07 EDT
We need to add semantic support for constexpr lambda expressions in order to have expression evaluation.
Comment 2 Marco Stornelli CLA 2020-03-16 04:07:19 EDT
At the moment, with the previous commit, basic semantic support has been added to CDT. However the support isn't complete yet, since we need to model lambda captures as closure fields in order to have a complete "static" evaluation of the expression. Example of test cases to be addressed:

  constexpr int f() {
    return ([]() constexpr -> int {return 58;})();
  }
  constexpr int x = f();


  constexpr int f() {
    int a = 58;
    return ([=]() constexpr -> int {return a;})();
  }
  constexpr int x = f();


  constexpr int f() {
    int b = 57;
    return ([a = b + 1]() constexpr -> int {return a;})();
  }
  constexpr int x = f();
Comment 3 Nathan Ridge CLA 2020-03-16 11:05:12 EDT
(In reply to Marco Stornelli from comment #2)
>   constexpr int f() {
>     return ([]() constexpr -> int {return 58;})();
>   }
>   constexpr int x = f();

Note, this test case doesn't involve a capture, so if it's failing there is something else going on.
Comment 4 Marco Stornelli CLA 2020-03-16 11:07:45 EDT
Oops, my fault, yes, you are right, I copied pasted the test cases here just for reference and I didn't notice it.
Comment 5 Marco Stornelli CLA 2020-03-17 03:43:13 EDT
@Nathan I was looking at that test and it's failing. The problem is inside the method "ICPPExecution computeFunctionBodyExecution(IASTNode def)" of CPPFunction. When this method is called, it calls getFunctionDefinition(). In this particular case it finds f() again and here we have a loop until the code hit the max steps threshold. Basically it seems to me that getFunctionDefinition() should take into accounts lambda expressions too or we need to perform a basic check before like that:

public static ICPPExecution computeFunctionBodyExecution(IASTNode def) {

if (def.getParent() instanceof ICPPASTLambdaExpression) { <-----additional check
.........
}

ICPPASTFunctionDefinition fnDef = getFunctionDefinition(def);
if (fnDef == null) {
.....
}
.......
}

Let me know what you think about that.
Comment 6 Nathan Ridge CLA 2020-03-17 14:01:08 EDT
We can just inline the body of getFunctionDefintion() into computeFunctionBodyExection(), and modify the loop to check for a lambda expression as well.
Comment 7 Marco Stornelli CLA 2020-03-18 04:09:06 EDT
I did the change but the test with the index strategy if the function is declared in the header file doesn't work. I tried to follow the code and I guess there's something wrong "around" PDOMCPPFunction but I didn't understand where to look into the index code.
Comment 8 Nathan Ridge CLA 2020-03-18 09:49:41 EDT
Yes, I am not surprised that index support requires extra work.

Please feel free to land the test case with all the code being in the main file (no header). I can try to look into the index stuff as time permits (it may take a few weeks).
Comment 9 Eclipse Genie CLA 2020-03-18 11:20:33 EDT
New Gerrit change created: https://git.eclipse.org/r/159642
Comment 11 Marco Stornelli CLA 2020-03-20 15:12:30 EDT
Just a summary. We need two additional steps in this moment: model captures as fields (test2 and test3) and fix the index when the constexpr is defined in header file (test1).

test1:
header file
constexpr int f() {
    return ([]() constexpr -> int {return 58;})();
  }
cpp file
  constexpr int x = f();

test2:
  constexpr int f() {
    int a = 58;
    return ([=]() constexpr -> int {return a;})();
  }
  constexpr int x = f();

test3:
  constexpr int f() {
    int b = 57;
    return ([a = b + 1]() constexpr -> int {return a;})();
  }
  constexpr int x = f();
Comment 12 Nathan Ridge CLA 2020-03-23 00:53:44 EDT
The index problem occurs because we fail to store the CPPClosureType in the index. It's a local binding (its owner is a function), and in PDOMCPPLinkage.adaptOrAddParent() we have some logic that limits which local bindings are stored in the index. We can relax this to include closure types (in fact, all types).
Comment 13 Eclipse Genie CLA 2020-03-23 00:54:30 EDT
New Gerrit change created: https://git.eclipse.org/r/159867
Comment 14 Nathan Ridge CLA 2020-03-23 00:55:23 EDT
For modelling captures, the place to start looking is CPPASTLambdaExpression.getEvaluation(). Where we currently pass IntegralValue.UNKNOWN, we will want to pass a CompositeValue representing an object of the closure's type.
Comment 15 Nathan Ridge CLA 2020-03-23 00:56:43 EDT
(In reply to Eclipse Genie from comment #13)
> New Gerrit change created: https://git.eclipse.org/r/159867

This patch fixes the index issue.
Comment 17 Axel Mueller CLA 2020-11-19 12:34:58 EST
Are these patches in CDT 9.11 (Eclipse 2020-09)? 

The following code (from https://docs.microsoft.com/de-de/cpp/cpp/lambda-expressions-constexpr?view=msvc-160) is indicated as an error in the editor:
int y = 32;
auto answer = [y]() constexpr
{
   int x = 10;
   return y + x;
};

If I rewrite the code to have constexpr up-front everything is fine.

int y = 32;
constexpr auto answer = [y]()
{
   int x = 10;
   return y + x;
};
Comment 18 Nathan Ridge CLA 2020-11-20 02:59:37 EST
(In reply to Axel Mueller from comment #17)
> Are these patches in CDT 9.11 (Eclipse 2020-09)? 

The patch required to parse 'constexpr' in a lambda-declarator (which was in bug 560483) is in CDT 10.0. It is not in CDT 9.11.

However, Eclipse 2020-09 should include CDT 10.0.
Comment 19 Axel Mueller CLA 2020-11-20 06:58:37 EST
(In reply to Nathan Ridge from comment #18)
> The patch required to parse 'constexpr' in a lambda-declarator (which was in
> bug 560483) is in CDT 10.0. It is not in CDT 9.11.
> 
> However, Eclipse 2020-09 should include CDT 10.0.
Sorry, I have indeed CDT 10.0 installed (only some features report version 9.11). But unfortunately, the expression in bug 560483 shows an error in the editor
Comment 20 Nathan Ridge CLA 2020-11-20 11:21:38 EST
Which features report version 9.11? A mixture of versions can indicate an incomplete installation or upgrade.

I did just download an unmodified 2020-09 Eclipse C++ package, and the code is parsed successfully.
Comment 21 Axel Mueller CLA 2020-11-21 09:05:40 EST
(In reply to Nathan Ridge from comment #20)
> Which features report version 9.11? A mixture of versions can indicate an
> incomplete installation or upgrade.
> 
> I did just download an unmodified 2020-09 Eclipse C++ package, and the code
> is parsed successfully.
I did run an update and now all features indicate version 10.0.1. The problem with the constexpr is gone. Thanks.