]> granicus.if.org Git - clang/commitdiff
Fix grammar for C++11 alignment specifiers, and add a few FIXMEs.
authorPeter Collingbourne <peter@pcc.me.uk>
Sun, 23 Oct 2011 20:07:52 +0000 (20:07 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Sun, 23 Oct 2011 20:07:52 +0000 (20:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142760 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/CXX/temp/temp.decls/temp.variadic/p5.cpp
test/SemaCXX/attr-cxx0x.cpp

index ec4a140734de40f882191807395269b669438f45..f0add4c067d88cdbcc95ef60b1712cf5bb8063db 100644 (file)
@@ -427,6 +427,8 @@ def err_cxx0x_attribute_forbids_arguments : Error<
 def err_cxx0x_attribute_requires_arguments : Error<
   "C++11 attribute '%0' must have an argument list">;
 def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
+def err_alignas_pack_exp_unsupported : Error<
+  "pack expansions in alignment specifiers are not supported yet">;
 
 /// C++ Templates
 def err_expected_template : Error<"expected template">;
index 5cd6e44870855fba4f9754548bd99def3b53ae0e..3bf473cbe1cf18d8673da939382884e94b9a9aa8 100644 (file)
@@ -1853,7 +1853,8 @@ private:
   void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
   void ParseAtomicSpecifier(DeclSpec &DS);
 
-  ExprResult ParseAlignArgument(SourceLocation Start);
+  ExprResult ParseAlignArgument(SourceLocation Start,
+                                SourceLocation &EllipsisLoc);
   void ParseAlignmentSpecifier(ParsedAttributes &Attrs,
                                SourceLocation *endLoc = 0);
 
index 8ce3bc174652aa697e458e20650634827c131ab4..3511f4abde9634af1fd5c0bcb49b4d283c11b38c 100644 (file)
@@ -1552,19 +1552,28 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
 /// FIXME: Simply returns an alignof() expression if the argument is a
 /// type. Ideally, the type should be propagated directly into Sema.
 ///
-/// [C1X/C++0x] type-id
-/// [C1X]       constant-expression
-/// [C++0x]     assignment-expression
-ExprResult Parser::ParseAlignArgument(SourceLocation Start) {
+/// [C1X]   type-id
+/// [C1X]   constant-expression
+/// [C++0x] type-id ...[opt]
+/// [C++0x] assignment-expression ...[opt]
+ExprResult Parser::ParseAlignArgument(SourceLocation Start,
+                                      SourceLocation &EllipsisLoc) {
+  ExprResult ER;
   if (isTypeIdInParens()) {
-    EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
     SourceLocation TypeLoc = Tok.getLocation();
     ParsedType Ty = ParseTypeName().get();
     SourceRange TypeRange(Start, Tok.getLocation());
-    return Actions.ActOnUnaryExprOrTypeTraitExpr(TypeLoc, UETT_AlignOf, true,
-                                                Ty.getAsOpaquePtr(), TypeRange);
+    ER = Actions.ActOnUnaryExprOrTypeTraitExpr(TypeLoc, UETT_AlignOf, true,
+                                               Ty.getAsOpaquePtr(), TypeRange);
   } else
-    return ParseConstantExpression();
+    ER = ParseConstantExpression();
+
+  if (getLang().CPlusPlus0x && Tok.is(tok::ellipsis)) {
+    EllipsisLoc = Tok.getLocation();
+    ConsumeToken();
+  }
+
+  return ER;
 }
 
 /// ParseAlignmentSpecifier - Parse an alignment-specifier, and add the
@@ -1573,8 +1582,8 @@ ExprResult Parser::ParseAlignArgument(SourceLocation Start) {
 /// alignment-specifier:
 /// [C1X]   '_Alignas' '(' type-id ')'
 /// [C1X]   '_Alignas' '(' constant-expression ')'
-/// [C++0x] 'alignas' '(' type-id ')'
-/// [C++0x] 'alignas' '(' assignment-expression ')'
+/// [C++0x] 'alignas' '(' type-id ...[opt] ')'
+/// [C++0x] 'alignas' '(' assignment-expression ...[opt] ')'
 void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
                                      SourceLocation *endLoc) {
   assert((Tok.is(tok::kw_alignas) || Tok.is(tok::kw__Alignas)) &&
@@ -1587,7 +1596,8 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
   if (T.expectAndConsume(diag::err_expected_lparen))
     return;
 
-  ExprResult ArgExpr = ParseAlignArgument(T.getOpenLocation());
+  SourceLocation EllipsisLoc;
+  ExprResult ArgExpr = ParseAlignArgument(T.getOpenLocation(), EllipsisLoc);
   if (ArgExpr.isInvalid()) {
     SkipUntil(tok::r_paren);
     return;
@@ -1597,6 +1607,12 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
   if (endLoc)
     *endLoc = T.getCloseLocation();
 
+  // FIXME: Handle pack-expansions here.
+  if (EllipsisLoc.isValid()) {
+    Diag(EllipsisLoc, diag::err_alignas_pack_exp_unsupported);
+    return;
+  }
+
   ExprVector ArgExprs(Actions);
   ArgExprs.push_back(ArgExpr.release());
   Attrs.addNew(PP.getIdentifierInfo("aligned"), KWLoc, 0, KWLoc,
index d801664ad63ee0636fcb7fa5ffdfb8752a9362d5..d43e1f1a9baf551a286625d984f204a01ed9c0b9 100644 (file)
@@ -2544,6 +2544,10 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
 }
 
 void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E) {
+  // FIXME: Handle pack-expansions here.
+  if (DiagnoseUnexpandedParameterPack(E))
+    return;
+
   if (E->isTypeDependent() || E->isValueDependent()) {
     // Save dependent expressions in the AST to be instantiated.
     D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E));
index bade856f6033c7ece670a7bcc5837934f0fdbef5..a0b55804b94a871941ccba74246b70d5e4492576 100644 (file)
@@ -160,8 +160,9 @@ struct TestUnexpandedTTP {
 };
 
 // Test for unexpanded parameter packs in declarations.
-// FIXME: Attributes?
 template<typename T, typename... Types>
+// FIXME: this should test that the diagnostic reads "type contains..."
+alignas(Types) // expected-error{{expression contains unexpanded parameter pack 'Types'}}
 struct TestUnexpandedDecls : T{
   void member_function(Types);  // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
   void member_function () throw(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
index 5d02cfca343307af46c0ff324bbc401115d9f884..c697a7d152328022749b05a0d2768b656cf9e918 100644 (file)
@@ -11,6 +11,10 @@ struct align_member {
 
 template <unsigned A> alignas(A) struct align_class_template {};
 
+// FIXME: these should not error
+template <typename... T> alignas(T...) struct align_class_temp_pack_type {}; // expected-error{{pack expansions in alignment specifiers are not supported yet}}
+template <unsigned... A> alignas(A...) struct align_class_temp_pack_expr {}; // expected-error{{pack expansions in alignment specifiers are not supported yet}}
+
 typedef char align_typedef alignas(8);
 template<typename T> using align_alias_template = align_typedef;
 
@@ -22,4 +26,7 @@ static_assert(sizeof(align_member) == 8, "quuux's size is wrong");
 static_assert(alignof(align_typedef) == 8, "typedef's alignment is wrong");
 static_assert(alignof(align_class_template<8>) == 8, "template's alignment is wrong");
 static_assert(alignof(align_class_template<16>) == 16, "template's alignment is wrong");
+// FIXME: enable these tests
+// static_assert(alignof(align_class_temp_pack_type<short, int, long>) == alignof(long), "template's alignment is wrong");
+// static_assert(alignof(align_class_temp_pack_expr<8, 16, 32>) == 32, "template's alignment is wrong");
 static_assert(alignof(align_alias_template<int>) == 8, "alias template's alignment is wrong");