Author: hubert.reinterpretcast Date: Wed Jun 24 19:23:39 2015 New Revision: 240611
URL: http://llvm.org/viewvc/llvm-project?rev=240611&view=rev Log: [Concepts] Parsing of requires-clause in template-declaration Summary: This change implements parse-only acceptance of the optional requires-clause in a template-declaration. Diagnostic testing is added for cases where the grammar is ambiguous with the expectation that the longest token sequence which matches the syntax of a constraint-expression is consumed without backtracking. Reviewers: faisalv, fraggamuffin, rsmith Reviewed By: rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D10462 Added: cfe/trunk/test/Parser/cxx-concepts-ambig-constraint-expr.cpp cfe/trunk/test/Parser/cxx-concepts-requires-clause.cpp Modified: cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/Parse/ParseExpr.cpp cfe/trunk/lib/Parse/ParseTemplate.cpp Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=240611&r1=240610&r2=240611&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Wed Jun 24 19:23:39 2015 @@ -1331,6 +1331,7 @@ public: ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast); ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast); + ExprResult ParseConstraintExpression(); // Expr that doesn't include commas. ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast); Modified: cfe/trunk/lib/Parse/ParseExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=240611&r1=240610&r2=240611&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExpr.cpp (original) +++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Jun 24 19:23:39 2015 @@ -205,6 +205,24 @@ ExprResult Parser::ParseConstantExpressi return Actions.ActOnConstantExpression(Res); } +/// \brief Parse a constraint-expression. +/// +/// \verbatim +/// constraint-expression: [Concepts TS temp.constr.decl p1] +/// logical-or-expression +/// \endverbatim +ExprResult Parser::ParseConstraintExpression() { + // FIXME: this may erroneously consume a function-body as the braced + // initializer list of a compound literal + // + // FIXME: this may erroneously consume a parenthesized rvalue reference + // declarator as a parenthesized address-of-label expression + ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false)); + ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr)); + + return Res; +} + bool Parser::isNotExpressionStart() { tok::TokenKind K = Tok.getKind(); if (K == tok::l_brace || K == tok::r_brace || Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=240611&r1=240610&r2=240611&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTemplate.cpp (original) +++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Jun 24 19:23:39 2015 @@ -116,7 +116,7 @@ Parser::ParseTemplateDeclarationOrSpecia SmallVector<Decl*, 4> TemplateParams; if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(), TemplateParams, LAngleLoc, RAngleLoc)) { - // Skip until the semi-colon or a }. + // Skip until the semi-colon or a '}'. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); TryConsumeToken(tok::semi); return nullptr; @@ -132,6 +132,17 @@ Parser::ParseTemplateDeclarationOrSpecia if (!TemplateParams.empty()) { isSpecialization = false; ++CurTemplateDepthTracker; + + if (TryConsumeToken(tok::kw_requires)) { + ExprResult ER = + Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression()); + if (!ER.isUsable()) { + // Skip until the semi-colon or a '}'. + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + TryConsumeToken(tok::semi); + return nullptr; + } + } } else { LastParamListWasEmpty = true; } Added: cfe/trunk/test/Parser/cxx-concepts-ambig-constraint-expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-concepts-ambig-constraint-expr.cpp?rev=240611&view=auto ============================================================================== --- cfe/trunk/test/Parser/cxx-concepts-ambig-constraint-expr.cpp (added) +++ cfe/trunk/test/Parser/cxx-concepts-ambig-constraint-expr.cpp Wed Jun 24 19:23:39 2015 @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ %s -verify + +// Test parsing of constraint-expressions in cases where the grammar is +// ambiguous with the expectation that the longest token sequence which matches +// the syntax is consumed without backtracking. + +// type-specifier-seq in conversion-type-id +template <typename T> requires (bool)&T::operator short +unsigned int foo(); // expected-error {{C++ requires a type specifier for all declarations}} + +// type-specifier-seq in new-type-id +template <typename T> requires (bool)sizeof new (T::f()) short +unsigned int bar(); // expected-error {{C++ requires a type specifier for all declarations}} + +template<typename T> requires (bool)sizeof new (T::f()) unsigned // expected-error {{'struct' cannot be signed or unsigned}} +struct X { }; // expected-error {{'X' cannot be defined in a type specifier}} + +// C-style cast +// of function call on function-style cast +template <typename T> requires (bool(T())) +T (*fp)(); // expected-error {{use of undeclared identifier 'fp'}} + +// function-style cast +// as the callee in a function call +struct A { + static int t; + template <typename T> requires bool(T()) + (A(T (&t))) { } // expected-error {{called object type 'bool' is not a function or function pointer}} +}; Added: cfe/trunk/test/Parser/cxx-concepts-requires-clause.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-concepts-requires-clause.cpp?rev=240611&view=auto ============================================================================== --- cfe/trunk/test/Parser/cxx-concepts-requires-clause.cpp (added) +++ cfe/trunk/test/Parser/cxx-concepts-requires-clause.cpp Wed Jun 24 19:23:39 2015 @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ %s -verify +// expected-no-diagnostics + +// Test parsing of the optional requires-clause in a template-declaration. + +template <typename T> requires true +void foo() { } + + +template <typename T> requires !0 +struct A { + void foo(); + struct AA; + enum E : int; + static int x; + + template <typename> requires true + void Mfoo(); + + template <typename> requires true + struct M; + + template <typename> requires true + static int Mx; + + template <typename TT> requires true + using MQ = M<TT>; +}; + +template <typename T> requires !0 +void A<T>::foo() { } + +template <typename T> requires !0 +struct A<T>::AA { }; + +template <typename T> requires !0 +enum A<T>::E : int { E0 }; + +template <typename T> requires !0 +int A<T>::x = 0; + +template <typename T> requires !0 +template <typename> requires true +void A<T>::Mfoo() { } + +template <typename T> requires !0 +template <typename> requires true +struct A<T>::M { }; + +template <typename T> requires !0 +template <typename> requires true +int A<T>::Mx = 0; + + +template <typename T> requires true +int x = 0; + +template <typename T> requires true +using Q = A<T>; + +struct C { + template <typename> requires true + void Mfoo(); + + template <typename> requires true + struct M; + + template <typename> requires true + static int Mx; + + template <typename T> requires true + using MQ = M<T>; +}; + +template <typename> requires true +void C::Mfoo() { } + +template <typename> requires true +struct C::M { }; + +template <typename> requires true +int C::Mx = 0; _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
