diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -14705,6 +14705,8 @@ return getSema().CreateBuiltinArraySubscriptExpr( First, Callee->getBeginLoc(), Second, OpLoc); } else if (Op == OO_Arrow) { + if (First->getType()->isDependentType()) + return ExprError(); // -> is never a builtin operation. return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc); } else if (Second == nullptr || isPostIncDec) { diff --git a/clang/test/SemaCXX/arrow-operator.cpp b/clang/test/SemaCXX/arrow-operator.cpp --- a/clang/test/SemaCXX/arrow-operator.cpp +++ b/clang/test/SemaCXX/arrow-operator.cpp @@ -65,3 +65,51 @@ } } // namespace arrow_suggest + +namespace no_crash_dependent_type { + +template +struct A { + void call(); + A* operator->(); +}; + +template +void foo() { + // The "requires an initializer" error seems unnecessary. + A& x = blah[7]; // expected-error {{use of undeclared identifier 'blah'}} \ + // expected-error {{requires an initializer}} + // x is dependent. + x->call(); +} + +void test() { + foo(); // expected-note {{requested here}} +} + +} // namespace no_crash_dependent_type + +namespace clangd_issue_1073_no_crash_dependent_type { + +template struct Ptr { + T *operator->(); +}; + +struct Struct { + int len; +}; + +template +struct TemplateStruct { + Ptr val(); // expected-note {{declared here}} +}; + +template +void templateFunc(const TemplateStruct &ts) { + Ptr ptr = ts.val(); // expected-error {{function is not marked const}} + auto foo = ptr->len; +} + +template void templateFunc<0>(const TemplateStruct<0> &); // expected-note {{requested here}} + +} // namespace clangd_issue_1073_no_crash_dependent_type