diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | lib/Headers/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Headers/stdalign.h | 30 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 65 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 49 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 4 |
6 files changed, 107 insertions, 44 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 4bafb2b6e7..0f6df31755 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -705,7 +705,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { // *except* on a struct or struct member, where it only increases // alignment unless 'packed' is also specified. // - // It is an error for [[align]] to decrease alignment, so we can + // It is an error for alignas to decrease alignment, so we can // ignore that possibility; Sema should diagnose it. if (isa<FieldDecl>(D)) { UseAlignAttrOnly = D->hasAttr<PackedAttr>() || diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt index 78fd6f19f6..1faf92fd19 100644 --- a/lib/Headers/CMakeLists.txt +++ b/lib/Headers/CMakeLists.txt @@ -12,6 +12,7 @@ set(files nmmintrin.h pmmintrin.h smmintrin.h + stdalign.h stdarg.h stdbool.h stddef.h diff --git a/lib/Headers/stdalign.h b/lib/Headers/stdalign.h new file mode 100644 index 0000000000..e7fbfa0499 --- /dev/null +++ b/lib/Headers/stdalign.h @@ -0,0 +1,30 @@ +/*===---- stdalign.h - Standard header for alignment ------------------------=== + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __STDALIGN_H +#define __STDALIGN_H + +#define alignas _Alignas +#define __alignas_is_defined 1 + +#endif /* __STDALIGN_H */ diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d904bcc807..e9d3185b9a 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1314,6 +1314,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS) { /// specifier-qualifier-list is a subset of declaration-specifiers. Just /// parse declaration-specifiers and complain about extra stuff. + /// TODO: diagnose attribute-specifiers and alignment-specifiers. ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS); // Validate declspec for type-name. @@ -1497,11 +1498,68 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { return DSC_normal; } +/// ParseAlignArgument - Parse the argument to an alignment-specifier. +/// +/// 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) { + 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); + } else + return ParseConstantExpression(); +} + +/// ParseAlignmentSpecifier - Parse an alignment-specifier, and add the +/// attribute to Attrs. +/// +/// alignment-specifier: +/// [C1X] '_Alignas' '(' type-id ')' +/// [C1X] '_Alignas' '(' constant-expression ')' +/// [C++0x] 'alignas' '(' type-id ')' +/// [C++0x] 'alignas' '(' assignment-expression ')' +void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, + SourceLocation *endLoc) { + assert((Tok.is(tok::kw_alignas) || Tok.is(tok::kw__Alignas)) && + "Not an alignment-specifier!"); + + SourceLocation KWLoc = Tok.getLocation(); + ConsumeToken(); + + SourceLocation ParamLoc = Tok.getLocation(); + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + return; + + ExprResult ArgExpr = ParseAlignArgument(ParamLoc); + if (ArgExpr.isInvalid()) { + SkipUntil(tok::r_paren); + return; + } + + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, ParamLoc); + if (endLoc) + *endLoc = RParenLoc; + + ExprVector ArgExprs(Actions); + ArgExprs.push_back(ArgExpr.release()); + Attrs.addNew(PP.getIdentifierInfo("aligned"), KWLoc, 0, KWLoc, + 0, ParamLoc, ArgExprs.take(), 1, false, true); +} + /// ParseDeclarationSpecifiers /// declaration-specifiers: [C99 6.7] /// storage-class-specifier declaration-specifiers[opt] /// type-specifier declaration-specifiers[opt] /// [C99] function-specifier declaration-specifiers[opt] +/// [C1X] alignment-specifier declaration-specifiers[opt] /// [GNU] attributes declaration-specifiers[opt] /// [Clang] '__module_private__' declaration-specifiers[opt] /// @@ -1946,6 +2004,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec, DiagID); break; + // alignment-specifier + case tok::kw__Alignas: + if (!getLang().C1X) + Diag(Tok, diag::ext_c1x_alignas); + ParseAlignmentSpecifier(DS.getAttributes()); + continue; + // friend case tok::kw_friend: if (DSContext == DSC_class) diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index ab953dc9c8..2fd5c0059d 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2561,6 +2561,7 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) { /// /// [C++0x] attribute-specifier: /// '[' '[' attribute-list ']' ']' +/// alignment-specifier /// /// [C++0x] attribute-list: /// attribute[opt] @@ -2593,6 +2594,11 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) { /// any token but '(', ')', '[', ']', '{', or '}' void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs, SourceLocation *endLoc) { + if (Tok.is(tok::kw_alignas)) { + ParseAlignmentSpecifier(attrs, endLoc); + return; + } + assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) && "Not a C++0x attribute list"); @@ -2652,29 +2658,6 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs, break; } - // One argument; must be a type-id or assignment-expression - case AttributeList::AT_aligned: { - if (Tok.isNot(tok::l_paren)) { - Diag(Tok.getLocation(), diag::err_cxx0x_attribute_requires_arguments) - << AttrName->getName(); - break; - } - SourceLocation ParamLoc = ConsumeParen(); - - ExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc); - - MatchRHSPunctuation(tok::r_paren, ParamLoc); - - ExprVector ArgExprs(Actions); - ArgExprs.push_back(ArgExpr.release()); - attrs.addNew(AttrName, AttrLoc, 0, AttrLoc, - 0, ParamLoc, ArgExprs.take(), 1, - false, true); - - AttrParsed = true; - break; - } - // Silence warnings default: break; } @@ -2713,26 +2696,6 @@ void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, attrs.Range = SourceRange(StartLoc, *endLoc); } -/// ParseCXX0XAlignArgument - Parse the argument to C++0x's [[align]] -/// attribute. -/// -/// FIXME: Simply returns an alignof() expression if the argument is a -/// type. Ideally, the type should be propagated directly into Sema. -/// -/// [C++0x] 'align' '(' type-id ')' -/// [C++0x] 'align' '(' assignment-expression ')' -ExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) { - 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); - } else - return ParseConstantExpression(); -} - /// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr] /// /// [MS] ms-attribute: diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 9b2ea90ba1..210d179db1 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -377,6 +377,7 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { /// /// [C++0x] attribute-specifier: /// '[' '[' attribute-list ']' ']' +/// alignment-specifier /// /// [C++0x] attribute-list: /// attribute[opt] @@ -409,6 +410,9 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { /// any token but '(', ')', '[', ']', '{', or '}' bool Parser::isCXX0XAttributeSpecifier (bool CheckClosing, tok::TokenKind *After) { + if (Tok.is(tok::kw_alignas)) + return true; + if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) return false; |