diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 328641ed94881..f831e1244970d 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5680,8 +5680,15 @@ QualType getApproximateType(const Expr *E) { } } if (const auto *UO = llvm::dyn_cast(E)) { - if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) - return UO->getSubExpr()->getType()->getPointeeType(); + if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) { + // We recurse into the subexpression because it could be of dependent + // type. + if (auto Pointee = getApproximateType(UO->getSubExpr())->getPointeeType(); + !Pointee.isNull()) + return Pointee; + // Our caller expects a non-null result, even though the SubType is + // supposed to have a pointee. Fall through to Unresolved anyway. + } } return Unresolved; } diff --git a/clang/test/CodeCompletion/member-access.cpp b/clang/test/CodeCompletion/member-access.cpp index 9f8c21c0bca6d..912f269db6c1a 100644 --- a/clang/test/CodeCompletion/member-access.cpp +++ b/clang/test/CodeCompletion/member-access.cpp @@ -367,4 +367,20 @@ class A { // CHECK-DEREF-THIS: [#void#]function() } }; + +template +struct RepeatedField { + void Add(); +}; + +template +RepeatedField* MutableRepeatedField() {} + +template +void Foo() { + auto& C = *MutableRepeatedField(); + C. +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:382:5 %s -o - | FileCheck -check-prefix=CHECK-DEREF-DEPENDENT %s +// CHECK-DEREF-DEPENDENT: [#void#]Add() }