[clang] Revert "Reapply "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (#104458)"" (PR #123982)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 22 11:13:35 PST 2025
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/123982
>From c57b0c0bda26134131a4c846e0b81b000250709d Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 22 Jan 2025 13:43:38 -0500
Subject: [PATCH 1/2] =?UTF-8?q?Revert=20"Reapply=20"[Clang][Sema]=20Use=20?=
=?UTF-8?q?the=20correct=20lookup=20context=20when=20building=20o=E2=80=A6?=
=?UTF-8?q?"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 195a1fc5b05d7a42b2e3fa383edb9a7e8b34a9c5.
---
clang/include/clang/Sema/Sema.h | 5 ++-
clang/lib/Sema/SemaExprCXX.cpp | 21 +++++++--
clang/lib/Sema/SemaExprMember.cpp | 2 +-
clang/lib/Sema/SemaOverload.cpp | 20 +++------
clang/lib/Sema/TreeTransform.h | 5 +--
.../temp.res/temp.dep/temp.dep.type/p4.cpp | 45 +++++--------------
6 files changed, 39 insertions(+), 59 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index a2a47d535b8e06..9fa33d6ca76ba5 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10608,8 +10608,9 @@ class Sema final : public SemaBase {
/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator->
/// (if one exists), where @c Base is an expression of class type and
/// @c Member is the name of the member we're trying to find.
- ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
- bool *NoArrowOperatorFound);
+ ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ bool *NoArrowOperatorFound = nullptr);
ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
CXXConversionDecl *Method,
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 0ebf5f54613926..1e39d69e8b230f 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -7999,6 +7999,18 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
QualType BaseType = Base->getType();
MayBePseudoDestructor = false;
+ if (BaseType->isDependentType()) {
+ // If we have a pointer to a dependent type and are using the -> operator,
+ // the object type is the type that the pointer points to. We might still
+ // have enough information about that type to do something useful.
+ if (OpKind == tok::arrow)
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+
+ ObjectType = ParsedType::make(BaseType);
+ MayBePseudoDestructor = true;
+ return Base;
+ }
// C++ [over.match.oper]p8:
// [...] When operator->returns, the operator-> is applied to the value
@@ -8013,7 +8025,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
SmallVector<FunctionDecl*, 8> OperatorArrows;
CTypes.insert(Context.getCanonicalType(BaseType));
- while (BaseType->getAsRecordDecl()) {
+ while (BaseType->isRecordType()) {
if (OperatorArrows.size() >= getLangOpts().ArrowDepth) {
Diag(OpLoc, diag::err_operator_arrow_depth_exceeded)
<< StartingType << getLangOpts().ArrowDepth << Base->getSourceRange();
@@ -8024,7 +8036,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
}
Result = BuildOverloadedArrowExpr(
- Base, OpLoc,
+ S, Base, OpLoc,
// When in a template specialization and on the first loop iteration,
// potentially give the default diagnostic (with the fixit in a
// separate note) instead of having the error reported back to here
@@ -8088,7 +8100,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
// it's legal for the type to be incomplete if this is a pseudo-destructor
// call. We'll do more incomplete-type checks later in the lookup process,
// so just skip this check for ObjC types.
- if (BaseType->isDependentType() || !BaseType->isRecordType()) {
+ if (!BaseType->isRecordType()) {
ObjectType = ParsedType::make(BaseType);
MayBePseudoDestructor = true;
return Base;
@@ -8099,7 +8111,8 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
// Unlike the object expression in other contexts, *this is not required to
// be of complete type for purposes of class member access (5.2.5) outside
// the member function body.
- if (!isThisOutsideMemberFunctionBody(BaseType) &&
+ if (!BaseType->isDependentType() &&
+ !isThisOutsideMemberFunctionBody(BaseType) &&
RequireCompleteType(OpLoc, BaseType,
diag::err_incomplete_member_access)) {
return CreateRecoveryExpr(Base->getBeginLoc(), Base->getEndLoc(), {Base});
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 8326a4db0a7719..d130e8b86bc56d 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -1357,7 +1357,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
BaseType = Ptr->getPointeeType();
else if (BaseType->isFunctionType())
goto fail;
- else if (BaseExpr.get()->isTypeDependent())
+ else if (BaseType->isDependentType())
BaseType = S.Context.DependentTy;
else if (BaseType->isRecordType()) {
// Recover from arrow accesses to records, e.g.:
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index bf4c0288274ac7..7e8811b5274efb 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -15962,9 +15962,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method);
}
-ExprResult Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
- bool *NoArrowOperatorFound) {
- assert(Base->getType()->getAsRecordDecl() &&
+ExprResult
+Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
+ bool *NoArrowOperatorFound) {
+ assert(Base->getType()->isRecordType() &&
"left-hand side must have class type");
if (checkPlaceholderForOverload(*this, Base))
@@ -15987,20 +15988,9 @@ ExprResult Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
return ExprError();
LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
- LookupParsedName(R, /*S=*/nullptr, /*SS=*/nullptr, Base->getType());
+ LookupQualifiedName(R, Base->getType()->castAs<RecordType>()->getDecl());
R.suppressAccessDiagnostics();
- if (Base->getType()->isDependentType() &&
- (!R.empty() || R.wasNotFoundInCurrentInstantiation())) {
- DeclarationNameInfo OpNameInfo(OpName, OpLoc);
- ExprResult Fn = CreateUnresolvedLookupExpr(
- /*NamingClass=*/nullptr, /*NNSLoc=*/NestedNameSpecifierLoc(),
- OpNameInfo, R.asUnresolvedSet(), /*PerformADL=*/false);
- return CXXOperatorCallExpr::Create(Context, OO_Arrow, Fn.get(), Base,
- Context.DependentTy, VK_PRValue, OpLoc,
- CurFPFeatureOverrides());
- }
-
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context),
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index c0363692a3eb72..7dc88a1ae23b98 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -17282,11 +17282,10 @@ ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(
} else if (Op == OO_Arrow) {
// It is possible that the type refers to a RecoveryExpr created earlier
// in the tree transformation.
- if (First->containsErrors())
+ if (First->getType()->isDependentType())
return ExprError();
// -> is never a builtin operation.
- return getSema().BuildOverloadedArrowExpr(First, OpLoc,
- /*NoArrowOperatorFound=*/nullptr);
+ return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc);
} else if (Second == nullptr || isPostIncDec) {
if (!First->getType()->isOverloadableType() ||
(Op == OO_Amp && getSema().isQualifiedMemberAccess(First))) {
diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
index 03eda1f13feed7..f32f49ef4539a5 100644
--- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
@@ -484,19 +484,16 @@ namespace N4 {
template<typename T>
struct A {
void not_instantiated(A a, A<T> b, T c) {
- a->x; // expected-error {{member reference type 'A<T>' is not a pointer; did you mean to use '.'?}}
- b->x; // expected-error {{member reference type 'A<T>' is not a pointer; did you mean to use '.'?}}
+ a->x;
+ b->x;
c->x;
}
void instantiated(A a, A<T> b, T c) {
- // FIXME: We should only emit a single diagnostic suggesting to use '.'!
- a->x; // expected-error {{member reference type 'A<T>' is not a pointer; did you mean to use '.'?}}
- // expected-error at -1 {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
- // expected-error at -2 {{no member named 'x' in 'N4::A<int>'}}
- b->x; // expected-error {{member reference type 'A<T>' is not a pointer; did you mean to use '.'?}}
- // expected-error at -1 {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
- // expected-error at -2 {{no member named 'x' in 'N4::A<int>'}}
+ a->x; // expected-error {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
+ // expected-error at -1 {{no member named 'x' in 'N4::A<int>'}}
+ b->x; // expected-error {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
+ // expected-error at -1 {{no member named 'x' in 'N4::A<int>'}}
c->x; // expected-error {{member reference type 'int' is not a pointer}}
}
};
@@ -543,10 +540,11 @@ namespace N4 {
a->T::f();
a->T::g();
- a->U::x;
- a->U::y;
- a->U::f();
- a->U::g();
+ // FIXME: 'U' should be a dependent name, and its lookup context should be 'a.operator->()'!
+ a->U::x; // expected-error {{use of undeclared identifier 'U'}}
+ a->U::y; // expected-error {{use of undeclared identifier 'U'}}
+ a->U::f(); // expected-error {{use of undeclared identifier 'U'}}
+ a->U::g(); // expected-error {{use of undeclared identifier 'U'}}
}
void instantiated(D a) {
@@ -607,24 +605,3 @@ namespace N5 {
template void g(int); // expected-note {{in instantiation of}}
} // namespace N5
-
-namespace N6 {
- struct A {
- int x;
- };
-
- struct B {
- A* operator->();
- };
-
- struct C {
- B y;
- };
-
- template<typename T>
- struct D : C {
- void f() {
- y->x;
- }
- };
-} // namespace N6
>From f17058b354221c402b035a41545bf90deb95e233 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 22 Jan 2025 14:13:27 -0500
Subject: [PATCH 2/2] [FOLD] fix formatting
---
clang/lib/Sema/SemaOverload.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 7e8811b5274efb..23056ca5deba3c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -15962,9 +15962,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method);
}
-ExprResult
-Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
- bool *NoArrowOperatorFound) {
+ExprResult Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ bool *NoArrowOperatorFound) {
assert(Base->getType()->isRecordType() &&
"left-hand side must have class type");
More information about the cfe-commits
mailing list