Open Ukilele opened 11 months ago
I quickly checked that at least for the operators ,
(comma), +
(plus) and &
(bit and) the behavior is the same.
Hello @Ukilele,
thanks for reporting this issue!
I agree with your quote from the standard. My issue is that at the point I render something like 4, 5, 6
, I don't know whether this results from a fold-expression or a user's code. Looking at the AST using Compiler Explorer compiler-explorer.com/z/MYWb9T3xq shows in line 77 the BinaryOperator
. It does not say anything about a fold expression. I thought I could use NonTypeTemplateParmDecl
in line 80, but this also doesn't know how the pack is used later. I would be happy if you or anybody else knows how to get this information.
C++ Insights introduces parens in some cases, for example https://github.com/andreasfertig/cppinsights/blob/50b962d6bb6d96c567a5b0870c3c828405b40d14/CodeGenerator.cpp#L720
I wonder how your test looked for +
because my example works:
template<typename... Ts>
constexpr auto avg(const Ts&... vals)
{
return (vals + ...) / sizeof...(vals);
}
static_assert(avg(2, 3, 4) == 3);
This translates to
template<>
inline constexpr unsigned long avg<int, int, int>(const int & __vals0, const int & __vals1, const int & __vals2)
{
return (static_cast<unsigned long>(__vals0 + (__vals1 + __vals2))) / 3;
}
As much as it bugs me, this issue will remain unfixed for now.
Andreas
Hello @andreasfertig,
1.) You're welcome. Thanks so much for this helpful tool! :rocket:
2.) Yes, it seems that once you have a concrete FunctionDecl
(even if it is the result of instantiating a FunctionTemplateDecl
),
all information about the contained fold expression is lost. Maybe via getDescribedFunctionTemplate you can get from the FunctionDecl
to its FunctionTemplateDecl
, which does contain the CXXFoldExpr
we need. Still, it sounds like this issue is quite tedious to resolve.
3.) Thanks for pointing at const bool needLHSParens{isa<BinaryOperator>(stmt->getLHS()->IgnoreImpCasts())};
, I only just now realized that cppinsights transforms 1 + 2 + 3
into (1 + 2) + 3
.
I guess this explains the parentheses that cppinsights generates in the instantiations of my TestC
and TestD
functions.
4.) My test for +
looked the way, that I took the original code I mentioned in the issue and replaced each occurrence of the fold-operator ,
by +
.
Best regards, Kilian
Hello @Ukilele,
re 2.)
Thanks for that idea. Sadly, even with getDescribedFunctionTemplate
, the transformation remains guesswork, and there is at least one scenario where it fails.
The results for TestA
and TestC
are different. In TestC
, I can guess, with the help of storing state, that a SubstNonTypeTemplateParmExpr
comes from a NonTypeTemplateParmDecl
, which shares the same DeclRefExpr
as used prior for defining the CXXFoldExpr
in the primary template. I'm not even sure in how many cases this guessing fails, but at least for this case, it would work.
Everything is different for TestA
. Here, we are looking at a ParmVarDecl
in the instantiation. As far as I can tell, this decl shares nothing with the decl in the CXXFoldExpr
.
With the guessing, the effort, and the situation that it would still not work in all cases, I do not plan to do anything here. However. as always, PRs are welcome.
Andreas
Hello Andreas, there might be an issue with the transformation of fold expressions. Following code:
generates following outcome:
In all four of my Test-functions, the issue is, that the fold expression does not contain the right amount of parentheses around them. According to https://eel.is/c++draft/temp.variadic#11, a unary left fold of the form
(... , Is)
should expand to( ((Is1, Is2) , ...) , IsN )
. But this is not, what cppinsights generates. I added four Test-functions.TestA
andTestB
test the behavior with a function parameter pack, whileTestC
andTestD
test the behavior with a template parameter pack.TestA
andTestC
use the fold expression within a function call, whileTestC
andTestD
use the fold expression in an initialization. I did not check the behavior for the other kind of fold expressions (e.g. binary right fold) and other kind of operators, but I guess the behavior will be similar?Cheers!