Skip to content

Commit b8fda81

Browse files
committed
[FOLD] Fix arrow operator for expressions with non-pointer type that is the current instantiation
1 parent 99d48cf commit b8fda81

File tree

2 files changed

+104
-34
lines changed

2 files changed

+104
-34
lines changed

clang/lib/Sema/SemaExprMember.cpp

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,12 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
991991
bool SuppressQualifierCheck,
992992
ActOnMemberAccessExtraArgs *ExtraArgs) {
993993
assert(!SS.isInvalid() && "nested-name-specifier cannot be invalid");
994-
if (R.wasNotFoundInCurrentInstantiation())
994+
// If the member wasn't found in the current instantiation, or if the
995+
// arrow operator was used with a dependent non-pointer object expression,
996+
// build a CXXDependentScopeMemberExpr.
997+
if (R.wasNotFoundInCurrentInstantiation() ||
998+
(IsArrow && !BaseExprType->isPointerType() &&
999+
BaseExprType->isDependentType()))
9951000
return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS,
9961001
TemplateKWLoc, FirstQualifierInScope,
9971002
R.getLookupNameInfo(), TemplateArgs);
@@ -1036,41 +1041,39 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
10361041
<< isa<CXXDestructorDecl>(FD);
10371042

10381043
if (R.empty()) {
1039-
// Rederive where we looked up.
1040-
DeclContext *DC =
1041-
(SS.isSet() ? computeDeclContext(SS) : computeDeclContext(BaseType));
1042-
if (ExtraArgs) {
1043-
ExprResult RetryExpr;
1044-
if (!IsArrow && BaseExpr && !BaseExpr->isTypeDependent()) {
1045-
SFINAETrap Trap(*this, true);
1046-
ParsedType ObjectType;
1047-
bool MayBePseudoDestructor = false;
1048-
RetryExpr = ActOnStartCXXMemberReference(getCurScope(), BaseExpr,
1049-
OpLoc, tok::arrow, ObjectType,
1050-
MayBePseudoDestructor);
1051-
if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) {
1052-
CXXScopeSpec TempSS(SS);
1053-
RetryExpr = ActOnMemberAccessExpr(
1054-
ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS,
1055-
TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl);
1056-
}
1057-
if (Trap.hasErrorOccurred())
1058-
RetryExpr = ExprError();
1059-
}
1060-
if (RetryExpr.isUsable()) {
1061-
Diag(OpLoc, diag::err_no_member_overloaded_arrow)
1062-
<< MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->");
1063-
return RetryExpr;
1044+
ExprResult RetryExpr = ExprError();
1045+
if (ExtraArgs && !IsArrow && BaseExpr && !BaseExpr->isTypeDependent()) {
1046+
SFINAETrap Trap(*this, true);
1047+
ParsedType ObjectType;
1048+
bool MayBePseudoDestructor = false;
1049+
RetryExpr = ActOnStartCXXMemberReference(getCurScope(), BaseExpr, OpLoc,
1050+
tok::arrow, ObjectType,
1051+
MayBePseudoDestructor);
1052+
if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) {
1053+
CXXScopeSpec TempSS(SS);
1054+
RetryExpr = ActOnMemberAccessExpr(
1055+
ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS,
1056+
TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl);
10641057
}
1058+
if (Trap.hasErrorOccurred())
1059+
RetryExpr = ExprError();
10651060
}
10661061

1062+
// Rederive where we looked up.
1063+
DeclContext *DC =
1064+
(SS.isSet() ? computeDeclContext(SS) : computeDeclContext(BaseType));
10671065
assert(DC);
1068-
Diag(R.getNameLoc(), diag::err_no_member)
1069-
<< MemberName << DC
1070-
<< (SS.isSet()
1071-
? SS.getRange()
1072-
: (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()));
1073-
return ExprError();
1066+
1067+
if (RetryExpr.isUsable())
1068+
Diag(OpLoc, diag::err_no_member_overloaded_arrow)
1069+
<< MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->");
1070+
else
1071+
Diag(R.getNameLoc(), diag::err_no_member)
1072+
<< MemberName << DC
1073+
<< (SS.isSet()
1074+
? SS.getRange()
1075+
: (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()));
1076+
return RetryExpr;
10741077
}
10751078

10761079
// Diagnose lookups that find only declarations from a non-base

clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ namespace N2 {
439439
a->B::C::x;
440440
}
441441
};
442-
}
442+
} // namespace N2
443443

444444
namespace N3 {
445445
struct A { };
@@ -453,4 +453,71 @@ namespace N3 {
453453
this->A::operator=(*this);
454454
}
455455
};
456-
}
456+
} // namespace N3
457+
458+
namespace N4 {
459+
template<typename T>
460+
struct A {
461+
void not_instantiated(A a, A<T> b, T c) {
462+
a->x;
463+
b->x;
464+
c->x;
465+
}
466+
467+
void instantiated(A a, A<T> b, T c) {
468+
a->x; // expected-error {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
469+
// expected-error@-1 {{no member named 'x' in 'N4::A<int>'}}
470+
b->x; // expected-error {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
471+
// expected-error@-1 {{no member named 'x' in 'N4::A<int>'}}
472+
c->x; // expected-error {{member reference type 'int' is not a pointer}}
473+
}
474+
};
475+
476+
template void A<int>::instantiated(A<int>, A<int>, int); // expected-note {{in instantiation of}}
477+
478+
struct B {
479+
int x;
480+
481+
void f();
482+
};
483+
484+
template<typename T>
485+
struct C {
486+
B *operator->();
487+
488+
void not_instantiated(C a, C<T> b, T c) {
489+
a->x;
490+
b->x;
491+
c->x;
492+
}
493+
494+
void instantiated(C a, C<T> b, T c) {
495+
a->x;
496+
b->x;
497+
c->x; // expected-error {{member reference type 'int' is not a pointer}}
498+
}
499+
};
500+
501+
template void C<int>::instantiated(C, C, int); // expected-note {{in instantiation of}}
502+
503+
template<typename T>
504+
struct D {
505+
T *operator->();
506+
507+
void not_instantiated(D a) {
508+
a->x;
509+
a->y;
510+
a->f();
511+
a->g();
512+
}
513+
514+
void instantiated(D a) {
515+
a->x;
516+
a->y; // expected-error {{no member named 'y' in 'N4::B'}}
517+
a->f();
518+
a->g(); // expected-error {{no member named 'g' in 'N4::B'}}
519+
}
520+
};
521+
522+
template void D<B>::instantiated(D); // expected-note {{in instantiation of}}
523+
} // namespace N4

0 commit comments

Comments
 (0)