From: Adam Czachorowski Date: Wed, 16 Mar 2022 13:27:27 +0000 (+0100) Subject: [clang] Do not crash on arrow operator on dependent type. X-Git-Tag: upstream/15.0.7~12324 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7e459126185f4d5115e6e2166a866aba1369d024;p=platform%2Fupstream%2Fllvm.git [clang] Do not crash on arrow operator on dependent type. There seems to be more than one way to get to that state. I included to example cases in the test, both were noticed recently. There is room for improvement, for example by creating RecoveryExpr in place of the bad initializer, but for now let's stop the crashes. Differential Revision: https://reviews.llvm.org/D121824 --- diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index fb830ef..1ee457b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -14757,6 +14757,10 @@ TreeTransform::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, return getSema().CreateBuiltinArraySubscriptExpr( First, Callee->getBeginLoc(), Second, OpLoc); } else if (Op == OO_Arrow) { + // It is possible that the type refers to a RecoveryExpr created earlier + // in the tree transformation. + 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 index 3e32a6b..c6d2a99 100644 --- a/clang/test/SemaCXX/arrow-operator.cpp +++ b/clang/test/SemaCXX/arrow-operator.cpp @@ -65,3 +65,51 @@ void test() { } } // 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