Skip to content

Commit 5ede7b6

Browse files
authored
Revert "Reapply "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (#104458)"" (#123982)
Reverts #109422
1 parent 1687aa2 commit 5ede7b6

File tree

6 files changed

+38
-58
lines changed

6 files changed

+38
-58
lines changed

clang/include/clang/Sema/Sema.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -10608,8 +10608,9 @@ class Sema final : public SemaBase {
1060810608
/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator->
1060910609
/// (if one exists), where @c Base is an expression of class type and
1061010610
/// @c Member is the name of the member we're trying to find.
10611-
ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
10612-
bool *NoArrowOperatorFound);
10611+
ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
10612+
SourceLocation OpLoc,
10613+
bool *NoArrowOperatorFound = nullptr);
1061310614

1061410615
ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
1061510616
CXXConversionDecl *Method,

clang/lib/Sema/SemaExprCXX.cpp

+17-4
Original file line numberDiff line numberDiff line change
@@ -7999,6 +7999,18 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
79997999

80008000
QualType BaseType = Base->getType();
80018001
MayBePseudoDestructor = false;
8002+
if (BaseType->isDependentType()) {
8003+
// If we have a pointer to a dependent type and are using the -> operator,
8004+
// the object type is the type that the pointer points to. We might still
8005+
// have enough information about that type to do something useful.
8006+
if (OpKind == tok::arrow)
8007+
if (const PointerType *Ptr = BaseType->getAs<PointerType>())
8008+
BaseType = Ptr->getPointeeType();
8009+
8010+
ObjectType = ParsedType::make(BaseType);
8011+
MayBePseudoDestructor = true;
8012+
return Base;
8013+
}
80028014

80038015
// C++ [over.match.oper]p8:
80048016
// [...] When operator->returns, the operator-> is applied to the value
@@ -8013,7 +8025,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80138025
SmallVector<FunctionDecl*, 8> OperatorArrows;
80148026
CTypes.insert(Context.getCanonicalType(BaseType));
80158027

8016-
while (BaseType->getAsRecordDecl()) {
8028+
while (BaseType->isRecordType()) {
80178029
if (OperatorArrows.size() >= getLangOpts().ArrowDepth) {
80188030
Diag(OpLoc, diag::err_operator_arrow_depth_exceeded)
80198031
<< StartingType << getLangOpts().ArrowDepth << Base->getSourceRange();
@@ -8024,7 +8036,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80248036
}
80258037

80268038
Result = BuildOverloadedArrowExpr(
8027-
Base, OpLoc,
8039+
S, Base, OpLoc,
80288040
// When in a template specialization and on the first loop iteration,
80298041
// potentially give the default diagnostic (with the fixit in a
80308042
// separate note) instead of having the error reported back to here
@@ -8088,7 +8100,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80888100
// it's legal for the type to be incomplete if this is a pseudo-destructor
80898101
// call. We'll do more incomplete-type checks later in the lookup process,
80908102
// so just skip this check for ObjC types.
8091-
if (BaseType->isDependentType() || !BaseType->isRecordType()) {
8103+
if (!BaseType->isRecordType()) {
80928104
ObjectType = ParsedType::make(BaseType);
80938105
MayBePseudoDestructor = true;
80948106
return Base;
@@ -8099,7 +8111,8 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80998111
// Unlike the object expression in other contexts, *this is not required to
81008112
// be of complete type for purposes of class member access (5.2.5) outside
81018113
// the member function body.
8102-
if (!isThisOutsideMemberFunctionBody(BaseType) &&
8114+
if (!BaseType->isDependentType() &&
8115+
!isThisOutsideMemberFunctionBody(BaseType) &&
81038116
RequireCompleteType(OpLoc, BaseType,
81048117
diag::err_incomplete_member_access)) {
81058118
return CreateRecoveryExpr(Base->getBeginLoc(), Base->getEndLoc(), {Base});

clang/lib/Sema/SemaExprMember.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1357,7 +1357,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
13571357
BaseType = Ptr->getPointeeType();
13581358
else if (BaseType->isFunctionType())
13591359
goto fail;
1360-
else if (BaseExpr.get()->isTypeDependent())
1360+
else if (BaseType->isDependentType())
13611361
BaseType = S.Context.DependentTy;
13621362
else if (BaseType->isRecordType()) {
13631363
// Recover from arrow accesses to records, e.g.:

clang/lib/Sema/SemaOverload.cpp

+4-14
Original file line numberDiff line numberDiff line change
@@ -15962,9 +15962,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
1596215962
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method);
1596315963
}
1596415964

15965-
ExprResult Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
15965+
ExprResult Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base,
15966+
SourceLocation OpLoc,
1596615967
bool *NoArrowOperatorFound) {
15967-
assert(Base->getType()->getAsRecordDecl() &&
15968+
assert(Base->getType()->isRecordType() &&
1596815969
"left-hand side must have class type");
1596915970

1597015971
if (checkPlaceholderForOverload(*this, Base))
@@ -15987,20 +15988,9 @@ ExprResult Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
1598715988
return ExprError();
1598815989

1598915990
LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
15990-
LookupParsedName(R, /*S=*/nullptr, /*SS=*/nullptr, Base->getType());
15991+
LookupQualifiedName(R, Base->getType()->castAs<RecordType>()->getDecl());
1599115992
R.suppressAccessDiagnostics();
1599215993

15993-
if (Base->getType()->isDependentType() &&
15994-
(!R.empty() || R.wasNotFoundInCurrentInstantiation())) {
15995-
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
15996-
ExprResult Fn = CreateUnresolvedLookupExpr(
15997-
/*NamingClass=*/nullptr, /*NNSLoc=*/NestedNameSpecifierLoc(),
15998-
OpNameInfo, R.asUnresolvedSet(), /*PerformADL=*/false);
15999-
return CXXOperatorCallExpr::Create(Context, OO_Arrow, Fn.get(), Base,
16000-
Context.DependentTy, VK_PRValue, OpLoc,
16001-
CurFPFeatureOverrides());
16002-
}
16003-
1600415994
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
1600515995
Oper != OperEnd; ++Oper) {
1600615996
AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context),

clang/lib/Sema/TreeTransform.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -17282,11 +17282,10 @@ ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(
1728217282
} else if (Op == OO_Arrow) {
1728317283
// It is possible that the type refers to a RecoveryExpr created earlier
1728417284
// in the tree transformation.
17285-
if (First->containsErrors())
17285+
if (First->getType()->isDependentType())
1728617286
return ExprError();
1728717287
// -> is never a builtin operation.
17288-
return getSema().BuildOverloadedArrowExpr(First, OpLoc,
17289-
/*NoArrowOperatorFound=*/nullptr);
17288+
return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc);
1729017289
} else if (Second == nullptr || isPostIncDec) {
1729117290
if (!First->getType()->isOverloadableType() ||
1729217291
(Op == OO_Amp && getSema().isQualifiedMemberAccess(First))) {

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

+11-34
Original file line numberDiff line numberDiff line change
@@ -484,19 +484,16 @@ namespace N4 {
484484
template<typename T>
485485
struct A {
486486
void not_instantiated(A a, A<T> b, T c) {
487-
a->x; // expected-error {{member reference type 'A<T>' is not a pointer; did you mean to use '.'?}}
488-
b->x; // expected-error {{member reference type 'A<T>' is not a pointer; did you mean to use '.'?}}
487+
a->x;
488+
b->x;
489489
c->x;
490490
}
491491

492492
void instantiated(A a, A<T> b, T c) {
493-
// FIXME: We should only emit a single diagnostic suggesting to use '.'!
494-
a->x; // expected-error {{member reference type 'A<T>' is not a pointer; did you mean to use '.'?}}
495-
// expected-error@-1 {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
496-
// expected-error@-2 {{no member named 'x' in 'N4::A<int>'}}
497-
b->x; // expected-error {{member reference type 'A<T>' is not a pointer; did you mean to use '.'?}}
498-
// expected-error@-1 {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
499-
// expected-error@-2 {{no member named 'x' in 'N4::A<int>'}}
493+
a->x; // expected-error {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
494+
// expected-error@-1 {{no member named 'x' in 'N4::A<int>'}}
495+
b->x; // expected-error {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
496+
// expected-error@-1 {{no member named 'x' in 'N4::A<int>'}}
500497
c->x; // expected-error {{member reference type 'int' is not a pointer}}
501498
}
502499
};
@@ -543,10 +540,11 @@ namespace N4 {
543540
a->T::f();
544541
a->T::g();
545542

546-
a->U::x;
547-
a->U::y;
548-
a->U::f();
549-
a->U::g();
543+
// FIXME: 'U' should be a dependent name, and its lookup context should be 'a.operator->()'!
544+
a->U::x; // expected-error {{use of undeclared identifier 'U'}}
545+
a->U::y; // expected-error {{use of undeclared identifier 'U'}}
546+
a->U::f(); // expected-error {{use of undeclared identifier 'U'}}
547+
a->U::g(); // expected-error {{use of undeclared identifier 'U'}}
550548
}
551549

552550
void instantiated(D a) {
@@ -607,24 +605,3 @@ namespace N5 {
607605

608606
template void g(int); // expected-note {{in instantiation of}}
609607
} // namespace N5
610-
611-
namespace N6 {
612-
struct A {
613-
int x;
614-
};
615-
616-
struct B {
617-
A* operator->();
618-
};
619-
620-
struct C {
621-
B y;
622-
};
623-
624-
template<typename T>
625-
struct D : C {
626-
void f() {
627-
y->x;
628-
}
629-
};
630-
} // namespace N6

0 commit comments

Comments
 (0)