This is an archive of the discontinued LLVM Phabricator instance.

[Sema] Fix an assert-on-invalid by avoiding function template specialisation deduction for invalid functions with fabricated template arguments
ClosedPublic

Authored by arphaman on Aug 31 2017, 9:34 AM.

Details

Summary

This patch fixes an an assertion that previously occurred for the following sample:

template <typename InputT, typename OutputT>
struct SourceSelectionRequirement {

  template<typename T>
  OutputT evaluateSelectionRequirement(InputT &&Value) {
  }
};

template <typename InputT, typename OutputT>
OutputT SourceSelectionRequirement<InputT, OutputT>::evaluateSelectionRequirement<void>(InputT &&Value) {
    return Value;
}

Clang asserted when it was trying to deduce the function template specialisation for evaluateSelectionRequirement, because it was trying to do deduction with the template specialisation <void> and template <typename InputT, typename OutputT> which have different template depths.

I initially fixed the issue by setting the right depth, during the deduction, but wasn't happy with the results (we produced two errors, the second one complained about failed deduction). Thus I changed my approach to the one that's presented in this patch - we can detect if the template parameters are fabricated and then avoid the deduction. This approach avoids the second error while fixing the assertion. It also fixed a redundant error FIXME in SemaTemplate/explicit-specialization-member.cpp (Basically removed a redundant deduction error).

Thanks for taking a look

Diff Detail

Repository
rL LLVM

Event Timeline

arphaman created this revision.Aug 31 2017, 9:34 AM
arphaman edited the summary of this revision. (Show Details)
vsapsai edited edge metadata.Sep 12 2017, 5:59 PM

Does your fix work for deeper nesting too (e.g. template in template in template)? Looks like it should, just want to confirm.

Are there other places where you need to avoid calling DeduceTemplateArguments due to templates depth mismatch? CheckDependentFunctionTemplateSpecialization should be OK as it's not deducing template arguments. But I'm not sure about CheckMemberSpecialization. It doesn't call DeduceTemplateArguments directly but I haven't dug deep enough to confirm it's not performing deduction indirectly.

lib/Sema/SemaDecl.cpp
8307–8308 ↗(On Diff #113418)

Checking if angle location is invalid looks suspicious. It can be my lack of knowledge but I expect various locations not to convey sema information.

8880–8881 ↗(On Diff #113418)

Will something more general like

!NewFD->isInvalidDecl() && CheckFunctionTemplateSpecialization(...)

work here? Because if matching template parameters to scope specifier fails, NewFD is marked as invalid decl and seems like we can use that.

arphaman marked an inline comment as done.Oct 23 2017, 4:29 PM

Does your fix work for deeper nesting too (e.g. template in template in template)? Looks like it should, just want to confirm.

Yes.

Are there other places where you need to avoid calling DeduceTemplateArguments due to templates depth mismatch? CheckDependentFunctionTemplateSpecialization should be OK as it's not deducing template arguments. But I'm not sure about CheckMemberSpecialization. It doesn't call DeduceTemplateArguments directly but I haven't dug deep enough to confirm it's not performing deduction indirectly.

The problem only seems to happen when the TPL is fabricated. I didn't see other potential places where such an issue might happen.

lib/Sema/SemaDecl.cpp
8880–8881 ↗(On Diff #113418)

Yeah, good idea.

arphaman updated this revision to Diff 119967.Oct 23 2017, 4:29 PM

Use just the isInvalidDecl check.

vsapsai accepted this revision.Oct 26 2017, 10:29 AM

Looks good to me.

This revision is now accepted and ready to land.Oct 26 2017, 10:29 AM
This revision was automatically updated to reflect the committed changes.