Skip to content

Commit 3681d85

Browse files
committed
Revert "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (#104458)"
This reverts commit 3cdb30e. Breaks clang bootstrap.
1 parent ab82f83 commit 3681d85

File tree

5 files changed

+37
-62
lines changed

5 files changed

+37
-62
lines changed

clang/include/clang/Sema/Sema.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -10639,9 +10639,9 @@ class Sema final : public SemaBase {
1063910639
/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator->
1064010640
/// (if one exists), where @c Base is an expression of class type and
1064110641
/// @c Member is the name of the member we're trying to find.
10642-
ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
10643-
bool *NoArrowOperatorFound,
10644-
bool &IsDependent);
10642+
ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
10643+
SourceLocation OpLoc,
10644+
bool *NoArrowOperatorFound = nullptr);
1064510645

1064610646
ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
1064710647
CXXConversionDecl *Method,

clang/lib/Sema/SemaExprCXX.cpp

+16-21
Original file line numberDiff line numberDiff line change
@@ -7966,6 +7966,18 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
79667966

79677967
QualType BaseType = Base->getType();
79687968
MayBePseudoDestructor = false;
7969+
if (BaseType->isDependentType()) {
7970+
// If we have a pointer to a dependent type and are using the -> operator,
7971+
// the object type is the type that the pointer points to. We might still
7972+
// have enough information about that type to do something useful.
7973+
if (OpKind == tok::arrow)
7974+
if (const PointerType *Ptr = BaseType->getAs<PointerType>())
7975+
BaseType = Ptr->getPointeeType();
7976+
7977+
ObjectType = ParsedType::make(BaseType);
7978+
MayBePseudoDestructor = true;
7979+
return Base;
7980+
}
79697981

79707982
// C++ [over.match.oper]p8:
79717983
// [...] When operator->returns, the operator-> is applied to the value
@@ -7980,8 +7992,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
79807992
SmallVector<FunctionDecl*, 8> OperatorArrows;
79817993
CTypes.insert(Context.getCanonicalType(BaseType));
79827994

7983-
while (
7984-
isa<InjectedClassNameType, RecordType>(BaseType.getCanonicalType())) {
7995+
while (BaseType->isRecordType()) {
79857996
if (OperatorArrows.size() >= getLangOpts().ArrowDepth) {
79867997
Diag(OpLoc, diag::err_operator_arrow_depth_exceeded)
79877998
<< StartingType << getLangOpts().ArrowDepth << Base->getSourceRange();
@@ -7991,26 +8002,15 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
79918002
return ExprError();
79928003
}
79938004

7994-
bool IsDependent;
79958005
Result = BuildOverloadedArrowExpr(
7996-
Base, OpLoc,
8006+
S, Base, OpLoc,
79978007
// When in a template specialization and on the first loop iteration,
79988008
// potentially give the default diagnostic (with the fixit in a
79998009
// separate note) instead of having the error reported back to here
80008010
// and giving a diagnostic with a fixit attached to the error itself.
80018011
(FirstIteration && CurFD && CurFD->isFunctionTemplateSpecialization())
80028012
? nullptr
8003-
: &NoArrowOperatorFound,
8004-
IsDependent);
8005-
8006-
if (IsDependent) {
8007-
// BuildOverloadedArrowExpr sets IsDependent to indicate that we need
8008-
// to build a dependent overloaded arrow expression.
8009-
assert(BaseType->isDependentType());
8010-
BaseType = Context.DependentTy;
8011-
break;
8012-
}
8013-
8013+
: &NoArrowOperatorFound);
80148014
if (Result.isInvalid()) {
80158015
if (NoArrowOperatorFound) {
80168016
if (FirstIteration) {
@@ -8030,7 +8030,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80308030
}
80318031
return ExprError();
80328032
}
8033-
80348033
Base = Result.get();
80358034
if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base))
80368035
OperatorArrows.push_back(OpCall->getDirectCallee());
@@ -8068,7 +8067,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80688067
// it's legal for the type to be incomplete if this is a pseudo-destructor
80698068
// call. We'll do more incomplete-type checks later in the lookup process,
80708069
// so just skip this check for ObjC types.
8071-
if (!isa<InjectedClassNameType, RecordType>(BaseType.getCanonicalType())) {
8070+
if (!BaseType->isRecordType()) {
80728071
ObjectType = ParsedType::make(BaseType);
80738072
MayBePseudoDestructor = true;
80748073
return Base;
@@ -8086,10 +8085,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80868085
return CreateRecoveryExpr(Base->getBeginLoc(), Base->getEndLoc(), {Base});
80878086
}
80888087

8089-
// We can't implicitly declare the destructor for a templated class.
8090-
if (BaseType->isDependentType())
8091-
MayBePseudoDestructor = true;
8092-
80938088
// C++ [basic.lookup.classref]p2:
80948089
// If the id-expression in a class member access (5.2.5) is an
80958090
// unqualified-id, and the type of the object expression is of a class

clang/lib/Sema/SemaOverload.cpp

+5-19
Original file line numberDiff line numberDiff line change
@@ -15878,14 +15878,12 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
1587815878
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method);
1587915879
}
1588015880

15881-
ExprResult Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
15882-
bool *NoArrowOperatorFound,
15883-
bool &IsDependent) {
15884-
assert(Base->getType()->getAsRecordDecl() &&
15881+
ExprResult
15882+
Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
15883+
bool *NoArrowOperatorFound) {
15884+
assert(Base->getType()->isRecordType() &&
1588515885
"left-hand side must have class type");
1588615886

15887-
IsDependent = false;
15888-
1588915887
if (checkPlaceholderForOverload(*this, Base))
1589015888
return ExprError();
1589115889

@@ -15906,19 +15904,7 @@ ExprResult Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
1590615904
return ExprError();
1590715905

1590815906
LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
15909-
LookupParsedName(R, /*S=*/nullptr, /*SS=*/nullptr, Base->getType());
15910-
15911-
// If the expression is dependent and we either:
15912-
// - found a member of the current instantiation named 'operator->', or
15913-
// - found nothing, and the lookup context has no dependent base classes
15914-
//
15915-
// then we should build a dependent class member access expression.
15916-
if (R.wasNotFoundInCurrentInstantiation() ||
15917-
(Base->isTypeDependent() && !R.empty())) {
15918-
IsDependent = true;
15919-
return Base;
15920-
}
15921-
15907+
LookupQualifiedName(R, Base->getType()->castAs<RecordType>()->getDecl());
1592215908
R.suppressAccessDiagnostics();
1592315909

1592415910
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();

clang/lib/Sema/TreeTransform.h

+2-6
Original file line numberDiff line numberDiff line change
@@ -16583,14 +16583,10 @@ ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(
1658316583
} else if (Op == OO_Arrow) {
1658416584
// It is possible that the type refers to a RecoveryExpr created earlier
1658516585
// in the tree transformation.
16586-
if (First->containsErrors())
16586+
if (First->getType()->isDependentType())
1658716587
return ExprError();
16588-
bool IsDependent;
1658916588
// -> is never a builtin operation.
16590-
ExprResult Result = SemaRef.BuildOverloadedArrowExpr(
16591-
First, OpLoc, /*NoArrowOperatorFound=*/nullptr, IsDependent);
16592-
assert(!IsDependent);
16593-
return Result;
16589+
return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc);
1659416590
} else if (Second == nullptr || isPostIncDec) {
1659516591
if (!First->getType()->isOverloadableType() ||
1659616592
(Op == OO_Amp && getSema().isQualifiedMemberAccess(First))) {

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

+11-13
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) {

0 commit comments

Comments
 (0)