diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-01-29 09:02:09 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-01-29 09:02:09 +0000 |
commit | 4cd81c5bf5957b2b10ddf253035f6e1596082108 (patch) | |
tree | 4c82f17c205f3de1a1819c9f542d51e0c1c31af1 /lib | |
parent | 52a92509aa204f64a28e05ffede63312b07ea9ef (diff) |
Implement C++11 [dcl.align]p1 and C11 6.7.5/2 rules for alignas and _Alignas.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173779 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 44 |
3 files changed, 56 insertions, 10 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 438c6f8cf5..20d8f711ae 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3890,6 +3890,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_explicit: case tok::kw__Noreturn: + // alignment-specifier + case tok::kw__Alignas: + // friend keyword. case tok::kw_friend: diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 0a1eccaa76..8b026e859f 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -2156,14 +2156,13 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard /// -/// handler: -/// 'catch' '(' exception-declaration ')' compound-statement +/// handler: +/// 'catch' '(' exception-declaration ')' compound-statement /// -/// exception-declaration: -/// type-specifier-seq declarator -/// type-specifier-seq abstract-declarator -/// type-specifier-seq -/// '...' +/// exception-declaration: +/// attribute-specifier-seq[opt] type-specifier-seq declarator +/// attribute-specifier-seq[opt] type-specifier-seq abstract-declarator[opt] +/// '...' /// StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { assert(Tok.is(tok::kw_catch) && "Expected 'catch'"); @@ -2184,9 +2183,15 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { // without default arguments. Decl *ExceptionDecl = 0; if (Tok.isNot(tok::ellipsis)) { + ParsedAttributesWithRange Attributes(AttrFactory); + MaybeParseCXX11Attributes(Attributes); + DeclSpec DS(AttrFactory); + DS.takeAttributesFrom(Attributes); + if (ParseCXXTypeSpecifierSeq(DS)) return StmtError(); + Declarator ExDecl(DS, Declarator::CXXCatchContext); ParseDeclarator(ExDecl); ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 0e51ba3ba3..01a3505cf7 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3272,9 +3272,47 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - //FIXME: The C++0x version of this attribute has more limited applicabilty - // than GNU's, and should error out when it is used to specify a - // weaker alignment, rather than being silently ignored. + // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. + // FIXME: Use a more reliable mechanism to determine how the attribute was + // spelled. + if (Attr.isKeywordAttribute()) { + // C++11 [dcl.align]p1: + // An alignment-specifier may be applied to a variable or to a class + // data member, but it shall not be applied to a bit-field, a function + // parameter, the formal parameter of a catch clause, or a variable + // declared with the register storage class specifier. An + // alignment-specifier may also be applied to the declaration of a class + // or enumeration type. + // C11 6.7.5/2: + // An alignment attribute shall not be specified in a declaration of + // a typedef, or a bit-field, or a function, or a parameter, or an + // object declared with the register storage-class specifier. + int DiagKind = -1; + if (isa<ParmVarDecl>(D)) { + DiagKind = 0; + } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (VD->getStorageClass() == SC_Register) + DiagKind = 1; + if (VD->isExceptionVariable()) + DiagKind = 2; + } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { + if (FD->isBitField()) + DiagKind = 3; + } else if (!isa<TagDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableFunctionOrTag; + return; + } + if (DiagKind != -1) { + S.Diag(Attr.getLoc(), diag::err_alignas_attribute_wrong_decl_type) + << Attr.getName() << DiagKind; + return; + } + } + + // FIXME: The C++11 version of this attribute should error out when it is + // used to specify a weaker alignment, rather than being silently + // ignored. if (Attr.getNumArgs() == 0) { D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, |