From dcf17ded66cda437987b5e983f6177cbcc5fa8b6 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 6 Jun 2019 23:24:15 +0000 Subject: [PATCH] Convert MemberExpr creation and serialization to work the same way as most / all other Expr subclasses. This reinstates r362551, reverted in r362597, with a fix to a bug that caused MemberExprs to sometimes have a null FoundDecl after a round-trip through an AST file. llvm-svn: 362756 --- clang/include/clang/AST/Expr.h | 68 +++++++---------- clang/include/clang/AST/Stmt.h | 1 + clang/lib/AST/DeclBase.cpp | 1 + clang/lib/AST/Expr.cpp | 72 +++++++++++++----- clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp | 54 ++++++------- clang/lib/Frontend/Rewrite/RewriteObjC.cpp | 24 +++--- clang/lib/Sema/SemaExprCXX.cpp | 9 ++- clang/lib/Serialization/ASTReaderStmt.cpp | 96 +++++++++++------------- clang/lib/Serialization/ASTWriterStmt.cpp | 56 ++++++++------ clang/test/PCH/cxx-templates.cpp | 9 +++ clang/test/PCH/cxx-templates.h | 9 +++ 11 files changed, 218 insertions(+), 181 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 96cb8e8..438b10c 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2735,6 +2735,7 @@ class MemberExpr final ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { friend class ASTReader; + friend class ASTStmtReader; friend class ASTStmtWriter; friend TrailingObjects; @@ -2769,49 +2770,38 @@ class MemberExpr final return MemberExprBits.HasTemplateKWAndArgsInfo; } + MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, + ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo, + QualType T, ExprValueKind VK, ExprObjectKind OK); + MemberExpr(EmptyShell Empty) + : Expr(MemberExprClass, Empty), Base(), MemberDecl() {} + public: - MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc, - ValueDecl *memberdecl, const DeclarationNameInfo &NameInfo, - QualType ty, ExprValueKind VK, ExprObjectKind OK) - : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), - base->isValueDependent(), base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()), - MemberLoc(NameInfo.getLoc()) { - assert(memberdecl->getDeclName() == NameInfo.getName()); - MemberExprBits.IsArrow = isarrow; - MemberExprBits.HasQualifierOrFoundDecl = false; - MemberExprBits.HasTemplateKWAndArgsInfo = false; - MemberExprBits.HadMultipleCandidates = false; - MemberExprBits.OperatorLoc = operatorloc; - } - - // NOTE: this constructor should be used only when it is known that - // the member name can not provide additional syntactic info - // (i.e., source locations for C++ operator names or type source info - // for constructors, destructors and conversion operators). - MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc, - ValueDecl *memberdecl, SourceLocation l, QualType ty, - ExprValueKind VK, ExprObjectKind OK) - : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), - base->isValueDependent(), base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l) { - MemberExprBits.IsArrow = isarrow; - MemberExprBits.HasQualifierOrFoundDecl = false; - MemberExprBits.HasTemplateKWAndArgsInfo = false; - MemberExprBits.HadMultipleCandidates = false; - MemberExprBits.OperatorLoc = operatorloc; - } - - static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow, + static MemberExpr *Create(const ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *memberdecl, - DeclAccessPair founddecl, + SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, + DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo, - const TemplateArgumentListInfo *targs, QualType ty, - ExprValueKind VK, ExprObjectKind OK); + const TemplateArgumentListInfo *TemplateArgs, + QualType T, ExprValueKind VK, ExprObjectKind OK); + + /// Create an implicit MemberExpr, with no location, qualifier, template + /// arguments, and so on. + static MemberExpr *CreateImplicit(const ASTContext &C, Expr *Base, + bool IsArrow, ValueDecl *MemberDecl, + QualType T, ExprValueKind VK, + ExprObjectKind OK) { + return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(), + SourceLocation(), MemberDecl, + DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()), + DeclarationNameInfo(), nullptr, T, VK, OK); + } + + static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier, + bool HasFoundDecl, + bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs); void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast(Base); } diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index fe5d802..d3b3bc2 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -453,6 +453,7 @@ protected: enum { NumCallExprBits = 32 }; class MemberExprBitfields { + friend class ASTStmtReader; friend class MemberExpr; unsigned : NumExprBits; diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 3198548..f5853b4 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -920,6 +920,7 @@ bool Decl::AccessDeclContextSanity() const { if (isa(this) || isa(this) || isa(this) || + !getDeclContext() || !isa(getDeclContext()) || isInvalidDecl() || isa(this) || diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 10829c7..ee9d853 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1538,29 +1538,44 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr( } } +MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, + ValueDecl *MemberDecl, + const DeclarationNameInfo &NameInfo, QualType T, + ExprValueKind VK, ExprObjectKind OK) + : Expr(MemberExprClass, T, VK, OK, Base->isTypeDependent(), + Base->isValueDependent(), Base->isInstantiationDependent(), + Base->containsUnexpandedParameterPack()), + Base(Base), MemberDecl(MemberDecl), MemberDNLoc(NameInfo.getInfo()), + MemberLoc(NameInfo.getLoc()) { + assert(!NameInfo.getName() || + MemberDecl->getDeclName() == NameInfo.getName()); + MemberExprBits.IsArrow = IsArrow; + MemberExprBits.HasQualifierOrFoundDecl = false; + MemberExprBits.HasTemplateKWAndArgsInfo = false; + MemberExprBits.HadMultipleCandidates = false; + MemberExprBits.OperatorLoc = OperatorLoc; +} + MemberExpr *MemberExpr::Create( - const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc, + const ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, - ValueDecl *memberdecl, DeclAccessPair founddecl, - DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs, - QualType ty, ExprValueKind vk, ExprObjectKind ok) { - - bool hasQualOrFound = (QualifierLoc || - founddecl.getDecl() != memberdecl || - founddecl.getAccess() != memberdecl->getAccess()); - - bool HasTemplateKWAndArgsInfo = targs || TemplateKWLoc.isValid(); + ValueDecl *MemberDecl, DeclAccessPair FoundDecl, + DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs, + QualType T, ExprValueKind VK, ExprObjectKind OK) { + bool HasQualOrFound = QualifierLoc || FoundDecl.getDecl() != MemberDecl || + FoundDecl.getAccess() != MemberDecl->getAccess(); + bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); std::size_t Size = totalSizeToAlloc(hasQualOrFound ? 1 : 0, - HasTemplateKWAndArgsInfo ? 1 : 0, - targs ? targs->size() : 0); + TemplateArgumentLoc>( + HasQualOrFound ? 1 : 0, HasTemplateKWAndArgsInfo ? 1 : 0, + TemplateArgs ? TemplateArgs->size() : 0); void *Mem = C.Allocate(Size, alignof(MemberExpr)); MemberExpr *E = new (Mem) - MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok); + MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, NameInfo, T, VK, OK); - if (hasQualOrFound) { + if (HasQualOrFound) { // FIXME: Wrong. We should be looking at the member declaration we found. if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) { E->setValueDependent(true); @@ -1576,19 +1591,20 @@ MemberExpr *MemberExpr::Create( MemberExprNameQualifier *NQ = E->getTrailingObjects(); NQ->QualifierLoc = QualifierLoc; - NQ->FoundDecl = founddecl; + NQ->FoundDecl = FoundDecl; } E->MemberExprBits.HasTemplateKWAndArgsInfo = - (targs || TemplateKWLoc.isValid()); + TemplateArgs || TemplateKWLoc.isValid(); - if (targs) { + if (TemplateArgs) { bool Dependent = false; bool InstantiationDependent = false; bool ContainsUnexpandedParameterPack = false; E->getTrailingObjects()->initializeFrom( - TemplateKWLoc, *targs, E->getTrailingObjects(), - Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); + TemplateKWLoc, *TemplateArgs, + E->getTrailingObjects(), Dependent, + InstantiationDependent, ContainsUnexpandedParameterPack); if (InstantiationDependent) E->setInstantiationDependent(true); } else if (TemplateKWLoc.isValid()) { @@ -1599,6 +1615,22 @@ MemberExpr *MemberExpr::Create( return E; } +MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context, + bool HasQualifier, bool HasFoundDecl, + bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs) { + assert((!NumTemplateArgs || HasTemplateKWAndArgsInfo) && + "template args but no template arg info?"); + bool HasQualOrFound = HasQualifier || HasFoundDecl; + std::size_t Size = + totalSizeToAlloc(HasQualOrFound ? 1 : 0, + HasTemplateKWAndArgsInfo ? 1 : 0, + NumTemplateArgs); + void *Mem = Context.Allocate(Size, alignof(MemberExpr)); + return new (Mem) MemberExpr(EmptyShell()); +} + SourceLocation MemberExpr::getBeginLoc() const { if (isImplicitAccess()) { if (hasQualifier()) diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 7b1f204..170149d 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -881,9 +881,8 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) { IvarT, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); IvarT = Context->getDecltypeType(ME, ME->getType()); } } @@ -2736,9 +2735,9 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { Context->getPointerType(Context->VoidPtrTy), nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ArrayLiteralME = new (Context) - MemberExpr(NSArrayCallExpr, false, SourceLocation(), ARRFD, - SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ArrayLiteralME = + MemberExpr::CreateImplicit(*Context, NSArrayCallExpr, false, ARRFD, + ARRFD->getType(), VK_LValue, OK_Ordinary); QualType ConstIdT = Context->getObjCIdType().withConst(); CStyleCastExpr * ArrayLiteralObjects = NoTypeInfoCStyleCastExpr(Context, @@ -2865,9 +2864,9 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral Context->getPointerType(Context->VoidPtrTy), nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *DictLiteralValueME = new (Context) - MemberExpr(NSValueCallExpr, false, SourceLocation(), ARRFD, - SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *DictLiteralValueME = + MemberExpr::CreateImplicit(*Context, NSValueCallExpr, false, ARRFD, + ARRFD->getType(), VK_LValue, OK_Ordinary); QualType ConstIdT = Context->getObjCIdType().withConst(); CStyleCastExpr * DictValueObjects = NoTypeInfoCStyleCastExpr(Context, @@ -2878,9 +2877,9 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral Expr *NSKeyCallExpr = CallExpr::Create( *Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, SourceLocation()); - MemberExpr *DictLiteralKeyME = new (Context) - MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD, - SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *DictLiteralKeyME = + MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD, + ARRFD->getType(), VK_LValue, OK_Ordinary); CStyleCastExpr * DictKeyObjects = NoTypeInfoCStyleCastExpr(Context, @@ -3180,9 +3179,8 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla returnType, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(STCE, false, SourceLocation(), FieldD, SourceLocation(), - FieldD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, STCE, false, FieldD, FieldD->getType(), VK_LValue, OK_Ordinary); return ME; } @@ -4629,9 +4627,8 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = - new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, CK_BitCast, ME); @@ -4676,9 +4673,8 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary); StringRef Name = VD->getName(); FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -4686,9 +4682,8 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - ME = - new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(), - DeclRefExp->getType(), VK_LValue, OK_Ordinary); + ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(), + VK_LValue, OK_Ordinary); // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), @@ -7528,9 +7523,8 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { IvarT, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); IvarT = Context->getDecltypeType(ME, ME->getType()); } } @@ -7557,9 +7551,9 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { D->getType(), nullptr, /*BitWidth=*/D->getBitWidth(), /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(PE, /*isArrow*/ false, SourceLocation(), FD, - SourceLocation(), FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = + MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD, + FD->getType(), VK_LValue, OK_Ordinary); Replacement = ME; } diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp index 3e50aff..2ff230df 100644 --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -3793,9 +3793,8 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = - new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, CK_BitCast, ME); @@ -3840,9 +3839,9 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = + MemberExpr::CreateImplicit(*Context, DeclRefExp, isArrow, FD, + FD->getType(), VK_LValue, OK_Ordinary); StringRef Name = VD->getName(); FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -3850,9 +3849,8 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - ME = - new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(), - DeclRefExp->getType(), VK_LValue, OK_Ordinary); + ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(), + VK_LValue, OK_Ordinary); // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), @@ -5830,10 +5828,10 @@ Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { OldRange.getEnd(), castExpr); if (IV->isFreeIvar() && - declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) { - MemberExpr *ME = new (Context) - MemberExpr(PE, true, SourceLocation(), D, IV->getLocation(), - D->getType(), VK_LValue, OK_Ordinary); + declaresSameEntity(CurMethodDef->getClassInterface(), + iFaceDecl->getDecl())) { + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, D, D->getType(), VK_LValue, OK_Ordinary); Replacement = ME; } else { IV->setBase(PE); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 1eb6a71..c42d272 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7189,9 +7189,12 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, } } - MemberExpr *ME = new (Context) MemberExpr( - Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(), - Context.BoundMemberTy, VK_RValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::Create( + Context, Exp.get(), /*IsArrow=*/false, SourceLocation(), + NestedNameSpecifierLoc(), SourceLocation(), Method, + DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()), + DeclarationNameInfo(), /*TemplateArgs=*/nullptr, Context.BoundMemberTy, + VK_RValue, OK_Ordinary); if (HadMultipleCandidates) ME->setHadMultipleCandidates(true); MarkMemberReferenced(ME); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 52aa3d9..b89bb04 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -752,9 +752,46 @@ void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { } void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { - // Don't call VisitExpr, this is fully initialized at creation. - assert(E->getStmtClass() == Stmt::MemberExprClass && - "It's a subclass, we must advance Idx!"); + VisitExpr(E); + + bool HasQualifier = Record.readInt(); + bool HasFoundDecl = Record.readInt(); + bool HasTemplateInfo = Record.readInt(); + unsigned NumTemplateArgs = Record.readInt(); + + E->Base = Record.readSubExpr(); + E->MemberDecl = Record.readDeclAs(); + Record.readDeclarationNameLoc(E->MemberDNLoc, E->MemberDecl->getDeclName()); + E->MemberLoc = Record.readSourceLocation(); + E->MemberExprBits.IsArrow = Record.readInt(); + E->MemberExprBits.HasQualifierOrFoundDecl = HasQualifier || HasFoundDecl; + E->MemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo; + E->MemberExprBits.HadMultipleCandidates = Record.readInt(); + E->MemberExprBits.OperatorLoc = Record.readSourceLocation(); + + if (HasQualifier || HasFoundDecl) { + DeclAccessPair FoundDecl; + if (HasFoundDecl) { + auto *FoundD = Record.readDeclAs(); + auto AS = (AccessSpecifier)Record.readInt(); + FoundDecl = DeclAccessPair::make(FoundD, AS); + } else { + FoundDecl = DeclAccessPair::make(E->MemberDecl, + E->MemberDecl->getAccess()); + } + E->getTrailingObjects()->FoundDecl = FoundDecl; + + NestedNameSpecifierLoc QualifierLoc; + if (HasQualifier) + QualifierLoc = Record.readNestedNameSpecifierLoc(); + E->getTrailingObjects()->QualifierLoc = + QualifierLoc; + } + + if (HasTemplateInfo) + ReadTemplateKWAndArgsInfo( + *E->getTrailingObjects(), + E->getTrailingObjects(), NumTemplateArgs); } void ASTStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) { @@ -2551,55 +2588,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); break; - case EXPR_MEMBER: { - // We load everything here and fully initialize it at creation. - // That way we can use MemberExpr::Create and don't have to duplicate its - // logic with a MemberExpr::CreateEmpty. - - assert(Record.getIdx() == 0); - NestedNameSpecifierLoc QualifierLoc; - if (Record.readInt()) { // HasQualifier. - QualifierLoc = Record.readNestedNameSpecifierLoc(); - } - - SourceLocation TemplateKWLoc; - TemplateArgumentListInfo ArgInfo; - bool HasTemplateKWAndArgsInfo = Record.readInt(); - if (HasTemplateKWAndArgsInfo) { - TemplateKWLoc = Record.readSourceLocation(); - unsigned NumTemplateArgs = Record.readInt(); - ArgInfo.setLAngleLoc(Record.readSourceLocation()); - ArgInfo.setRAngleLoc(Record.readSourceLocation()); - for (unsigned i = 0; i != NumTemplateArgs; ++i) - ArgInfo.addArgument(Record.readTemplateArgumentLoc()); - } - - bool HadMultipleCandidates = Record.readInt(); - - auto *FoundD = Record.readDeclAs(); - auto AS = (AccessSpecifier)Record.readInt(); - DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS); - - QualType T = Record.readType(); - auto VK = static_cast(Record.readInt()); - auto OK = static_cast(Record.readInt()); - Expr *Base = ReadSubExpr(); - auto *MemberD = Record.readDeclAs(); - SourceLocation MemberLoc = Record.readSourceLocation(); - DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc); - bool IsArrow = Record.readInt(); - SourceLocation OperatorLoc = Record.readSourceLocation(); - - S = MemberExpr::Create(Context, Base, IsArrow, OperatorLoc, QualifierLoc, - TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo, - HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, T, - VK, OK); - Record.readDeclarationNameLoc(cast(S)->MemberDNLoc, - MemberD->getDeclName()); - if (HadMultipleCandidates) - cast(S)->setHadMultipleCandidates(true); + case EXPR_MEMBER: + S = MemberExpr::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields], + Record[ASTStmtReader::NumExprFields + 1], + Record[ASTStmtReader::NumExprFields + 2], + Record[ASTStmtReader::NumExprFields + 3]); break; - } case EXPR_BINARY_OPERATOR: S = new (Context) BinaryOperator(Empty); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 776aab6..d52a4a8 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -660,39 +660,45 @@ void ASTStmtWriter::VisitCallExpr(CallExpr *E) { } void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { - // Don't call VisitExpr, we'll write everything here. - - Record.push_back(E->hasQualifier()); - if (E->hasQualifier()) - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - - Record.push_back(E->hasTemplateKWAndArgsInfo()); - if (E->hasTemplateKWAndArgsInfo()) { - Record.AddSourceLocation(E->getTemplateKeywordLoc()); - unsigned NumTemplateArgs = E->getNumTemplateArgs(); - Record.push_back(NumTemplateArgs); - Record.AddSourceLocation(E->getLAngleLoc()); - Record.AddSourceLocation(E->getRAngleLoc()); - for (unsigned i=0; i != NumTemplateArgs; ++i) - Record.AddTemplateArgumentLoc(E->getTemplateArgs()[i]); - } + VisitExpr(E); - Record.push_back(E->hadMultipleCandidates()); + bool HasQualifier = E->hasQualifier(); + bool HasFoundDecl = + E->hasQualifierOrFoundDecl() && + (E->getFoundDecl().getDecl() != E->getMemberDecl() || + E->getFoundDecl().getAccess() != E->getMemberDecl()->getAccess()); + bool HasTemplateInfo = E->hasTemplateKWAndArgsInfo(); + unsigned NumTemplateArgs = E->getNumTemplateArgs(); - DeclAccessPair FoundDecl = E->getFoundDecl(); - Record.AddDeclRef(FoundDecl.getDecl()); - Record.push_back(FoundDecl.getAccess()); + // Write these first for easy access when deserializing, as they affect the + // size of the MemberExpr. + Record.push_back(HasQualifier); + Record.push_back(HasFoundDecl); + Record.push_back(HasTemplateInfo); + Record.push_back(NumTemplateArgs); - Record.AddTypeRef(E->getType()); - Record.push_back(E->getValueKind()); - Record.push_back(E->getObjectKind()); Record.AddStmt(E->getBase()); Record.AddDeclRef(E->getMemberDecl()); + Record.AddDeclarationNameLoc(E->MemberDNLoc, + E->getMemberDecl()->getDeclName()); Record.AddSourceLocation(E->getMemberLoc()); Record.push_back(E->isArrow()); + Record.push_back(E->hadMultipleCandidates()); Record.AddSourceLocation(E->getOperatorLoc()); - Record.AddDeclarationNameLoc(E->MemberDNLoc, - E->getMemberDecl()->getDeclName()); + + if (HasFoundDecl) { + DeclAccessPair FoundDecl = E->getFoundDecl(); + Record.AddDeclRef(FoundDecl.getDecl()); + Record.push_back(FoundDecl.getAccess()); + } + + if (HasQualifier) + Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); + + if (HasTemplateInfo) + AddTemplateKWAndArgsInfo(*E->getTrailingObjects(), + E->getTrailingObjects()); + Code = serialization::EXPR_MEMBER; } diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp index 78898f7..966bd00 100644 --- a/clang/test/PCH/cxx-templates.cpp +++ b/clang/test/PCH/cxx-templates.cpp @@ -156,3 +156,12 @@ namespace ClassScopeExplicitSpecializations { static_assert(A<4>().f<0>() == 2, ""); static_assert(A<4>().f<1>() == 1, ""); } + +namespace DependentMemberExpr { +#ifndef NO_ERRORS + // This used to mark 'f' invalid without producing any diagnostic. That's a + // little hard to detect, but we can make sure that constexpr evaluation + // fails when it should. + static_assert(A().f() == 1); // expected-error {{static_assert failed}} +#endif +} diff --git a/clang/test/PCH/cxx-templates.h b/clang/test/PCH/cxx-templates.h index bfdb3b8..5aa6854 100644 --- a/clang/test/PCH/cxx-templates.h +++ b/clang/test/PCH/cxx-templates.h @@ -439,3 +439,12 @@ namespace ClassScopeExplicitSpecializations { template<> template<> constexpr int B<0>::w = 7; template<> template<> constexpr int B<0>::w = 8; } + +namespace DependentMemberExpr { + struct Base { + constexpr int setstate() { return 0; } + }; + template struct A : Base { + constexpr int f() { return Base::setstate(); } + }; +} -- 2.7.4