diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index e92f6696027f9..53afd206073ab 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -3263,7 +3263,7 @@ class MemberExpr final : public Expr, private llvm::TrailingObjects { + TemplateArgumentLoc, QualType> { friend class ASTReader; friend class ASTStmtReader; friend class ASTStmtWriter; @@ -3304,13 +3304,23 @@ class MemberExpr final return MemberExprBits.HasTemplateKWAndArgsInfo; } + size_t numTrailingObjects(OverloadToken) const { + return getNumTemplateArgs(); + } + + size_t numTrailingObjects(OverloadToken) const { + return HasResugaredDeclType(); + } + + static bool needsDeclTypeStorage(ValueDecl *VD, QualType DeclType); + MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, DeclAccessPair FoundDecl, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK, - ExprObjectKind OK, NonOdrUseReason NOUR); + QualType DeclType, ExprObjectKind OK, NonOdrUseReason NOUR); MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty), Base(), MemberDecl() {} @@ -3322,7 +3332,7 @@ class MemberExpr final DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK, - ExprObjectKind OK, NonOdrUseReason NOUR); + QualType DeclType, ExprObjectKind OK, NonOdrUseReason NOUR); /// Create an implicit MemberExpr, with no location, qualifier, template /// arguments, and so on. Suitable only for non-static member access. @@ -3333,14 +3343,15 @@ class MemberExpr final return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), MemberDecl, DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()), - DeclarationNameInfo(), nullptr, /*Deduced=*/{}, T, VK, OK, - NOUR_None); + DeclarationNameInfo(), nullptr, /*Deduced=*/{}, T, VK, + QualType(), OK, NOUR_None); } static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier, bool HasFoundDecl, bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs); + unsigned NumTemplateArgs, + bool HasResugaredDeclType); void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast(Base); } @@ -3351,6 +3362,16 @@ class MemberExpr final /// static data members), a CXXMethodDecl, or an EnumConstantDecl. ValueDecl *getMemberDecl() const { return MemberDecl; } void setMemberDecl(ValueDecl *D); + void recomputeDependency(); + + bool HasResugaredDeclType() const { + return MemberExprBits.HasResugaredDeclType; + } + QualType getDeclType() const { + return HasResugaredDeclType() ? *getTrailingObjects() + : MemberDecl->getType(); + } + void setDeclType(QualType T); /// Retrieves the declaration found by lookup. DeclAccessPair getFoundDecl() const { diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 805d301b95f8e..a64f8de074237 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -616,6 +616,10 @@ class alignas(void *) Stmt { LLVM_PREFERRED_TYPE(NonOdrUseReason) unsigned NonOdrUseReason : 2; + /// Consider a different type for the MemberDecl this MemberExpr refers to. + LLVM_PREFERRED_TYPE(bool) + unsigned HasResugaredDeclType : 1; + /// This is the location of the -> or . in the expression. SourceLocation OperatorLoc; }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index c476c80f5237d..101062ce778c7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8709,7 +8709,8 @@ class Sema final : public SemaBase { NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, - ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr, + ExprObjectKind OK, QualType DeclType = QualType(), + const TemplateArgumentListInfo *TemplateArgs = nullptr, const TemplateArgumentList *Deduced = nullptr); // Check whether the declarations we found through a nested-name @@ -8758,7 +8759,7 @@ class Sema final : public SemaBase { ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const NestedNameSpecifierLoc &NNS, - FieldDecl *Field, QualType FieldType, + FieldDecl *Field, QualType FieldDeclType, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo); @@ -14013,6 +14014,7 @@ class Sema final : public SemaBase { QualType resugar(const Type *Base, NamedDecl *ND, ArrayRef Args, QualType T); QualType resugar(DeclRefExpr *DRE, ValueDecl *VD); + QualType resugar(MemberExpr *ME, ValueDecl *VD); /// Performs template instantiation for all implicit template /// instantiations we have seen until this point. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 876e6cd26ff7b..a5fb4f286d1cf 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8452,6 +8452,7 @@ ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { auto ToDecl = importChecked(Err, E->getFoundDecl().getDecl()); auto ToName = importChecked(Err, E->getMemberNameInfo().getName()); auto ToLoc = importChecked(Err, E->getMemberNameInfo().getLoc()); + auto ToDeclType = importChecked(Err, E->getDeclType()); if (Err) return std::move(Err); @@ -8473,7 +8474,7 @@ ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl, ToFoundDecl, ToMemberNameInfo, ResInfo, ToDeduced, ToType, E->getValueKind(), - E->getObjectKind(), E->isNonOdrUse()); + ToDeclType, E->getObjectKind(), E->isNonOdrUse()); } ExpectedStmt diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 80f22a4eab99c..82e54839547b7 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1761,6 +1761,11 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr( setDependence(computeDependence(this)); } +bool MemberExpr::needsDeclTypeStorage(ValueDecl *VD, QualType DeclType) { + return !DeclType.isNull() && + (DeclType != VD->getType() || VD->getType()->isUndeducedType()); +} + MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, @@ -1768,7 +1773,7 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, const TemplateArgumentList *Deduced, QualType T, - ExprValueKind VK, ExprObjectKind OK, + ExprValueKind VK, QualType DeclType, ExprObjectKind OK, NonOdrUseReason NOUR) : Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl), Deduced(Deduced), MemberDNLoc(NameInfo.getInfo()), @@ -1784,6 +1789,8 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, TemplateArgs || TemplateKWLoc.isValid(); MemberExprBits.HadMultipleCandidates = false; MemberExprBits.NonOdrUseReason = NOUR; + MemberExprBits.HasResugaredDeclType = + needsDeclTypeStorage(MemberDecl, DeclType); MemberExprBits.OperatorLoc = OperatorLoc; if (hasQualifier()) @@ -1800,6 +1807,12 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, getTrailingObjects()->initializeFrom( TemplateKWLoc); } + if (HasResugaredDeclType()) { + assert(DeclType.getCanonicalType() == + MemberDecl->getType().getCanonicalType()); + *getTrailingObjects() = + DeclType.isNull() ? MemberDecl->getType() : DeclType; + } setDependence(computeDependence(this)); } @@ -1809,45 +1822,60 @@ MemberExpr *MemberExpr::Create( ValueDecl *MemberDecl, DeclAccessPair FoundDecl, DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs, const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK, - ExprObjectKind OK, NonOdrUseReason NOUR) { + QualType DeclType, ExprObjectKind OK, NonOdrUseReason NOUR) { bool HasQualifier = QualifierLoc.hasQualifier(); bool HasFoundDecl = FoundDecl.getDecl() != MemberDecl || FoundDecl.getAccess() != MemberDecl->getAccess(); bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); std::size_t Size = totalSizeToAlloc( + ASTTemplateKWAndArgsInfo, TemplateArgumentLoc, QualType>( HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo, - TemplateArgs ? TemplateArgs->size() : 0); + TemplateArgs ? TemplateArgs->size() : 0, + needsDeclTypeStorage(MemberDecl, DeclType) ? 1 : 0); void *Mem = C.Allocate(Size, alignof(MemberExpr)); return new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc, MemberDecl, FoundDecl, NameInfo, - TemplateArgs, Deduced, T, VK, OK, NOUR); + TemplateArgs, Deduced, T, VK, DeclType, OK, NOUR); } MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context, bool HasQualifier, bool HasFoundDecl, bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs) { + unsigned NumTemplateArgs, + bool HasResugaredDeclType) { assert((!NumTemplateArgs || HasTemplateKWAndArgsInfo) && "template args but no template arg info?"); std::size_t Size = totalSizeToAlloc( - HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo, - NumTemplateArgs); + ASTTemplateKWAndArgsInfo, TemplateArgumentLoc, QualType>( + HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo, NumTemplateArgs, + HasResugaredDeclType); void *Mem = Context.Allocate(Size, alignof(MemberExpr)); return new (Mem) MemberExpr(EmptyShell()); } void MemberExpr::setMemberDecl(ValueDecl *NewD) { + assert(MemberDecl != NewD); + assert(declaresSameEntity(MemberDecl, NewD)); + assert(!HasResugaredDeclType() || + MemberDecl->getASTContext().hasSameType( + NewD->getType(), *getTrailingObjects())); MemberDecl = NewD; - if (getType()->isUndeducedType()) - setType(NewD->getType()); + recomputeDependency(); +} + +void MemberExpr::recomputeDependency() { setDependence(computeDependence(this)); } +void MemberExpr::setDeclType(QualType T) { + assert(!T.isNull()); + if (HasResugaredDeclType()) + *getTrailingObjects() = T; +} + SourceLocation MemberExpr::getBeginLoc() const { if (isImplicitAccess()) { if (hasQualifier()) diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp index 058d8fa1328e3..9fdfe2946d7c1 100644 --- a/clang/lib/Analysis/BodyFarm.cpp +++ b/clang/lib/Analysis/BodyFarm.cpp @@ -232,7 +232,7 @@ MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl, SourceLocation(), MemberDecl, FoundDecl, DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()), /* TemplateArgumentListInfo=*/nullptr, /*Deduced=*/nullptr, - MemberDecl->getType(), ValueKind, OK_Ordinary, NOUR_None); + MemberDecl->getType(), ValueKind, QualType(), OK_Ordinary, NOUR_None); } ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 6b9b6199e575b..f9be8fbc1444b 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1867,7 +1867,7 @@ static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction &CGF, return DeclRefExpr::Create( CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD, /*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(), - ME->getType(), ME->getValueKind(), QualType(), nullptr, nullptr, + ME->getType(), ME->getValueKind(), ME->getDeclType(), nullptr, nullptr, nullptr, ME->isNonOdrUse()); } return nullptr; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 18e5c77b55c49..62c852eb5b22e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -19537,7 +19537,8 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(), CopiedTemplateArgs(ME), ME->getDeduced(), ME->getType(), - ME->getValueKind(), ME->getObjectKind(), ME->isNonOdrUse()); + ME->getValueKind(), ME->getDeclType(), ME->getObjectKind(), + ME->isNonOdrUse()); } if (ME->getMemberDecl()->isCXXInstanceMember()) @@ -19554,7 +19555,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, S.Context, ME->getBase(), ME->isArrow(), ME->getOperatorLoc(), ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(), CopiedTemplateArgs(ME), - ME->getDeduced(), ME->getType(), ME->getValueKind(), + ME->getDeduced(), ME->getType(), ME->getValueKind(), ME->getDeclType(), ME->getObjectKind(), NOUR); } @@ -19905,17 +19906,9 @@ static void DoMarkVarDeclReferenced( DRE->setType(SemaRef.resugar(DRE, DRE->getDecl())); DRE->recomputeDependency(); } else if (auto *ME = dyn_cast_or_null(E)) { - ME->setMemberDecl(ME->getMemberDecl()); - CXXScopeSpec SS; - SS.Adopt(ME->getQualifierLoc()); - assert(ME->template_arguments().size() == 0 || - ME->getDeduced() != nullptr); - QualType T = - ME->getDeduced() - ? SemaRef.resugar(SS.getScopeRep(), ME->getMemberDecl(), - ME->getDeduced()->asArray(), ME->getType()) - : SemaRef.resugar(SS.getScopeRep(), ME->getType()); - ME->setType(T); + if (ME->getType()->isUndeducedType()) + ME->setType(SemaRef.resugar(ME, ME->getMemberDecl())); + ME->recomputeDependency(); } } else if (FirstInstantiation) { SemaRef.PendingInstantiations diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 72ae475548e23..427241f36b2b7 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -943,14 +943,14 @@ MemberExpr *Sema::BuildMemberExpr( Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, - QualType Ty, ExprValueKind VK, ExprObjectKind OK, + QualType Ty, ExprValueKind VK, ExprObjectKind OK, QualType DeclType, const TemplateArgumentListInfo *TemplateArgs, const TemplateArgumentList *Deduced) { assert((!IsArrow || Base->isPRValue()) && "-> base must be a pointer prvalue"); MemberExpr *E = MemberExpr::Create( Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member, FoundDecl, - MemberNameInfo, TemplateArgs, Deduced, Ty, VK, OK, + MemberNameInfo, TemplateArgs, Deduced, Ty, VK, DeclType, OK, getNonOdrUseReasonInCurrentContext(Member)); E->setHadMultipleCandidates(HadMultipleCandidates); MarkMemberReferenced(E); @@ -1204,13 +1204,15 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, NNS, TemplateKWLoc, Var, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, VarType.getNonReferenceType(), - VK_LValue, OK_Ordinary); + VK_LValue, OK_Ordinary, VarType); } if (CXXMethodDecl *MemberFn = dyn_cast(MemberDecl)) { assert(!TemplateArgs); NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context); + QualType DeclType = + resugar(BaseType.getTypePtr(), SS.getScopeRep(), MemberFn->getType()); ExprValueKind valueKind; QualType type; if (MemberFn->isInstance()) { @@ -1224,13 +1226,13 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (ConvertBaseExprToDiscardedValue()) return ExprError(); valueKind = VK_LValue; - type = - resugar(BaseType.getTypePtr(), SS.getScopeRep(), MemberFn->getType()); + type = DeclType; } return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, NNS, TemplateKWLoc, MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, - MemberNameInfo, type, valueKind, OK_Ordinary); + MemberNameInfo, type, valueKind, OK_Ordinary, + DeclType); } assert(!isa(MemberDecl) && "member function not C++ method?"); @@ -1244,7 +1246,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, resugar(BaseType.getTypePtr(), SS.getScopeRep(), Enum->getType()); return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, NNS, TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandidates=*/false, - MemberNameInfo, EnumType, VK_PRValue, OK_Ordinary); + MemberNameInfo, EnumType, VK_PRValue, OK_Ordinary, + EnumType); } if (VarTemplateDecl *VarTempl = dyn_cast(MemberDecl)) { @@ -1279,7 +1282,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, NNS, TemplateKWLoc, Var, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, VarType.getNonReferenceType(), - VK_LValue, OK_Ordinary, TemplateArgs, ConvertedArgs); + VK_LValue, OK_Ordinary, VarType, TemplateArgs, + ConvertedArgs); } // We found something that we didn't expect. Complain. @@ -1893,12 +1897,13 @@ void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) { ExprResult Sema::BuildFieldReferenceExpr( Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, - const NestedNameSpecifierLoc &NNS, FieldDecl *Field, QualType FieldType, + const NestedNameSpecifierLoc &NNS, FieldDecl *Field, QualType FieldDeclType, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo) { // x.a is an l-value if 'a' has a reference type. Otherwise: // x.a is an l-value/x-value/pr-value if the base is (and note // that *x is always an l-value), except that if the base isn't // an ordinary object then we must have an rvalue. + QualType FieldType = FieldDeclType; ExprValueKind VK = VK_LValue; ExprObjectKind OK = OK_Ordinary; if (!IsArrow) { @@ -1975,7 +1980,7 @@ ExprResult Sema::BuildFieldReferenceExpr( return BuildMemberExpr(Base.get(), IsArrow, OpLoc, NNS, /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, - FieldType, VK, OK); + FieldType, VK, OK, FieldDeclType); } ExprResult diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 934e0d05b4948..f5b582ec42cb6 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -16645,13 +16645,14 @@ Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, } else Base = MemExpr->getBase(); + QualType DeclType = Deduced ? resugar(BasePointeeType, Fn, + Deduced->asArray(), Fn->getType()) + : resugar(BasePointeeType, Fn->getType()); ExprValueKind valueKind; QualType Type; if (cast(Fn)->isStatic()) { valueKind = VK_LValue; - Type = Deduced ? resugar(BasePointeeType, Fn, Deduced->asArray(), - Fn->getType()) - : resugar(BasePointeeType, Fn->getType()); + Type = DeclType; } else { valueKind = VK_PRValue; Type = Context.BoundMemberTy; @@ -16661,7 +16662,7 @@ Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, Base, MemExpr->isArrow(), MemExpr->getOperatorLoc(), MemExpr->getQualifierLoc(), MemExpr->getTemplateKeywordLoc(), Fn, Found, /*HadMultipleCandidates=*/true, MemExpr->getMemberNameInfo(), Type, - valueKind, OK_Ordinary, TemplateArgs, Deduced); + valueKind, OK_Ordinary, DeclType, TemplateArgs, Deduced); } llvm_unreachable("Invalid reference to overloaded function"); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ec4d3a30bbb01..8c0f1b3a2d871 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -948,6 +948,17 @@ QualType Sema::resugar(DeclRefExpr *DRE, ValueDecl *VD) { DRE->setDeclType(NewT); return NewT; } +QualType Sema::resugar(MemberExpr *ME, ValueDecl *VD) { + assert(ME->template_arguments().size() == 0 || ME->getDeduced() != nullptr); + const NestedNameSpecifier *NNS = + ME->getQualifierLoc().getNestedNameSpecifier(); + QualType T = VD->getType(); + QualType NewT = ME->getDeduced() + ? SemaRef.resugar(NNS, VD, ME->getDeduced()->asArray(), T) + : SemaRef.resugar(NNS, T); + ME->setDeclType(NewT); + return NewT; +} /// \brief Determine whether the declaration found is acceptable as the name /// of a template and, if so, return that template declaration. Otherwise, diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c94d706a829c4..fafe1cc093a06 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -9622,7 +9622,7 @@ QualType Sema::getDecltypeForExpr(Expr *E) { if (const auto *ME = dyn_cast(IDExpr)) { if (const auto *VD = ME->getMemberDecl()) if (isa(VD) || isa(VD)) - return VD->getType(); + return ME->getDeclType(); } else if (const auto *IR = dyn_cast(IDExpr)) { return IR->getDecl()->getType(); } else if (const auto *PR = dyn_cast(IDExpr)) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 57f47bd75a745..ec7ea584c03ef 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1064,6 +1064,7 @@ void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { bool HasQualifier = CurrentUnpackingBits->getNextBit(); bool HasFoundDecl = CurrentUnpackingBits->getNextBit(); bool HasTemplateInfo = CurrentUnpackingBits->getNextBit(); + bool HasResugaredDeclType = CurrentUnpackingBits->getNextBit(); unsigned NumTemplateArgs = Record.readInt(); E->Base = Record.readSubExpr(); @@ -1074,6 +1075,7 @@ void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { E->MemberExprBits.HasQualifier = HasQualifier; E->MemberExprBits.HasFoundDecl = HasFoundDecl; E->MemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo; + E->MemberExprBits.HasResugaredDeclType = HasResugaredDeclType; E->MemberExprBits.HadMultipleCandidates = CurrentUnpackingBits->getNextBit(); E->MemberExprBits.NonOdrUseReason = CurrentUnpackingBits->getNextBits(/*Width=*/2); @@ -1094,6 +1096,9 @@ void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { ReadTemplateKWAndArgsInfo( *E->getTrailingObjects(), E->getTrailingObjects(), NumTemplateArgs); + + if (HasResugaredDeclType) + *E->getTrailingObjects() = Record.readQualType(); } void ASTStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) { @@ -3295,9 +3300,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { bool HasQualifier = ExprMemberBits.getNextBit(); bool HasFoundDecl = ExprMemberBits.getNextBit(); bool HasTemplateInfo = ExprMemberBits.getNextBit(); + bool HasResugaredDeclType = ExprMemberBits.getNextBit(); unsigned NumTemplateArgs = Record[ASTStmtReader::NumExprFields + 1]; S = MemberExpr::CreateEmpty(Context, HasQualifier, HasFoundDecl, - HasTemplateInfo, NumTemplateArgs); + HasTemplateInfo, NumTemplateArgs, + HasResugaredDeclType); break; } diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 82ed11d0f0607..561db39252816 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1009,6 +1009,7 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { CurrentPackingBits.addBit(HasQualifier); CurrentPackingBits.addBit(HasFoundDecl); CurrentPackingBits.addBit(HasTemplateInfo); + CurrentPackingBits.addBit(E->HasResugaredDeclType()); Record.push_back(NumTemplateArgs); Record.AddStmt(E->getBase()); @@ -1038,6 +1039,9 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { AddTemplateKWAndArgsInfo(*E->getTrailingObjects(), E->getTrailingObjects()); + if (E->HasResugaredDeclType()) + Record.writeQualType(E->getDeclType()); + Code = serialization::EXPR_MEMBER; } diff --git a/clang/test/Sema/Resugar/resugar-expr.cpp b/clang/test/Sema/Resugar/resugar-expr.cpp index 4b6b82f1b9eaa..db250640a46e2 100644 --- a/clang/test/Sema/Resugar/resugar-expr.cpp +++ b/clang/test/Sema/Resugar/resugar-expr.cpp @@ -50,9 +50,8 @@ template struct A { (); }; -// FIXME: resugar this Z x1 = decltype(A().a){}(); -// expected-error@-1 {{with an rvalue of type 'int'}} +// expected-error@-1 {{with an rvalue of type 'Int' (aka 'int')}} } // namespace t5 namespace t6 {