From: Chris Lattner Date: Mon, 10 May 2010 00:25:06 +0000 (+0000) Subject: pchify CXXTemporary, CXXBindTemporaryExpr, and X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d2598368876cfe40bc8465540033bc5b5e58d8af;p=clang pchify CXXTemporary, CXXBindTemporaryExpr, and CXXExprWithTemporaries. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103387 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 1ae16c3eb8..58603ebbfb 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -580,11 +580,15 @@ protected: virtual void DoDestroy(ASTContext &C); public: + CXXBindTemporaryExpr(EmptyShell Empty) + : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {} + static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp, Expr* SubExpr); CXXTemporary *getTemporary() { return Temp; } const CXXTemporary *getTemporary() const { return Temp; } + void setTemporary(CXXTemporary *T) { Temp = T; } const Expr *getSubExpr() const { return cast(SubExpr); } Expr *getSubExpr() { return cast(SubExpr); } @@ -611,8 +615,8 @@ public: /// const int &i = 10; /// /// a bind reference expression is inserted to indicate that 10 is bound to -/// a reference. (Ans also that a temporary needs to be created to hold the -/// value). +/// a reference, and that a temporary needs to be created to hold the +/// value. class CXXBindReferenceExpr : public Expr { // SubExpr - The expression being bound. Stmt *SubExpr; @@ -1658,11 +1662,17 @@ protected: virtual void DoDestroy(ASTContext &C); public: + CXXExprWithTemporaries(EmptyShell Empty) + : Expr(CXXExprWithTemporariesClass, Empty), + SubExpr(0), Temps(0), NumTemps(0) {} + static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); unsigned getNumTemporaries() const { return NumTemps; } + void setNumTemporaries(unsigned N); + CXXTemporary *getTemporary(unsigned i) { assert(i < NumTemps && "Index out of range"); return Temps[i]; @@ -1670,6 +1680,10 @@ public: const CXXTemporary *getTemporary(unsigned i) const { return const_cast(this)->getTemporary(i); } + void setTemporary(unsigned i, CXXTemporary *T) { + assert(i < NumTemps && "Index out of range"); + Temps[i] = T; + } Expr *getSubExpr() { return cast(SubExpr); } const Expr *getSubExpr() const { return cast(SubExpr); } diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index c217a75a3b..57823ff810 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -751,7 +751,10 @@ namespace clang { EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type). EXPR_CXX_THIS, // CXXThisExpr EXPR_CXX_THROW, // CXXThrowExpr - EXPR_CXX_DEFAULT_ARG // CXXDefaultArgExpr + EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr + EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr + + EXPR_CXX_EXPR_WITH_TEMPORARIES // CXXExprWithTemporaries }; /// \brief The kinds of designators that can occur in a diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index cac3398b96..e144738236 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -652,8 +652,8 @@ public: /// declarations with this name are visible from translation unit scope, their /// declarations will be deserialized and introduced into the declaration /// chain of the identifier. - virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd); - IdentifierInfo* get(llvm::StringRef Name) { + virtual IdentifierInfo *get(const char *NameStart, const char *NameEnd); + IdentifierInfo *get(llvm::StringRef Name) { return get(Name.begin(), Name.end()); } @@ -724,6 +724,8 @@ public: // \brief Read a string std::string ReadString(const RecordData &Record, unsigned &Idx); + CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx); + /// \brief Reads attributes from the current stream position. Attr *ReadAttributes(); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 24025c9feb..85f53b9e03 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -256,7 +256,7 @@ public: /// \brief Emit a source range. void AddSourceRange(SourceRange Range, RecordData &Record); - + /// \brief Emit an integral value. void AddAPInt(const llvm::APInt &Value, RecordData &Record); @@ -266,12 +266,15 @@ public: /// \brief Emit a floating-point value. void AddAPFloat(const llvm::APFloat &Value, RecordData &Record); - /// \brief Emit a reference to an identifier + /// \brief Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record); - /// \brief Emit a Selector (which is a smart pointer reference) - void AddSelectorRef(const Selector, RecordData &Record); + /// \brief Emit a Selector (which is a smart pointer reference). + void AddSelectorRef(Selector, RecordData &Record); + /// \brief Emit a CXXTemporary. + void AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record); + /// \brief Get the unique number used to refer to the given /// identifier. pch::IdentID getIdentifierRef(const IdentifierInfo *II); diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 2e03beb0f0..5eef5591d6 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -520,16 +520,24 @@ void CXXConstructExpr::DoDestroy(ASTContext &C) { CXXExprWithTemporaries::CXXExprWithTemporaries(Expr *subexpr, CXXTemporary **temps, unsigned numtemps) -: Expr(CXXExprWithTemporariesClass, subexpr->getType(), + : Expr(CXXExprWithTemporariesClass, subexpr->getType(), subexpr->isTypeDependent(), subexpr->isValueDependent()), - SubExpr(subexpr), Temps(0), NumTemps(numtemps) { - if (NumTemps > 0) { - Temps = new CXXTemporary*[NumTemps]; - for (unsigned i = 0; i < NumTemps; ++i) + SubExpr(subexpr), Temps(0), NumTemps(0) { + if (NumTemps) { + setNumTemporaries(numtemps); + for (unsigned i = 0; i != numtemps; ++i) Temps[i] = temps[i]; } } +void CXXExprWithTemporaries::setNumTemporaries(unsigned N) { + assert(Temps == 0 && "Cannot resize with this"); + // FIXME: This is a memory leak in disable free mode. + Temps = new CXXTemporary*[NumTemps]; + NumTemps = N; +} + + CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, @@ -544,6 +552,7 @@ void CXXExprWithTemporaries::DoDestroy(ASTContext &C) { } CXXExprWithTemporaries::~CXXExprWithTemporaries() { + // FIXME: This is a memory leak in disable free mode. delete[] Temps; } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 8bc3b18bab..6e4e28eed1 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2974,6 +2974,12 @@ std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) { return Result; } +CXXTemporary *PCHReader::ReadCXXTemporary(const RecordData &Record, + unsigned &Idx) { + CXXDestructorDecl *Decl = cast(GetDecl(Record[Idx++])); + return CXXTemporary::Create(*Context, Decl); +} + DiagnosticBuilder PCHReader::Diag(unsigned DiagID) { return Diag(SourceLocation(), DiagID); } diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index 3392c04d55..fa3c681d90 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -130,6 +130,9 @@ namespace { unsigned VisitCXXThisExpr(CXXThisExpr *E); unsigned VisitCXXThrowExpr(CXXThrowExpr *E); unsigned VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); + unsigned VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); + + unsigned VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E); }; } @@ -1028,7 +1031,27 @@ unsigned PCHStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { bool HasStoredExpr = Record[Idx++]; if (!HasStoredExpr) return 0; E->setExpr(cast(StmtStack.back())); - return 1; // Read it. + return 1; +} + +unsigned PCHStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + VisitExpr(E); + E->setTemporary(Reader.ReadCXXTemporary(Record, Idx)); + E->setSubExpr(cast(StmtStack.back())); + return 1; +} + + +unsigned PCHStmtReader::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { + VisitExpr(E); + unsigned NumTemps = Record[Idx++]; + if (NumTemps) { + E->setNumTemporaries(NumTemps); + for (unsigned i = 0; i != NumTemps; ++i) + E->setTemporary(i, Reader.ReadCXXTemporary(Record, Idx)); + } + E->setSubExpr(cast(StmtStack.back())); + return 1; } @@ -1396,6 +1419,13 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { case pch::EXPR_CXX_DEFAULT_ARG: S = new (Context) CXXDefaultArgExpr(Empty); break; + case pch::EXPR_CXX_BIND_TEMPORARY: + S = new (Context) CXXBindTemporaryExpr(Empty); + break; + + case pch::EXPR_CXX_EXPR_WITH_TEMPORARIES: + S = new (Context) CXXExprWithTemporaries(Empty); + break; } // We hit a STMT_STOP, so we're done with this expression. diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 225772b30d..dc1fb23ac0 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -2241,6 +2241,10 @@ void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) { Record.push_back(SID); } +void PCHWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record) { + AddDeclRef(Temp->getDestructor(), Record); +} + void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, RecordData &Record) { switch (Arg.getArgument().getKind()) { diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index e64ebbe8a3..8c566d00fb 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -126,6 +126,9 @@ namespace { void VisitCXXThisExpr(CXXThisExpr *E); void VisitCXXThrowExpr(CXXThrowExpr *E); void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); + void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); + + void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E); }; } @@ -954,6 +957,23 @@ void PCHStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { Code = pch::EXPR_CXX_DEFAULT_ARG; } +void PCHStmtWriter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + VisitExpr(E); + Writer.AddCXXTemporary(E->getTemporary(), Record); + Writer.WriteSubStmt(E->getSubExpr()); + Code = pch::EXPR_CXX_BIND_TEMPORARY; +} + +void PCHStmtWriter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { + VisitExpr(E); + Record.push_back(E->getNumTemporaries()); + for (unsigned i = 0, e = E->getNumTemporaries(); i != e; ++i) + Writer.AddCXXTemporary(E->getTemporary(i), Record); + + Writer.WriteSubStmt(E->getSubExpr()); + Code = pch::EXPR_CXX_EXPR_WITH_TEMPORARIES; +} + //===----------------------------------------------------------------------===// // PCHWriter Implementation @@ -1021,8 +1041,12 @@ void PCHWriter::FlushStmts() { Writer.Code = pch::STMT_NULL_PTR; Writer.Visit(S); - assert(Writer.Code != pch::STMT_NULL_PTR && - "Unhandled expression writing PCH file"); +#ifndef NDEBUG + if (Writer.Code == pch::STMT_NULL_PTR) { + S->dump(); + assert(0 && "Unhandled expression writing PCH file"); + } +#endif Stream.EmitRecord(Writer.Code, Record); assert(N == StmtsToEmit.size() && diff --git a/test/PCH/cxx_exprs.h b/test/PCH/cxx_exprs.h index 60ac263715..6cc83f4585 100644 --- a/test/PCH/cxx_exprs.h +++ b/test/PCH/cxx_exprs.h @@ -5,7 +5,7 @@ typedef __typeof__(static_cast(0)) static_cast_result; // CXXDynamicCastExpr -struct Base { virtual void f(int x = 492); }; +struct Base { virtual void f(int x = 492); ~Base(); }; struct Derived : Base { void g(); }; Base *base_ptr; typedef __typeof__(dynamic_cast(base_ptr)) dynamic_cast_result; @@ -44,6 +44,8 @@ namespace std { typedef __typeof__(typeid(int))* typeid_result1; typedef __typeof__(typeid(2))* typeid_result2; +Derived foo(); + void Derived::g() { // CXXThisExpr f(2); // Implicit @@ -55,4 +57,9 @@ void Derived::g() { // CXXDefaultArgExpr f(); + + const Derived &X = foo(); + + + // FIXME: CXXBindReferenceExpr ? } \ No newline at end of file