diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTDumper.cpp | 3 | ||||
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 19 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 11 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 144 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 9 |
8 files changed, 161 insertions, 54 deletions
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index c95922b141e..0c9c14ba308 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -2017,6 +2017,9 @@ void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { VisitExpr(Node); dumpPointer(Node->getPack()); dumpName(Node->getPack()); + if (Node->isPartiallySubstituted()) + for (const auto &A : Node->getPartialArguments()) + dumpTemplateArgument(A); } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 56f720a9789..0dd36715113 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1432,6 +1432,25 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { return Record; } +SizeOfPackExpr * +SizeOfPackExpr::Create(ASTContext &Context, SourceLocation OperatorLoc, + NamedDecl *Pack, SourceLocation PackLoc, + SourceLocation RParenLoc, + Optional<unsigned> Length, + ArrayRef<TemplateArgument> PartialArgs) { + void *Storage = Context.Allocate( + sizeof(SizeOfPackExpr) + sizeof(TemplateArgument) * PartialArgs.size()); + return new (Storage) SizeOfPackExpr(Context.getSizeType(), OperatorLoc, Pack, + PackLoc, RParenLoc, Length, PartialArgs); +} + +SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context, + unsigned NumPartialArgs) { + void *Storage = Context.Allocate( + sizeof(SizeOfPackExpr) + sizeof(TemplateArgument) * NumPartialArgs); + return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs); +} + SubstNonTypeTemplateParmPackExpr:: SubstNonTypeTemplateParmPackExpr(QualType T, NonTypeTemplateParmDecl *Param, diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 9fafef13f62..64f9ccd9967 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3458,8 +3458,17 @@ recurse: break; case Expr::SizeOfPackExprClass: { + auto *SPE = cast<SizeOfPackExpr>(E); + if (SPE->isPartiallySubstituted()) { + Out << "sP"; + for (const auto &A : SPE->getPartialArguments()) + mangleTemplateArg(A); + Out << "E"; + break; + } + Out << "sZ"; - const NamedDecl *Pack = cast<SizeOfPackExpr>(E)->getPack(); + const NamedDecl *Pack = SPE->getPack(); if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack)) mangleTemplateParameter(TTP->getIndex()); else if (const NonTypeTemplateParmDecl *NTTP diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 231f450c9b4..b379745b4af 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1313,6 +1313,14 @@ void StmtProfiler::VisitPackExpansionExpr(const PackExpansionExpr *S) { void StmtProfiler::VisitSizeOfPackExpr(const SizeOfPackExpr *S) { VisitExpr(S); VisitDecl(S->getPack()); + if (S->isPartiallySubstituted()) { + auto Args = S->getPartialArguments(); + ID.AddInteger(Args.size()); + for (const auto &TA : Args) + VisitTemplateArgument(TA); + } else { + ID.AddInteger(0); + } } void StmtProfiler::VisitSubstNonTypeTemplateParmPackExpr( diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index fd3ba3549b4..a7fef8a29d8 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -867,8 +867,8 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, MarkAnyDeclReferenced(OpLoc, ParameterPack, true); - return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc, - ParameterPack, NameLoc, RParenLoc); + return SizeOfPackExpr::Create(Context, OpLoc, ParameterPack, NameLoc, + RParenLoc); } TemplateArgumentLoc diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 1629138c5b7..820fe65c6c8 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -504,7 +504,8 @@ public: /// /// Returns true if there was an error. bool TransformTemplateArgument(const TemplateArgumentLoc &Input, - TemplateArgumentLoc &Output); + TemplateArgumentLoc &Output, + bool Uneval = false); /// \brief Transform the given set of template arguments. /// @@ -526,8 +527,10 @@ public: /// Returns true if an error occurred. bool TransformTemplateArguments(const TemplateArgumentLoc *Inputs, unsigned NumInputs, - TemplateArgumentListInfo &Outputs) { - return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs); + TemplateArgumentListInfo &Outputs, + bool Uneval = false) { + return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs, + Uneval); } /// \brief Transform the given set of template arguments. @@ -547,7 +550,8 @@ public: template<typename InputIterator> bool TransformTemplateArguments(InputIterator First, InputIterator Last, - TemplateArgumentListInfo &Outputs); + TemplateArgumentListInfo &Outputs, + bool Uneval = false); /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument. void InventTemplateArgumentLoc(const TemplateArgument &Arg, @@ -2615,18 +2619,14 @@ public: } /// \brief Build a new expression to compute the length of a parameter pack. - ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack, + ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, + NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, - Optional<unsigned> Length) { - if (Length) - return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(), - OperatorLoc, Pack, PackLoc, - RParenLoc, *Length); - - return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(), - OperatorLoc, Pack, PackLoc, - RParenLoc); + Optional<unsigned> Length, + ArrayRef<TemplateArgument> PartialArgs) { + return SizeOfPackExpr::Create(SemaRef.Context, OperatorLoc, Pack, PackLoc, + RParenLoc, Length, PartialArgs); } /// \brief Build a new Objective-C boxed expression. @@ -3511,7 +3511,7 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc( template<typename Derived> bool TreeTransform<Derived>::TransformTemplateArgument( const TemplateArgumentLoc &Input, - TemplateArgumentLoc &Output) { + TemplateArgumentLoc &Output, bool Uneval) { const TemplateArgument &Arg = Input.getArgument(); switch (Arg.getKind()) { case TemplateArgument::Null: @@ -3559,8 +3559,8 @@ bool TreeTransform<Derived>::TransformTemplateArgument( case TemplateArgument::Expression: { // Template argument expressions are constant expressions. - EnterExpressionEvaluationContext Unevaluated(getSema(), - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated( + getSema(), Uneval ? Sema::Unevaluated : Sema::ConstantEvaluated); Expr *InputExpr = Input.getSourceExpression(); if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); @@ -3638,9 +3638,9 @@ public: template<typename Derived> template<typename InputIterator> -bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, - InputIterator Last, - TemplateArgumentListInfo &Outputs) { +bool TreeTransform<Derived>::TransformTemplateArguments( + InputIterator First, InputIterator Last, TemplateArgumentListInfo &Outputs, + bool Uneval) { for (; First != Last; ++First) { TemplateArgumentLoc Out; TemplateArgumentLoc In = *First; @@ -3658,7 +3658,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, In.getArgument().pack_begin()), PackLocIterator(*this, In.getArgument().pack_end()), - Outputs)) + Outputs, Uneval)) return true; continue; @@ -3696,7 +3696,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, // expansion. TemplateArgumentLoc OutPattern; Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); - if (getDerived().TransformTemplateArgument(Pattern, OutPattern)) + if (getDerived().TransformTemplateArgument(Pattern, OutPattern, Uneval)) return true; Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis, @@ -3713,7 +3713,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); - if (getDerived().TransformTemplateArgument(Pattern, Out)) + if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval)) return true; if (Out.getArgument().containsUnexpandedParameterPack()) { @@ -3731,7 +3731,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, if (RetainExpansion) { ForgetPartiallySubstitutedPackRAII Forget(getDerived()); - if (getDerived().TransformTemplateArgument(Pattern, Out)) + if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval)) return true; Out = getDerived().RebuildPackExpansion(Out, Ellipsis, @@ -3746,7 +3746,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, } // The simple case: - if (getDerived().TransformTemplateArgument(In, Out)) + if (getDerived().TransformTemplateArgument(In, Out, Uneval)) return true; Outputs.addArgument(Out); @@ -10005,36 +10005,86 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { if (!E->isValueDependent()) return E; - // Note: None of the implementations of TryExpandParameterPacks can ever - // produce a diagnostic when given only a single unexpanded parameter pack, - // so - UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc()); - bool ShouldExpand = false; - bool RetainExpansion = false; - Optional<unsigned> NumExpansions; - if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), - Unexpanded, - ShouldExpand, RetainExpansion, - NumExpansions)) - return ExprError(); + EnterExpressionEvaluationContext Unevaluated(getSema(), Sema::Unevaluated); - if (RetainExpansion) - return E; + ArrayRef<TemplateArgument> PackArgs; + TemplateArgument ArgStorage; + + // Find the argument list to transform. + if (E->isPartiallySubstituted()) { + PackArgs = E->getPartialArguments(); + } else if (E->isValueDependent()) { + UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc()); + bool ShouldExpand = false; + bool RetainExpansion = false; + Optional<unsigned> NumExpansions; + if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), + Unexpanded, + ShouldExpand, RetainExpansion, + NumExpansions)) + return ExprError(); + + // If we need to expand the pack, build a template argument from it and + // expand that. + if (ShouldExpand) { + auto *Pack = E->getPack(); + if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Pack)) { + ArgStorage = getSema().Context.getPackExpansionType( + getSema().Context.getTypeDeclType(TTPD), None); + } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Pack)) { + ArgStorage = TemplateArgument(TemplateName(TTPD), None); + } else { + auto *VD = cast<ValueDecl>(Pack); + ExprResult DRE = getSema().BuildDeclRefExpr(VD, VD->getType(), + VK_RValue, E->getPackLoc()); + if (DRE.isInvalid()) + return ExprError(); + ArgStorage = new (getSema().Context) PackExpansionExpr( + getSema().Context.DependentTy, DRE.get(), E->getPackLoc(), None); + } + PackArgs = ArgStorage; + } + } - NamedDecl *Pack = E->getPack(); - if (!ShouldExpand) { - Pack = cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getPackLoc(), - Pack)); + // If we're not expanding the pack, just transform the decl. + if (!PackArgs.size()) { + auto *Pack = cast_or_null<NamedDecl>( + getDerived().TransformDecl(E->getPackLoc(), E->getPack())); if (!Pack) return ExprError(); + return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), Pack, + E->getPackLoc(), + E->getRParenLoc(), None, None); + } + + TemplateArgumentListInfo TransformedPackArgs(E->getPackLoc(), + E->getPackLoc()); + { + TemporaryBase Rebase(*this, E->getPackLoc(), getBaseEntity()); + typedef TemplateArgumentLocInventIterator< + Derived, const TemplateArgument*> PackLocIterator; + if (TransformTemplateArguments(PackLocIterator(*this, PackArgs.begin()), + PackLocIterator(*this, PackArgs.end()), + TransformedPackArgs, /*Uneval*/true)) + return ExprError(); + } + + SmallVector<TemplateArgument, 8> Args; + bool PartialSubstitution = false; + for (auto &Loc : TransformedPackArgs.arguments()) { + Args.push_back(Loc.getArgument()); + if (Loc.getArgument().isPackExpansion()) + PartialSubstitution = true; } + if (PartialSubstitution) + return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(), + E->getPackLoc(), + E->getRParenLoc(), None, Args); - // We now know the length of the parameter pack, so build a new expression - // that stores that length. - return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), Pack, + return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(), E->getPackLoc(), E->getRParenLoc(), - NumExpansions); + Args.size(), None); } template<typename Derived> diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 1bdd65cdf82..98955f63af2 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1554,11 +1554,20 @@ void ASTStmtReader::VisitPackExpansionExpr(PackExpansionExpr *E) { void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) { VisitExpr(E); + unsigned NumPartialArgs = Record[Idx++]; E->OperatorLoc = ReadSourceLocation(Record, Idx); E->PackLoc = ReadSourceLocation(Record, Idx); E->RParenLoc = ReadSourceLocation(Record, Idx); - E->Length = Record[Idx++]; - E->Pack = ReadDeclAs<NamedDecl>(Record, Idx); + E->Pack = Reader.ReadDeclAs<NamedDecl>(F, Record, Idx); + if (E->isPartiallySubstituted()) { + assert(E->Length == NumPartialArgs); + for (auto *I = reinterpret_cast<TemplateArgument *>(E + 1), + *E = I + NumPartialArgs; + I != E; ++I) + new (I) TemplateArgument(Reader.ReadTemplateArgument(F, Record, Idx)); + } else if (!E->isValueDependent()) { + E->Length = Record[Idx++]; + } } void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( @@ -3114,7 +3123,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_SIZEOF_PACK: - S = new (Context) SizeOfPackExpr(Empty); + S = SizeOfPackExpr::CreateDeserialized( + Context, + /*NumPartialArgs=*/Record[ASTStmtReader::NumExprFields]); break; case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM: diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 41e9f969921..92d21389cbb 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1558,11 +1558,18 @@ void ASTStmtWriter::VisitPackExpansionExpr(PackExpansionExpr *E) { void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { VisitExpr(E); + Record.push_back(E->isPartiallySubstituted() ? E->getPartialArguments().size() + : 0); Writer.AddSourceLocation(E->OperatorLoc, Record); Writer.AddSourceLocation(E->PackLoc, Record); Writer.AddSourceLocation(E->RParenLoc, Record); - Record.push_back(E->Length); Writer.AddDeclRef(E->Pack, Record); + if (E->isPartiallySubstituted()) { + for (const auto &TA : E->getPartialArguments()) + Writer.AddTemplateArgument(TA, Record); + } else if (!E->isValueDependent()) { + Record.push_back(E->getPackLength()); + } Code = serialization::EXPR_SIZEOF_PACK; } |