diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ExprCXX.cpp | 12 | ||||
-rw-r--r-- | lib/AST/ExprClassification.cpp | 1 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 10 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 6 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 5 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 42 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 69 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 39 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 14 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 11 |
10 files changed, 207 insertions, 2 deletions
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 4592e5f571..fcedb8e7bb 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -1037,3 +1037,15 @@ Stmt::child_iterator PackExpansionExpr::child_begin() { Stmt::child_iterator PackExpansionExpr::child_end() { return child_iterator(&Pattern + 1); } + +SourceRange SizeOfPackExpr::getSourceRange() const { + return SourceRange(OperatorLoc, RParenLoc); +} + +Stmt::child_iterator SizeOfPackExpr::child_begin() { + return child_iterator(); +} + +Stmt::child_iterator SizeOfPackExpr::child_end() { + return child_iterator(); +} diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index f437804c29..a9ebe6fdb3 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -151,6 +151,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ObjCStringLiteralClass: case Expr::ParenListExprClass: case Expr::InitListExprClass: + case Expr::SizeOfPackExprClass: return Cl::CL_PRValue; // Next come the complicated cases. diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index c39b3983d3..23a4b09cb3 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -291,6 +291,8 @@ public: if (Visit(E->getInit(i))) return true; return false; } + + bool VisitSizeOfPackExpr(SizeOfPackExpr *) { return false; } }; } // end anonymous namespace @@ -965,7 +967,8 @@ public: bool VisitUnaryImag(const UnaryOperator *E); bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); - + bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); + private: CharUnits GetAlignOfExpr(const Expr *E); CharUnits GetAlignOfType(QualType T); @@ -1761,6 +1764,10 @@ bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { return Success(0, E); } +bool IntExprEvaluator::VisitSizeOfPackExpr(const SizeOfPackExpr *E) { + return Success(E->getPackLength(), E); +} + bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { return Success(E->getValue(), E); } @@ -2637,6 +2644,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::PackExpansionExprClass: return ICEDiag(2, E->getLocStart()); + case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: // GCC considers the GNU __null value to be an integral constant expression. return NoDiag(); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index cc90526736..2c8504357e 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1246,11 +1246,15 @@ void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { OS << ")"; } -void StmtPrinter::VisitPackExpansionExpr(clang::PackExpansionExpr *E) { +void StmtPrinter::VisitPackExpansionExpr(PackExpansionExpr *E) { PrintExpr(E->getPattern()); OS << "..."; } +void StmtPrinter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { + OS << "sizeof...(" << E->getPack()->getNameAsString() << ")"; +} + // Obj-C void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 820eb06416..ab24a69124 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -836,6 +836,11 @@ void StmtProfiler::VisitPackExpansionExpr(PackExpansionExpr *S) { VisitExpr(S); } +void StmtProfiler::VisitSizeOfPackExpr(SizeOfPackExpr *S) { + VisitExpr(S); + VisitDecl(S->getPack()); +} + void StmtProfiler::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index be5c7d7808..7133b61022 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -444,6 +444,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// unary-operator cast-expression /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' +/// [C++0x] 'sizeof' '...' '(' identifier ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' /// [C++0x] 'alignof' '(' type-id ')' @@ -1291,6 +1292,7 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' +/// [C++0x] 'sizeof' '...' '(' identifier ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' /// [C++0x] 'alignof' '(' type-id ')' @@ -1301,6 +1303,46 @@ ExprResult Parser::ParseSizeofAlignofExpression() { Token OpTok = Tok; ConsumeToken(); + // [C++0x] 'sizeof' '...' '(' identifier ')' + if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) { + SourceLocation EllipsisLoc = ConsumeToken(); + SourceLocation LParenLoc, RParenLoc; + IdentifierInfo *Name = 0; + SourceLocation NameLoc; + if (Tok.is(tok::l_paren)) { + LParenLoc = ConsumeParen(); + if (Tok.is(tok::identifier)) { + Name = Tok.getIdentifierInfo(); + NameLoc = ConsumeToken(); + RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + if (RParenLoc.isInvalid()) + RParenLoc = PP.getLocForEndOfToken(NameLoc); + } else { + Diag(Tok, diag::err_expected_parameter_pack); + SkipUntil(tok::r_paren); + } + } else if (Tok.is(tok::identifier)) { + Name = Tok.getIdentifierInfo(); + NameLoc = ConsumeToken(); + LParenLoc = PP.getLocForEndOfToken(EllipsisLoc); + RParenLoc = PP.getLocForEndOfToken(NameLoc); + Diag(LParenLoc, diag::err_paren_sizeof_parameter_pack) + << Name + << FixItHint::CreateInsertion(LParenLoc, "(") + << FixItHint::CreateInsertion(RParenLoc, ")"); + } else { + Diag(Tok, diag::err_sizeof_parameter_pack); + } + + if (!Name) + return ExprError(); + + return Actions.ActOnSizeofParameterPackExpr(getCurScope(), + OpTok.getLocation(), + *Name, NameLoc, + RParenLoc); + } + bool isCastExpr; ParsedType CastTy; SourceRange CastRange; 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) { diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 4703c633fb..5ed6f8e4d5 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -177,6 +177,7 @@ namespace clang { void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E); void VisitCXXNoexceptExpr(CXXNoexceptExpr *E); void VisitPackExpansionExpr(PackExpansionExpr *E); + void VisitSizeOfPackExpr(SizeOfPackExpr *E); void VisitOpaqueValueExpr(OpaqueValueExpr *E); }; @@ -1294,6 +1295,15 @@ void ASTStmtReader::VisitPackExpansionExpr(PackExpansionExpr *E) { E->Pattern = Reader.ReadSubExpr(); } +void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) { + VisitExpr(E); + E->OperatorLoc = ReadSourceLocation(Record, Idx); + E->PackLoc = ReadSourceLocation(Record, Idx); + E->RParenLoc = ReadSourceLocation(Record, Idx); + E->Length = Record[Idx++]; + E->Pack = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); +} + void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); } @@ -1820,6 +1830,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { S = new (Context) PackExpansionExpr(Empty); break; + case EXPR_SIZEOF_PACK: + S = new (Context) SizeOfPackExpr(Empty); + break; + case EXPR_OPAQUE_VALUE: S = new (Context) OpaqueValueExpr(Empty); break; diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 27261dbb2a..af066bb425 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -151,6 +151,7 @@ namespace clang { void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E); void VisitCXXNoexceptExpr(CXXNoexceptExpr *E); void VisitPackExpansionExpr(PackExpansionExpr *E); + void VisitSizeOfPackExpr(SizeOfPackExpr *E); void VisitOpaqueValueExpr(OpaqueValueExpr *E); }; } @@ -1303,6 +1304,16 @@ void ASTStmtWriter::VisitPackExpansionExpr(PackExpansionExpr *E) { Code = serialization::EXPR_PACK_EXPANSION; } +void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { + VisitExpr(E); + 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); + Code = serialization::EXPR_SIZEOF_PACK; +} + void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); Code = serialization::EXPR_OPAQUE_VALUE; |