From 7e459126185f4d5115e6e2166a866aba1369d024 Mon Sep 17 00:00:00 2001 From: Adam Czachorowski Date: Wed, 16 Mar 2022 14:27:27 +0100 Subject: [PATCH] [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 --- clang/lib/Sema/TreeTransform.h | 4 +++ clang/test/SemaCXX/arrow-operator.cpp | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) 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 -- 2.7.4