Skip to content

Clang crash on valid code since #87933 #92414

Closed
@yronglin

Description

@yronglin
namespace std {
template <class T> class initializer_list {};
}

template <typename T, int> class C {
public:
  C(std::initializer_list<T>);
};

template <typename T> using Ptr =__remove_pointer(T) *;
template <typename T>  C(T) ->  C<Ptr<T>, sizeof(T)>;

class A {
public:
  template <typename T1, typename T2>
  T1 *some_func(T2 &&);
};

struct B : A {
  int *ar = some_func<int>(C{some_func<int>(0)});
  B() {}
};

I've debug in local. The crash issue caused by initializer rebuild failed in

SFINAETrap Trap(*this);
runWithSufficientStackSpace(Loc, [&] {
Res = Immediate.TransformInitializer(Field->getInClassInitializer(),
/*CXXDirectInit=*/false);
});
, if remove Line 5717 SFINAETrap Trap(*this);, we can got diagnostics like the following:

./main.cpp:23:28: error: no viable constructor or deduction guide for deduction of template arguments of 'C'
   23 |   int *ar = some_func<int>(C{some_func<int>(0)});
      |                            ^
./main.cpp:6:34: note: candidate template ignored: couldn't infer template argument 'T'
    6 | template <typename T, int> class C {
      |                                  ^
./main.cpp:8:3: note: candidate template ignored: couldn't infer template argument ''
    8 |   C(std::initializer_list<T>);
      |   ^
./main.cpp:12:24: note: candidate template ignored: couldn't infer template argument 'T'
   12 | template <typename T>  C(T) ->  C<Ptr<T>, sizeof(T)>;
      |                        ^
1 error generated.

But why does the check pass during Parse phase but fails when we rebuilding CXXDefaultInitExpr? Through tracing, I found that the root cause was the parameter bool ListInitialization that passed to RebuildCXXTemporaryObjectExpr(fall throuth to Sema::BuildCXXTypeConstructExpr). During parsing, ListInitialization was true, but it became false during rebuilding, it's cause InitializationKind to become DirectInit instead of DirectListInit. Finally, causing Sema::DeduceTemplateSpecializationFromInitializer fail.

// FIXME: We should just pass E->isListInitialization(), but we're not
// prepared to handle list-initialization without a child InitListExpr.
SourceLocation LParenLoc = T->getTypeLoc().getEndLoc();
return getDerived().RebuildCXXTemporaryObjectExpr(
T, LParenLoc, Args, E->getEndLoc(),
/*ListInitialization=*/LParenLoc.isInvalid());

Therefore, I think the key to the problem is to fix TreeTransform.h:14116's FIXME. As the comments in TreeTransform.h:14116 said, we should pass E->isListInitialization(), because E is actually list initialization, I have tried this modification, but it will cause 3 lit failures. We have not try to rebuild the CXXDefaultInitExpr before this PR, so it's works fine before.

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"crash-on-valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions