diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 95a046844a..ff966b005f 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -563,12 +563,30 @@ public: /// \brief Read preprocessed entities into the virtual void ReadPreprocessedEntities(); + /// \brief Abstract interface for reading expressions. + class ExprReader { + public: + virtual Expr *Read(); + }; + + /// \brief Reads a TemplateArgumentLocInfo appropriate for the + /// given TemplateArgument kind. + TemplateArgumentLocInfo + GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, + const RecordData &Record, unsigned &Idx, + ExprReader &ExprRdr); + /// \brief Reads a TemplateArgumentLocInfo appropriate for the /// given TemplateArgument kind. TemplateArgumentLocInfo GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, const RecordData &Record, unsigned &Idx); + /// \brief Reads a TemplateArgumentLoc. + TemplateArgumentLoc ReadTemplateArgumentLoc(const RecordData &Record, + unsigned &Idx, + ExprReader &ExprRdr); + /// \brief Reads a TemplateArgumentLoc. TemplateArgumentLoc ReadTemplateArgumentLoc(const RecordData &Record, unsigned &Idx); @@ -700,6 +718,10 @@ public: /// \brief Read a template name. TemplateName ReadTemplateName(const RecordData &Record, unsigned &Idx); + /// \brief Read a template argument. + TemplateArgument ReadTemplateArgument(const RecordData &Record,unsigned &Idx, + ExprReader &ExprRdr); + /// \brief Read a template argument. TemplateArgument ReadTemplateArgument(const RecordData &Record,unsigned &Idx); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index af6338de98..dffda371b4 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -211,6 +211,9 @@ private: /// file. unsigned NumVisibleDeclContexts; + /// \brief True when we are in Stmts emitting mode. + bool EmittingStmts; + void WriteBlockInfoBlock(); void WriteMetadata(ASTContext &Context, const char *isysroot); void WriteLanguageOptions(const LangOptions &LangOpts); @@ -355,7 +358,12 @@ public: /// type or declaration has been written, call FlushStmts() to write /// the corresponding statements just after the type or /// declaration. - void AddStmt(Stmt *S) { StmtsToEmit.push_back(S); } + void AddStmt(Stmt *S) { + if (EmittingStmts) + WriteSubStmt(S); + else + StmtsToEmit.push_back(S); + } /// \brief Write the given subexpression to the bitstream. void WriteSubStmt(Stmt *S); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 386462443e..5628de3829 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -321,6 +321,18 @@ void PCHValidator::ReadCounter(unsigned Value) { // PCH reader implementation //===----------------------------------------------------------------------===// +// Give ExprReader's VTable a home. +Expr *PCHReader::ExprReader::Read() { return 0; } + +namespace { + class DeclExprReader : public PCHReader::ExprReader { + PCHReader &Reader; + public: + DeclExprReader(PCHReader &reader) : Reader(reader) { } + virtual Expr *Read() { return Reader.ReadDeclExpr(); } + }; +} // anonymous namespace + PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context, const char *isysroot) : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()), @@ -2499,19 +2511,16 @@ QualType PCHReader::GetType(pch::TypeID ID) { TemplateArgumentLocInfo PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, const RecordData &Record, - unsigned &Index) { + unsigned &Index, ExprReader &ExprRdr) { switch (Kind) { case TemplateArgument::Expression: - return ReadDeclExpr(); + return ExprRdr.Read(); case TemplateArgument::Type: return GetTypeSourceInfo(Record, Index); case TemplateArgument::Template: { - SourceLocation - QualStart = SourceLocation::getFromRawEncoding(Record[Index++]), - QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]), - TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]); - return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd), - TemplateNameLoc); + SourceRange QualifierRange = ReadSourceRange(Record, Index); + SourceLocation TemplateNameLoc = ReadSourceLocation(Record, Index); + return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc); } case TemplateArgument::Null: case TemplateArgument::Integral: @@ -2523,11 +2532,32 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, return TemplateArgumentLocInfo(); } +TemplateArgumentLocInfo +PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, + const RecordData &Record, + unsigned &Index) { + DeclExprReader DeclExprReader(*this); + return GetTemplateArgumentLocInfo(Kind, Record, Index, DeclExprReader); +} + +TemplateArgumentLoc +PCHReader::ReadTemplateArgumentLoc(const RecordData &Record, unsigned &Index, + ExprReader &ExprRdr) { + TemplateArgument Arg = ReadTemplateArgument(Record, Index, ExprRdr); + + if (Arg.getKind() == TemplateArgument::Expression) { + if (Record[Index++]) // bool InfoHasSameExpr. + return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr())); + } + return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(Arg.getKind(), + Record, Index, + ExprRdr)); +} + TemplateArgumentLoc PCHReader::ReadTemplateArgumentLoc(const RecordData &Record, unsigned &Index) { - TemplateArgument Arg = ReadTemplateArgument(Record, Index); - return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(Arg.getKind(), - Record, Index)); + DeclExprReader DeclExprReader(*this); + return ReadTemplateArgumentLoc(Record, Index, DeclExprReader); } Decl *PCHReader::GetExternalDecl(uint32_t ID) { @@ -2995,7 +3025,7 @@ PCHReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) { return Context->getDependentTemplateName(NNS, GetIdentifierInfo(Record, Idx)); return Context->getDependentTemplateName(NNS, - (OverloadedOperatorKind)Record[Idx++]); + (OverloadedOperatorKind)Record[Idx++]); } } @@ -3004,7 +3034,8 @@ PCHReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) { } TemplateArgument -PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) { +PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx, + ExprReader &ExprRdr) { switch ((TemplateArgument::ArgKind)Record[Idx++]) { case TemplateArgument::Null: return TemplateArgument(); @@ -3020,13 +3051,13 @@ PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) { case TemplateArgument::Template: return TemplateArgument(ReadTemplateName(Record, Idx)); case TemplateArgument::Expression: - return TemplateArgument(ReadDeclExpr()); + return TemplateArgument(ExprRdr.Read()); case TemplateArgument::Pack: { unsigned NumArgs = Record[Idx++]; llvm::SmallVector Args; Args.reserve(NumArgs); while (NumArgs--) - Args.push_back(ReadTemplateArgument(Record, Idx)); + Args.push_back(ReadTemplateArgument(Record, Idx, ExprRdr)); TemplateArgument TemplArg; TemplArg.setArgumentPack(Args.data(), Args.size(), /*CopyArgs=*/true); return TemplArg; @@ -3037,6 +3068,12 @@ PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) { return TemplateArgument(); } +TemplateArgument +PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) { + DeclExprReader DeclExprReader(*this); + return ReadTemplateArgument(Record, Idx, DeclExprReader); +} + TemplateParameterList * PCHReader::ReadTemplateParameterList(const RecordData &Record, unsigned &Idx) { SourceLocation TemplateLoc = ReadSourceLocation(Record, Idx); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index fa2a4513d1..1cdade5cc1 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -18,6 +18,15 @@ using namespace clang; namespace { + + class StmtStackExprReader : public PCHReader::ExprReader { + llvm::SmallVectorImpl::iterator StmtI; + public: + StmtStackExprReader(const llvm::SmallVectorImpl::iterator &stmtI) + : StmtI(stmtI) { } + virtual Expr *Read() { return cast_or_null(*StmtI++); } + }; + class PCHStmtReader : public StmtVisitor { PCHReader &Reader; const PCHReader::RecordData &Record; @@ -1124,6 +1133,7 @@ unsigned PCHStmtReader::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { unsigned PCHStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ VisitExpr(E); + unsigned NumExprs = 0; unsigned NumTemplateArgs = Record[Idx++]; assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() && @@ -1132,8 +1142,17 @@ PCHStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ TemplateArgumentListInfo ArgInfo; ArgInfo.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx)); ArgInfo.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx)); + + NumExprs = Record[Idx++]; + llvm::SmallVectorImpl::iterator + StartOfExprs = StmtStack.end() - NumExprs; + if (isa(E)) + --StartOfExprs; // UnresolvedMemberExpr contains an Expr; + StmtStackExprReader ExprReader(StartOfExprs); for (unsigned i = 0; i != NumTemplateArgs; ++i) - ArgInfo.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx)); + ArgInfo.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx, + ExprReader)); + E->initializeTemplateArgumentsFrom(ArgInfo); } @@ -1148,7 +1167,7 @@ PCHStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ E->setMember(Reader.ReadDeclarationName(Record, Idx)); E->setMemberLoc(Reader.ReadSourceLocation(Record, Idx)); - return 1; + return NumExprs + 1; } unsigned @@ -1167,6 +1186,7 @@ PCHStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { unsigned PCHStmtReader::VisitOverloadExpr(OverloadExpr *E) { VisitExpr(E); + unsigned NumExprs = 0; unsigned NumTemplateArgs = Record[Idx++]; assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() && @@ -1175,8 +1195,17 @@ unsigned PCHStmtReader::VisitOverloadExpr(OverloadExpr *E) { TemplateArgumentListInfo ArgInfo; ArgInfo.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx)); ArgInfo.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx)); + + NumExprs = Record[Idx++]; + llvm::SmallVectorImpl::iterator + StartOfExprs = StmtStack.end() - NumExprs; + if (isa(E)) + --StartOfExprs; // UnresolvedMemberExpr contains an Expr; + StmtStackExprReader ExprReader(StartOfExprs); for (unsigned i = 0; i != NumTemplateArgs; ++i) - ArgInfo.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx)); + ArgInfo.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx, + ExprReader)); + E->getExplicitTemplateArgs().initializeFrom(ArgInfo); } @@ -1193,25 +1222,25 @@ unsigned PCHStmtReader::VisitOverloadExpr(OverloadExpr *E) { E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); E->setNameLoc(Reader.ReadSourceLocation(Record, Idx)); - return 0; + return NumExprs; } unsigned PCHStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { - VisitOverloadExpr(E); + unsigned NumExprs = VisitOverloadExpr(E); E->setArrow(Record[Idx++]); E->setHasUnresolvedUsing(Record[Idx++]); E->setBase(cast_or_null(StmtStack.back())); E->setBaseType(Reader.GetType(Record[Idx++])); E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx)); - return 1; + return NumExprs + 1; } unsigned PCHStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { - VisitOverloadExpr(E); + unsigned NumExprs = VisitOverloadExpr(E); E->setRequiresADL(Record[Idx++]); E->setOverloaded(Record[Idx++]); E->setNamingClass(cast_or_null(Reader.GetDecl(Record[Idx++]))); - return 0; + return NumExprs; } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index efed0f0a6c..ebaba14e56 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -2057,7 +2057,7 @@ void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream) : Stream(Stream), NextTypeID(pch::NUM_PREDEF_TYPE_IDS), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), - NumVisibleDeclContexts(0) { } + NumVisibleDeclContexts(0), EmittingStmts(false) { } void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, const char *isysroot) { @@ -2302,10 +2302,8 @@ void PCHWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record); break; case TemplateArgument::Template: - Record.push_back( - Arg.getTemplateQualifierRange().getBegin().getRawEncoding()); - Record.push_back(Arg.getTemplateQualifierRange().getEnd().getRawEncoding()); - Record.push_back(Arg.getTemplateNameLoc().getRawEncoding()); + AddSourceRange(Arg.getTemplateQualifierRange(), Record); + AddSourceLocation(Arg.getTemplateNameLoc(), Record); break; case TemplateArgument::Null: case TemplateArgument::Integral: @@ -2318,6 +2316,14 @@ void PCHWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, RecordData &Record) { AddTemplateArgument(Arg.getArgument(), Record); + + if (Arg.getArgument().getKind() == TemplateArgument::Expression) { + bool InfoHasSameExpr + = Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr(); + Record.push_back(InfoHasSameExpr); + if (InfoHasSameExpr) + return; // Avoid storing the same expr twice. + } AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo(), Record); } diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 68b2daed4d..cd58bd0236 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -1025,6 +1025,40 @@ void PCHStmtWriter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { Code = pch::EXPR_CXX_EXPR_WITH_TEMPORARIES; } +/// \brief Return the number of Exprs contained in the given TemplateArgument. +static unsigned NumExprsContainedIn(const TemplateArgument Arg) { + switch (Arg.getKind()) { + default: break; + case TemplateArgument::Expression: + return 1; + case TemplateArgument::Pack: { + unsigned Count = 0; + for (TemplateArgument::pack_iterator I=Arg.pack_begin(), E=Arg.pack_end(); + I != E; ++I) + Count += NumExprsContainedIn(*I); + return Count; + } + } + + return 0; +} + +/// \brief Return the number of Exprs contained in the given +/// TemplateArgumentLoc. +static +unsigned NumExprsContainedIn(const TemplateArgumentLoc *Args,unsigned NumArgs) { + unsigned Count = 0; + for (unsigned i=0; i != NumArgs; ++i) { + const TemplateArgument &TemplA = Args[i].getArgument(); + Count += NumExprsContainedIn(TemplA); + if (TemplA.getKind() == TemplateArgument::Expression && + TemplA.getAsExpr() != Args[i].getLocInfo().getAsExpr()) + ++Count; // 1 in TemplateArgumentLocInfo. + } + + return Count; +} + void PCHStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ VisitExpr(E); @@ -1035,6 +1069,8 @@ PCHStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ Record.push_back(E->getNumTemplateArgs()); Writer.AddSourceLocation(E->getLAngleLoc(), Record); Writer.AddSourceLocation(E->getRAngleLoc(), Record); + Record.push_back(NumExprsContainedIn(E->getTemplateArgs(), + E->getNumTemplateArgs())); for (int i=0, e = E->getNumTemplateArgs(); i != e; ++i) Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record); } else { @@ -1080,6 +1116,8 @@ void PCHStmtWriter::VisitOverloadExpr(OverloadExpr *E) { Record.push_back(Args.NumTemplateArgs); Writer.AddSourceLocation(Args.LAngleLoc, Record); Writer.AddSourceLocation(Args.RAngleLoc, Record); + Record.push_back(NumExprsContainedIn(Args.getTemplateArgs(), + Args.NumTemplateArgs)); for (unsigned i=0; i != Args.NumTemplateArgs; ++i) Writer.AddTemplateArgumentLoc(Args.getTemplateArgs()[i], Record); } else { @@ -1178,6 +1216,8 @@ void PCHWriter::WriteSubStmt(Stmt *S) { void PCHWriter::FlushStmts() { RecordData Record; PCHStmtWriter Writer(*this, Record); + + EmittingStmts = true; for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) { ++NumStatements; @@ -1209,5 +1249,7 @@ void PCHWriter::FlushStmts() { Stream.EmitRecord(pch::STMT_STOP, Record); } + EmittingStmts = false; + StmtsToEmit.clear(); } diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h index 9446b08696..ca4a29fde7 100644 --- a/test/PCH/cxx-templates.h +++ b/test/PCH/cxx-templates.h @@ -15,9 +15,13 @@ struct S { static void explicit_special(); }; +template +int tmpl_f2() { return x; } + template T templ_f(T x) { int z = templ_f(3); + z = tmpl_f2(); return x+y; }