Skip to content

Commit d1b0cad

Browse files
committed
Reapply "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (llvm#104458)"
1 parent 620b8d9 commit d1b0cad

File tree

5 files changed

+35
-35
lines changed

5 files changed

+35
-35
lines changed

clang/include/clang/Sema/Sema.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -10639,8 +10639,7 @@ 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(Scope *S, Expr *Base,
10643-
SourceLocation OpLoc,
10642+
ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
1064410643
bool *NoArrowOperatorFound = nullptr);
1064510644

1064610645
ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,

clang/lib/Sema/SemaExprCXX.cpp

+10-15
Original file line numberDiff line numberDiff line change
@@ -7966,18 +7966,6 @@ 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-
}
79817969

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

7995-
while (BaseType->isRecordType()) {
7983+
while (BaseType->getAsRecordDecl()) {
79967984
if (OperatorArrows.size() >= getLangOpts().ArrowDepth) {
79977985
Diag(OpLoc, diag::err_operator_arrow_depth_exceeded)
79987986
<< StartingType << getLangOpts().ArrowDepth << Base->getSourceRange();
@@ -8003,7 +7991,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80037991
}
80047992

80057993
Result = BuildOverloadedArrowExpr(
8006-
S, Base, OpLoc,
7994+
Base, OpLoc,
80077995
// When in a template specialization and on the first loop iteration,
80087996
// potentially give the default diagnostic (with the fixit in a
80097997
// separate note) instead of having the error reported back to here
@@ -8029,7 +8017,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80298017
}
80308018
}
80318019
return ExprError();
8020+
} else if (Result.isUnset()) {
8021+
// BuildOverloadedArrowExpr returns an empty expression to indicate
8022+
// that we need to build a dependent overloaded arrow expression.
8023+
assert(BaseType->isDependentType());
8024+
BaseType = Context.DependentTy;
8025+
break;
80328026
}
8027+
80338028
Base = Result.get();
80348029
if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base))
80358030
OperatorArrows.push_back(OpCall->getDirectCallee());
@@ -8067,7 +8062,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
80678062
// it's legal for the type to be incomplete if this is a pseudo-destructor
80688063
// call. We'll do more incomplete-type checks later in the lookup process,
80698064
// so just skip this check for ObjC types.
8070-
if (!BaseType->isRecordType()) {
8065+
if (!BaseType->getAsRecordDecl()) {
80718066
ObjectType = ParsedType::make(BaseType);
80728067
MayBePseudoDestructor = true;
80738068
return Base;

clang/lib/Sema/SemaOverload.cpp

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

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

1588715886
if (checkPlaceholderForOverload(*this, Base))
@@ -15904,7 +15903,12 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
1590415903
return ExprError();
1590515904

1590615905
LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
15907-
LookupQualifiedName(R, Base->getType()->castAs<RecordType>()->getDecl());
15906+
LookupParsedName(R, /*S=*/nullptr, /*SS=*/nullptr, Base->getType());
15907+
15908+
if (R.wasNotFoundInCurrentInstantiation() ||
15909+
(Base->isTypeDependent() && !R.empty()))
15910+
return ExprEmpty();
15911+
1590815912
R.suppressAccessDiagnostics();
1590915913

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

clang/lib/Sema/TreeTransform.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -16583,10 +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->getType()->isDependentType())
16586+
if (First->containsErrors())
1658716587
return ExprError();
1658816588
// -> is never a builtin operation.
16589-
return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc);
16589+
return SemaRef.BuildOverloadedArrowExpr(First, OpLoc);
1659016590
} else if (Second == nullptr || isPostIncDec) {
1659116591
if (!First->getType()->isOverloadableType() ||
1659216592
(Op == OO_Amp && getSema().isQualifiedMemberAccess(First))) {

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

+13-11
Original file line numberDiff line numberDiff line change
@@ -484,16 +484,19 @@ namespace N4 {
484484
template<typename T>
485485
struct A {
486486
void not_instantiated(A a, A<T> b, T c) {
487-
a->x;
488-
b->x;
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 '.'?}}
489489
c->x;
490490
}
491491

492492
void instantiated(A a, A<T> b, T c) {
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>'}}
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>'}}
497500
c->x; // expected-error {{member reference type 'int' is not a pointer}}
498501
}
499502
};
@@ -540,11 +543,10 @@ namespace N4 {
540543
a->T::f();
541544
a->T::g();
542545

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'}}
546+
a->U::x;
547+
a->U::y;
548+
a->U::f();
549+
a->U::g();
548550
}
549551

550552
void instantiated(D a) {

0 commit comments

Comments
 (0)