From 8dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfe Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Thu, 24 Jun 2010 08:57:31 +0000 Subject: [PATCH] Support a couple more C++ Exprs for PCH. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106727 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 1 + include/clang/AST/ExprCXX.h | 26 +++++++++++++ include/clang/Frontend/PCHBitCodes.h | 9 ++++- lib/AST/Expr.cpp | 8 +++- lib/AST/ExprCXX.cpp | 31 +++++++++++++++ lib/Frontend/PCHReader.cpp | 8 ++++ lib/Frontend/PCHReaderStmt.cpp | 58 +++++++++++++++++++++++++++- lib/Frontend/PCHWriter.cpp | 6 ++- lib/Frontend/PCHWriterStmt.cpp | 50 +++++++++++++++++++++++- test/PCH/cxx-templates.cpp | 15 ++++++- test/PCH/cxx-templates.h | 15 +++++++ 11 files changed, 216 insertions(+), 11 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 912894ee80..23a5cc47f7 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -414,6 +414,7 @@ struct ExplicitTemplateArgumentList { void initializeFrom(const TemplateArgumentListInfo &List); void copyInto(TemplateArgumentListInfo &List) const; + static std::size_t sizeFor(unsigned NumTemplateArgs); static std::size_t sizeFor(const TemplateArgumentListInfo &List); }; diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index c7f4ff6288..7b0e9e4f34 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1800,6 +1800,9 @@ class CXXUnresolvedConstructExpr : public Expr { unsigned NumArgs, SourceLocation RParenLoc); + CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) + : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) { } + public: static CXXUnresolvedConstructExpr *Create(ASTContext &C, SourceLocation TyBegin, @@ -1809,6 +1812,9 @@ public: unsigned NumArgs, SourceLocation RParenLoc); + static CXXUnresolvedConstructExpr *CreateEmpty(ASTContext &C, + unsigned NumArgs); + /// \brief Retrieve the source location where the type begins. SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } @@ -1853,6 +1859,11 @@ public: return *(arg_begin() + I); } + void setArg(unsigned I, Expr *E) { + assert(I < NumArgs && "Argument index out-of-range"); + *(arg_begin() + I) = E; + } + virtual SourceRange getSourceRange() const { return SourceRange(TyBeginLoc, RParenLoc); } @@ -1968,6 +1979,9 @@ public: SourceLocation MemberLoc, const TemplateArgumentListInfo *TemplateArgs); + static CXXDependentScopeMemberExpr * + CreateEmpty(ASTContext &C, unsigned NumTemplateArgs); + /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source /// location of the operator is invalid in this case. @@ -1982,6 +1996,7 @@ public: void setBase(Expr *E) { Base = E; } QualType getBaseType() const { return BaseType; } + void setBaseType(QualType T) { BaseType = T; } /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. @@ -1995,10 +2010,12 @@ public: /// \brief Retrieve the nested-name-specifier that qualifies the member /// name. NestedNameSpecifier *getQualifier() const { return Qualifier; } + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } /// \brief Retrieve the source range covering the nested-name-specifier /// that qualifies the member name. SourceRange getQualifierRange() const { return QualifierRange; } + void setQualifierRange(SourceRange R) { QualifierRange = R; } /// \brief Retrieve the first part of the nested-name-specifier that was /// found in the scope of the member access expression when the member access @@ -2014,6 +2031,9 @@ public: NamedDecl *getFirstQualifierFoundInScope() const { return FirstQualifierFoundInScope; } + void setFirstQualifierFoundInScope(NamedDecl *D) { + FirstQualifierFoundInScope = D; + } /// \brief Retrieve the name of the member that this expression /// refers to. @@ -2038,6 +2058,12 @@ public: getExplicitTemplateArgumentList()->copyInto(List); } + /// \brief Initializes the template arguments using the given structure. + void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) { + assert(HasExplicitTemplateArgs); + getExplicitTemplateArgumentList()->initializeFrom(List); + } + /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index b95d0d99ae..3c61ebadb9 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -421,7 +421,9 @@ namespace clang { /// \brief An TemplateTypeParmType record. TYPE_TEMPLATE_TYPE_PARM = 29, /// \brief An TemplateSpecializationType record. - TYPE_TEMPLATE_SPECIALIZATION = 30 + TYPE_TEMPLATE_SPECIALIZATION = 30, + /// \brief An DependentNameType record. + TYPE_DEPENDENT_NAME = 31 }; /// \brief The type IDs for special types constructed by semantic @@ -765,7 +767,10 @@ namespace clang { EXPR_CXX_NEW, // CXXNewExpr EXPR_CXX_DELETE, // CXXDeleteExpr - EXPR_CXX_EXPR_WITH_TEMPORARIES // CXXExprWithTemporaries + EXPR_CXX_EXPR_WITH_TEMPORARIES, // CXXExprWithTemporaries + + EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr + EXPR_CXX_UNRESOLVED_CONSTRUCT // CXXUnresolvedConstructExpr }; /// \brief The kinds of designators that can occur in a diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index e36ae41ce4..85af3cc508 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -113,10 +113,14 @@ void ExplicitTemplateArgumentList::copyInto( Info.addArgument(getTemplateArgs()[I]); } +std::size_t ExplicitTemplateArgumentList::sizeFor(unsigned NumTemplateArgs) { + return sizeof(ExplicitTemplateArgumentList) + + sizeof(TemplateArgumentLoc) * NumTemplateArgs; +} + std::size_t ExplicitTemplateArgumentList::sizeFor( const TemplateArgumentListInfo &Info) { - return sizeof(ExplicitTemplateArgumentList) + - sizeof(TemplateArgumentLoc) * Info.size(); + return sizeFor(Info.size()); } void DeclRefExpr::computeDependence() { diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index d1a2b261f2..4d6d712f43 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -656,6 +656,14 @@ CXXUnresolvedConstructExpr::Create(ASTContext &C, Args, NumArgs, RParenLoc); } +CXXUnresolvedConstructExpr * +CXXUnresolvedConstructExpr::CreateEmpty(ASTContext &C, unsigned NumArgs) { + Stmt::EmptyShell Empty; + void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) + + sizeof(Expr *) * NumArgs); + return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs); +} + Stmt::child_iterator CXXUnresolvedConstructExpr::child_begin() { return child_iterator(reinterpret_cast(this + 1)); } @@ -714,6 +722,29 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, Member, MemberLoc, TemplateArgs); } +CXXDependentScopeMemberExpr * +CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, + unsigned NumTemplateArgs) { + if (NumTemplateArgs == 0) + return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(), + 0, SourceLocation(), 0, + SourceRange(), 0, + DeclarationName(), + SourceLocation()); + + std::size_t size = sizeof(CXXDependentScopeMemberExpr) + + ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + void *Mem = C.Allocate(size, llvm::alignof()); + CXXDependentScopeMemberExpr *E + = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(), + 0, SourceLocation(), 0, + SourceRange(), 0, + DeclarationName(), + SourceLocation(), 0); + E->HasExplicitTemplateArgs = true; + return E; +} + Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() { return child_iterator(&Base); } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 1f40781377..498e804cc6 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2216,6 +2216,14 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { IdentifierInfo *Name = GetIdentifierInfo(Record, Idx); return Context->getTemplateTypeParmType(Depth, Index, Pack, Name); } + + case pch::TYPE_DEPENDENT_NAME: { + unsigned Idx = 0; + ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; + NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); + const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx); + return Context->getDependentNameType(Keyword, NNS, Name, QualType()); + } case pch::TYPE_TEMPLATE_SPECIALIZATION: { unsigned Idx = 0; diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index 652fdb1cf2..9c2ae6dfdf 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -137,6 +137,9 @@ namespace { unsigned VisitCXXDeleteExpr(CXXDeleteExpr *E); unsigned VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E); + + unsigned VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); + unsigned VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E); }; } @@ -1114,6 +1117,50 @@ unsigned PCHStmtReader::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { return 1; } +unsigned +PCHStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ + VisitExpr(E); + + unsigned NumTemplateArgs = Record[Idx++]; + assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() && + "Read wrong record during creation ?"); + if (E->hasExplicitTemplateArgs()) { + TemplateArgumentListInfo ArgInfo; + ArgInfo.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx)); + ArgInfo.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx)); + for (unsigned i = 0; i != NumTemplateArgs; ++i) + ArgInfo.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx)); + E->initializeTemplateArgumentsFrom(ArgInfo); + } + + E->setBase(cast_or_null(StmtStack.back())); + E->setBaseType(Reader.GetType(Record[Idx++])); + E->setArrow(Record[Idx++]); + E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx)); + E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); + E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); + E->setFirstQualifierFoundInScope( + cast_or_null(Reader.GetDecl(Record[Idx++]))); + E->setMember(Reader.ReadDeclarationName(Record, Idx)); + E->setMemberLoc(Reader.ReadSourceLocation(Record, Idx)); + + return 1; +} + +unsigned +PCHStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { + VisitExpr(E); + assert(Record[Idx] == E->arg_size() && "Read wrong record during creation ?"); + ++Idx; // NumArgs; + for (unsigned I = 0, N = E->arg_size(); I != N; ++I) + E->setArg(I, cast(StmtStack[StmtStack.size() - N + I])); + E->setTypeBeginLoc(Reader.ReadSourceLocation(Record, Idx)); + E->setTypeAsWritten(Reader.GetType(Record[Idx++])); + E->setLParenLoc(Reader.ReadSourceLocation(Record, Idx)); + E->setRParenLoc(Reader.ReadSourceLocation(Record, Idx)); + return E->arg_size(); +} + // Within the bitstream, expressions are stored in Reverse Polish // Notation, with each of the subexpressions preceding the @@ -1493,10 +1540,19 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { S = new (Context) CXXDeleteExpr(Empty); break; - case pch::EXPR_CXX_EXPR_WITH_TEMPORARIES: S = new (Context) CXXExprWithTemporaries(Empty); break; + + case pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER: + S = CXXDependentScopeMemberExpr::CreateEmpty(*Context, + Record[PCHStmtReader::NumExprFields]); + break; + + case pch::EXPR_CXX_UNRESOLVED_CONSTRUCT: + S = CXXUnresolvedConstructExpr::CreateEmpty(*Context, + Record[PCHStmtReader::NumExprFields]); + 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 77356ccd10..21ea5fcdc8 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -252,8 +252,10 @@ PCHTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { void PCHTypeWriter::VisitDependentNameType(const DependentNameType *T) { - // FIXME: Serialize this type (C++ only) - assert(false && "Cannot serialize dependent name types"); + Record.push_back(T->getKeyword()); + Writer.AddNestedNameSpecifier(T->getQualifier(), Record); + Writer.AddIdentifierRef(T->getIdentifier(), Record); + Code = pch::TYPE_DEPENDENT_NAME; } void diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 80ee6a2ff8..66e1529ac6 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -127,12 +127,14 @@ namespace { void VisitCXXThrowExpr(CXXThrowExpr *E); void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); - + void VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E); void VisitCXXNewExpr(CXXNewExpr *E); void VisitCXXDeleteExpr(CXXDeleteExpr *E); - + void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E); + void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); + void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E); }; } @@ -1019,6 +1021,50 @@ void PCHStmtWriter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { Code = pch::EXPR_CXX_EXPR_WITH_TEMPORARIES; } +void +PCHStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ + VisitExpr(E); + + if (E->hasExplicitTemplateArgs()) { + assert(E->getNumTemplateArgs() && + "Num of template args was zero! PCH reading will mess up!"); + Record.push_back(E->getNumTemplateArgs()); + Writer.AddSourceLocation(E->getLAngleLoc(), Record); + Writer.AddSourceLocation(E->getRAngleLoc(), Record); + for (int i=0, e = E->getNumTemplateArgs(); i != e; ++i) + Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record); + } else { + Record.push_back(0); + } + + if (!E->isImplicitAccess()) + Writer.WriteSubStmt(E->getBase()); + else + Writer.WriteSubStmt(0); + Writer.AddTypeRef(E->getBaseType(), Record); + Record.push_back(E->isArrow()); + Writer.AddSourceLocation(E->getOperatorLoc(), Record); + Writer.AddNestedNameSpecifier(E->getQualifier(), Record); + Writer.AddSourceRange(E->getQualifierRange(), Record); + Writer.AddDeclRef(E->getFirstQualifierFoundInScope(), Record); + Writer.AddDeclarationName(E->getMember(), Record); + Writer.AddSourceLocation(E->getMemberLoc(), Record); + Code = pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER; +} + +void +PCHStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { + VisitExpr(E); + Record.push_back(E->arg_size()); + for (CXXUnresolvedConstructExpr::arg_iterator + ArgI = E->arg_begin(), ArgE = E->arg_end(); ArgI != ArgE; ++ArgI) + Writer.WriteSubStmt(*ArgI); + Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); + Writer.AddTypeRef(E->getTypeAsWritten(), Record); + Writer.AddSourceLocation(E->getLParenLoc(), Record); + Writer.AddSourceLocation(E->getRParenLoc(), Record); + Code = pch::EXPR_CXX_UNRESOLVED_CONSTRUCT; +} //===----------------------------------------------------------------------===// // PCHWriter Implementation diff --git a/test/PCH/cxx-templates.cpp b/test/PCH/cxx-templates.cpp index b068fa25b1..cfddde52b3 100644 --- a/test/PCH/cxx-templates.cpp +++ b/test/PCH/cxx-templates.cpp @@ -1,9 +1,16 @@ // Test this without pch. -// RUN: %clang_cc1 -include %S/cxx-templates.h -fsyntax-only -verify %s +// RUN: %clang_cc1 -include %S/cxx-templates.h -verify %s -ast-dump // Test with pch. // RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-templates.h -// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s +// RUN: %clang_cc1 -include-pch %t -verify %s -ast-dump + +struct A { + typedef int type; + static void my_f(); + template + static T my_templf(T x) { return x; } +}; void test() { int x = templ_f(3); @@ -11,4 +18,8 @@ void test() { S::templ(); S::partial(); S::explicit_special(); + + Dep::Ty ty; + Dep a; + a.f(); } diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h index c7dc7e8c7a..39c5591390 100644 --- a/test/PCH/cxx-templates.h +++ b/test/PCH/cxx-templates.h @@ -19,3 +19,18 @@ template T templ_f(T x) { return x; } + +template +struct Dep { + typedef typename T::type Ty; + void f() { + Ty x = Ty(); + T::my_f(); + int y = T::template my_templf(0); + } +}; + +template +inline T make_a(const A1& a1) { + return T(a1); +} -- 2.40.0