@@ -7966,6 +7966,18 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
7966
7966
7967
7967
QualType BaseType = Base->getType();
7968
7968
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
+ }
7969
7981
7970
7982
// C++ [over.match.oper]p8:
7971
7983
// [...] When operator->returns, the operator-> is applied to the value
@@ -7980,8 +7992,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
7980
7992
SmallVector<FunctionDecl*, 8> OperatorArrows;
7981
7993
CTypes.insert(Context.getCanonicalType(BaseType));
7982
7994
7983
- while (
7984
- isa<InjectedClassNameType, RecordType>(BaseType.getCanonicalType())) {
7995
+ while (BaseType->isRecordType()) {
7985
7996
if (OperatorArrows.size() >= getLangOpts().ArrowDepth) {
7986
7997
Diag(OpLoc, diag::err_operator_arrow_depth_exceeded)
7987
7998
<< StartingType << getLangOpts().ArrowDepth << Base->getSourceRange();
@@ -7991,26 +8002,15 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
7991
8002
return ExprError();
7992
8003
}
7993
8004
7994
- bool IsDependent;
7995
8005
Result = BuildOverloadedArrowExpr(
7996
- Base, OpLoc,
8006
+ S, Base, OpLoc,
7997
8007
// When in a template specialization and on the first loop iteration,
7998
8008
// potentially give the default diagnostic (with the fixit in a
7999
8009
// separate note) instead of having the error reported back to here
8000
8010
// and giving a diagnostic with a fixit attached to the error itself.
8001
8011
(FirstIteration && CurFD && CurFD->isFunctionTemplateSpecialization())
8002
8012
? 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);
8014
8014
if (Result.isInvalid()) {
8015
8015
if (NoArrowOperatorFound) {
8016
8016
if (FirstIteration) {
@@ -8030,7 +8030,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
8030
8030
}
8031
8031
return ExprError();
8032
8032
}
8033
-
8034
8033
Base = Result.get();
8035
8034
if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base))
8036
8035
OperatorArrows.push_back(OpCall->getDirectCallee());
@@ -8068,7 +8067,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
8068
8067
// it's legal for the type to be incomplete if this is a pseudo-destructor
8069
8068
// call. We'll do more incomplete-type checks later in the lookup process,
8070
8069
// so just skip this check for ObjC types.
8071
- if (!isa<InjectedClassNameType, RecordType>(BaseType.getCanonicalType() )) {
8070
+ if (!BaseType->isRecordType( )) {
8072
8071
ObjectType = ParsedType::make(BaseType);
8073
8072
MayBePseudoDestructor = true;
8074
8073
return Base;
@@ -8086,10 +8085,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
8086
8085
return CreateRecoveryExpr(Base->getBeginLoc(), Base->getEndLoc(), {Base});
8087
8086
}
8088
8087
8089
- // We can't implicitly declare the destructor for a templated class.
8090
- if (BaseType->isDependentType())
8091
- MayBePseudoDestructor = true;
8092
-
8093
8088
// C++ [basic.lookup.classref]p2:
8094
8089
// If the id-expression in a class member access (5.2.5) is an
8095
8090
// unqualified-id, and the type of the object expression is of a class
0 commit comments