@@ -74,6 +74,15 @@ class HeuristicResolverImpl {
7474 // resolves it to a TagDecl in which we can try name lookup.
7575 TagDecl *resolveTypeToTagDecl (const Type *T);
7676
77+ // Helper function for simplifying a type.
78+ // `Type` is the type to simplify.
79+ // `E` is the expression whose type `Type` is, if known. This sometimes
80+ // contains information relevant to the type that's not stored in `Type`
81+ // itself.
82+ // If `UnwrapPointer` is true, exactly only pointer type will be unwrapped
83+ // during simplification, and the operation fails if no pointer type is found.
84+ QualType simplifyType (QualType Type, const Expr *E, bool UnwrapPointer);
85+
7786 // This is a reimplementation of CXXRecordDecl::lookupDependentName()
7887 // so that the implementation can call into other HeuristicResolver helpers.
7988 // FIXME: Once HeuristicResolver is upstreamed to the clang libraries
@@ -198,6 +207,57 @@ QualType HeuristicResolverImpl::getPointeeType(QualType T) {
198207 return FirstArg.getAsType ();
199208}
200209
210+ QualType HeuristicResolverImpl::simplifyType (QualType Type, const Expr *E,
211+ bool UnwrapPointer) {
212+ bool DidUnwrapPointer = false ;
213+ auto SimplifyOneStep = [&](QualType T) {
214+ if (UnwrapPointer) {
215+ if (QualType Pointee = getPointeeType (T); !Pointee.isNull ()) {
216+ DidUnwrapPointer = true ;
217+ return Pointee;
218+ }
219+ }
220+ if (const auto *RT = T->getAs <ReferenceType>()) {
221+ // Does not count as "unwrap pointer".
222+ return RT->getPointeeType ();
223+ }
224+ if (const auto *BT = T->getAs <BuiltinType>()) {
225+ // If BaseType is the type of a dependent expression, it's just
226+ // represented as BuiltinType::Dependent which gives us no information. We
227+ // can get further by analyzing the dependent expression.
228+ if (E && BT->getKind () == BuiltinType::Dependent) {
229+ return resolveExprToType (E);
230+ }
231+ }
232+ if (const auto *AT = T->getContainedAutoType ()) {
233+ // If T contains a dependent `auto` type, deduction will not have
234+ // been performed on it yet. In simple cases (e.g. `auto` variable with
235+ // initializer), get the approximate type that would result from
236+ // deduction.
237+ // FIXME: A more accurate implementation would propagate things like the
238+ // `const` in `const auto`.
239+ if (E && AT->isUndeducedAutoType ()) {
240+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
241+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl ())) {
242+ if (VD->hasInit ())
243+ return resolveExprToType (VD->getInit ());
244+ }
245+ }
246+ }
247+ }
248+ return T;
249+ };
250+ while (!Type.isNull ()) {
251+ QualType New = SimplifyOneStep (Type);
252+ if (New == Type)
253+ break ;
254+ Type = New;
255+ }
256+ if (UnwrapPointer && !DidUnwrapPointer)
257+ return QualType ();
258+ return Type;
259+ }
260+
201261std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr (
202262 const CXXDependentScopeMemberExpr *ME) {
203263 // If the expression has a qualifier, try resolving the member inside the
@@ -230,36 +290,7 @@ std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
230290 // Try resolving the member inside the expression's base type.
231291 Expr *Base = ME->isImplicitAccess () ? nullptr : ME->getBase ();
232292 QualType BaseType = ME->getBaseType ();
233- if (ME->isArrow ()) {
234- BaseType = getPointeeType (BaseType);
235- if (BaseType.isNull ())
236- return {};
237- }
238- if (const auto *BT = BaseType->getAs <BuiltinType>()) {
239- // If BaseType is the type of a dependent expression, it's just
240- // represented as BuiltinType::Dependent which gives us no information. We
241- // can get further by analyzing the dependent expression.
242- if (Base && BT->getKind () == BuiltinType::Dependent) {
243- BaseType = resolveExprToType (Base);
244- if (BaseType.isNull ())
245- return {};
246- }
247- }
248- if (const auto *AT = BaseType->getContainedAutoType ()) {
249- // If BaseType contains a dependent `auto` type, deduction will not have
250- // been performed on it yet. In simple cases (e.g. `auto` variable with
251- // initializer), get the approximate type that would result from deduction.
252- // FIXME: A more accurate implementation would propagate things like the
253- // `const` in `const auto`.
254- if (AT->isUndeducedAutoType ()) {
255- if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
256- if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl ())) {
257- if (VD->hasInit ())
258- BaseType = resolveExprToType (VD->getInit ());
259- }
260- }
261- }
262- }
293+ BaseType = simplifyType (BaseType, Base, ME->isArrow ());
263294 return resolveDependentMember (BaseType, ME->getMember (), NoFilter);
264295}
265296
0 commit comments