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
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 92df1fd..4e01ec2 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 @@
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);
+}