aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--include/clang/Parse/Parser.h3
-rw-r--r--lib/Parse/ParseDecl.cpp38
-rw-r--r--lib/Sema/SemaDeclAttr.cpp4
-rw-r--r--test/CXX/temp/temp.decls/temp.variadic/p5.cpp3
-rw-r--r--test/SemaCXX/attr-cxx0x.cpp7
6 files changed, 44 insertions, 13 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index ec4a140734..f0add4c067 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -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">;
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 5cd6e44870..3bf473cbe1 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -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);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 8ce3bc1746..3511f4abde 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -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,
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index d801664ad6..d43e1f1a9b 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -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));
diff --git a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
index bade856f60..a0b55804b9 100644
--- a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
+++ b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
@@ -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'}}
diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp
index 5d02cfca34..c697a7d152 100644
--- a/test/SemaCXX/attr-cxx0x.cpp
+++ b/test/SemaCXX/attr-cxx0x.cpp
@@ -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");