diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-04 17:33:58 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-04 17:33:58 +0000 |
commit | ee8aff06f6a96214731de17b2cb6df407c6c1820 (patch) | |
tree | b3ceca1e1f5b668c492de0c8ddec937e78b228fa /lib/Sema | |
parent | bb03f5dbc23fb9aa1dfdf6a1dfdb192aa56b6b1c (diff) |
Implement the sizeof...(pack) expression to compute the length of a
parameter pack.
Note that we're missing proper libclang support for the new
SizeOfPackExpr expression node.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122813 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 69 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 39 |
2 files changed, 108 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 92df1fd863..4e01ec2407 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -10,6 +10,7 @@ //===----------------------------------------------------------------------===/ #include "clang/Sema/Sema.h" +#include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" @@ -533,3 +534,71 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { return false; } + +/// \brief Called when an expression computing the size of a parameter pack +/// is parsed. +/// +/// \code +/// template<typename ...Types> struct count { +/// static const unsigned value = sizeof...(Types); +/// }; +/// \endcode +/// +// +/// \param OpLoc The location of the "sizeof" keyword. +/// \param Name The name of the parameter pack whose size will be determined. +/// \param NameLoc The source location of the name of the parameter pack. +/// \param RParenLoc The location of the closing parentheses. +ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, + SourceLocation OpLoc, + IdentifierInfo &Name, + SourceLocation NameLoc, + SourceLocation RParenLoc) { + // C++0x [expr.sizeof]p5: + // The identifier in a sizeof... expression shall name a parameter pack. + + LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName); + LookupName(R, S); + + NamedDecl *ParameterPack = 0; + switch (R.getResultKind()) { + case LookupResult::Found: + ParameterPack = R.getFoundDecl(); + break; + + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + if (DeclarationName CorrectedName = CorrectTypo(R, S, 0, 0, false, + CTC_NoKeywords)) { + // FIXME: Variadic templates function parameter packs. + if (NamedDecl *CorrectedResult = R.getAsSingle<NamedDecl>()) + if (CorrectedResult->isTemplateParameterPack()) { + ParameterPack = CorrectedResult; + Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest) + << &Name << CorrectedName + << FixItHint::CreateReplacement(NameLoc, + CorrectedName.getAsString()); + Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here) + << CorrectedName; + } + } + + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + break; + + case LookupResult::Ambiguous: + DiagnoseAmbiguousLookup(R); + return ExprError(); + } + + // FIXME: Variadic templates function parameter packs. + if (!ParameterPack || !ParameterPack->isTemplateParameterPack()) { + Diag(NameLoc, diag::err_sizeof_pack_no_pack_name) + << &Name; + return ExprError(); + } + + return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc, + ParameterPack, NameLoc, RParenLoc); +} diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index c38902a3e9..27fbf939f9 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1913,6 +1913,16 @@ public: return SemaRef.BuildCXXNoexceptExpr(Range.getBegin(), Arg, Range.getEnd()); } + /// \brief Build a new expression to compute the length of a parameter pack. + ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack, + SourceLocation PackLoc, + SourceLocation RParenLoc, + unsigned Length) { + return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(), + OperatorLoc, Pack, PackLoc, + RParenLoc, Length); + } + /// \brief Build a new Objective-C @encode expression. /// /// By default, performs semantic analysis to build the new expression. @@ -6499,7 +6509,36 @@ TreeTransform<Derived>::TransformPackExpansionExpr(PackExpansionExpr *E) { llvm_unreachable("pack expansion expression in unhandled context"); return ExprError(); } + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { + // If E is not value-dependent, then nothing will change when we transform it. + // Note: This is an instantiation-centric view. + if (!E->isValueDependent()) + return SemaRef.Owned(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; + unsigned NumExpansions = 0; + if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), + &Unexpanded, 1, + ShouldExpand, NumExpansions)) + return ExprError(); + + if (!ShouldExpand) + return SemaRef.Owned(E); + // We now know the length of the parameter pack, so build a new expression + // that stores that length. + return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(), + E->getPackLoc(), E->getRParenLoc(), + NumExpansions); +} + template<typename Derived> ExprResult TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) { |