[cfe-dev] PR27015 (variable template initialized with a generic lambda expresssion)
Akira Hatanaka via cfe-dev
cfe-dev at lists.llvm.org
Thu Apr 14 11:57:03 PDT 2016
Thanks, I was about to send an update.
I made a few changes to make sure the lambda class gets the right parent
DeclContext, which I think is the translation unit (type
Decl::TranslationUnit) in my example. Currently, when the variable template
is instantiated (fn<char>), function "func" is passed as the DeclContext to
CXXRecordDecl::CreateLambda, which is causing
CXXRecordDecl::isDependentType() to return true.
With this change, clang doesn't crash anymore.
Does it sound like I'm headed in the right direction? I can send my WIP
patch for review to cfe-commits if that makes it easier to discuss my
current approach.
On Thu, Apr 14, 2016 at 11:52 AM, Richard Smith <richard at metafoo.co.uk>
wrote:
> On Wed, Apr 13, 2016 at 3:19 PM, Akira Hatanaka <ahatanak at gmail.com>
> wrote:
>
>> On Tue, Apr 12, 2016 at 5:34 PM, Richard Smith <richard at metafoo.co.uk>
>> wrote:
>>
>>> On Tue, Apr 12, 2016 at 5:22 PM, Akira Hatanaka via cfe-dev <
>>> cfe-dev at lists.llvm.org> wrote:
>>>
>>>> I was wondering whether someone could answer a few questions about
>>>> variable templates. I'm trying to come up with a patch that fixes the crash
>>>> described in PR27015.
>>>>
>>>> https://llvm.org/bugs/show_bug.cgi?id=27015
>>>>
>>>> The crash happens when clang compiles a code that has a variable
>>>> template initialized with a generic lambda. For example,
>>>>
>>>> $ cat test1.c
>>>>
>>>> template<typename T> auto fn = [](auto a) { return a + T(1); };
>>>>
>>>> template <typename X>
>>>> int func() {
>>>> X a = 0x61;
>>>> fn<char>(a);
>>>> return 0;
>>>> }
>>>>
>>>> int main() {
>>>> func<int>();
>>>> }
>>>>
>>>> First question, is this legal c++14 code? I didn't find anything that
>>>> suggests it isn't legal, but I haven't found any code that uses variable
>>>> templates like this either other than the provided test case.
>>>>
>>>
>>> Yes, sadly, this is valid C++14 code.
>>>
>>>
>>>> Second question, what would the closure type look like in this case? My
>>>> understanding is that the closure type for generic lambda without template
>>>> parameters looks like this:
>>>>
>>>> class Class {
>>>> template<typename AT>
>>>> AT operator()(AT a) { ... }
>>>> ...
>>>> };
>>>>
>>>> With template parameter, would it look like this?
>>>>
>>>> template<typename T>
>>>> class Class {
>>>> template<typename AT>
>>>> AT operator()(AT a) { return a + T(1); }
>>>> ...
>>>> };
>>>>
>>>
>>> No. Each instantiation of 'fn' gets its own closure type. The closure
>>> type from the template itself should be treated as being in a dependent
>>> context, even though there is no dependent DeclContext to contain it.
>>>
>>
>> After the template declaration for func is parsed,
>> VarTemplateSpecialization for fn looks like this in the AST:
>>
>> `-*VarTemplateSpecializationDecl* 0x10d001a00 <line:23:22, col:62> col:27
>> referenced* fn* 'auto' cinit
>>
>> I think this is not correct as the type of the
>> VarTemplateSpecializationDecl at this point should be the closure type for
>> fn<char> instead of 'auto'. Is that correct?
>>
>
> Yes.
>
>
>> I'm still trying to understand how instantiation of variable templates
>> works, but it seems like one of the problem is that
>> Sema::createLambdaClosureType is returning a type that is dependent
>> (CXXRecordDecl::isDependentType() returns true), which looks like is
>> preventing the type of VarTemplateSpecialization from being replaced.
>>
>
> The closure type created in the instantiation should not be considered
> dependent. If it is, that's a bug.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160414/bb60a55c/attachment.html>
More information about the cfe-dev
mailing list