aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-06-30 21:33:57 +0000
committerJordan Rose <jordan_rose@apple.com>2012-06-30 21:33:57 +0000
commitf70a88612a4bc2de2872a518267b9b4891ab6431 (patch)
tree1aa6e9e83c062251aed23d8bdf30aeeebbd96cae
parent685d78d0da52f611b09e728f73e83999fabaa463 (diff)
Add support for the C11 _Alignof keyword.
This behaves like the existing GNU __alignof and C++11 alignof keywords; most of the patch is simply adding the third token spelling to various places. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159494 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td4
-rw-r--r--include/clang/Basic/TokenKinds.def1
-rw-r--r--lib/AST/StmtDumper.cpp2
-rw-r--r--lib/AST/StmtPrinter.cpp7
-rw-r--r--lib/Parse/ParseDecl.cpp2
-rw-r--r--lib/Parse/ParseExpr.cpp26
-rw-r--r--lib/Parse/ParseTentative.cpp1
-rw-r--r--lib/Sema/SemaCodeComplete.cpp13
-rw-r--r--lib/Sema/SemaLookup.cpp6
-rw-r--r--test/Parser/c1x-alignas.c8
-rw-r--r--test/Sema/alignas.c13
11 files changed, 62 insertions, 21 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index a0e4ef958e..ae1a041596 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -92,8 +92,8 @@ def err_duplicate_default_assoc : Error<
def note_previous_default_assoc : Note<
"previous default generic association is here">;
-def ext_c11_alignas : Extension<
- "_Alignas is a C11-specific feature">, InGroup<C11>;
+def ext_c11_alignment : Extension<
+ "%0 is a C11-specific feature">, InGroup<C11>;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">, InGroup<GNU>;
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index c380f8c907..751d8674ae 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -251,6 +251,7 @@ KEYWORD(void , KEYALL)
KEYWORD(volatile , KEYALL)
KEYWORD(while , KEYALL)
KEYWORD(_Alignas , KEYALL)
+KEYWORD(_Alignof , KEYALL)
KEYWORD(_Atomic , KEYALL)
KEYWORD(_Bool , KEYNOCXX)
KEYWORD(_Complex , KEYALL)
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index ce330e06b7..d5e12c873d 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -463,7 +463,7 @@ void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
OS << " sizeof ";
break;
case UETT_AlignOf:
- OS << " __alignof ";
+ OS << " alignof ";
break;
case UETT_VecStep:
OS << " vec_step ";
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 9c7259745c..5bd61c3b52 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -814,7 +814,12 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){
OS << "sizeof";
break;
case UETT_AlignOf:
- OS << "__alignof";
+ if (Policy.LangOpts.CPlusPlus)
+ OS << "alignof";
+ else if (Policy.LangOpts.C11)
+ OS << "_Alignof";
+ else
+ OS << "__alignof";
break;
case UETT_VecStep:
OS << "vec_step";
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 409f8e002a..c6db497a53 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2478,7 +2478,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// alignment-specifier
case tok::kw__Alignas:
if (!getLangOpts().C11)
- Diag(Tok, diag::ext_c11_alignas);
+ Diag(Tok, diag::ext_c11_alignment) << Tok.getName();
ParseAlignmentSpecifier(DS.getAttributes());
continue;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 840402530b..7f268b523d 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -507,6 +507,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
/// [C++11] 'sizeof' '...' '(' identifier ')'
/// [GNU] '__alignof' unary-expression
/// [GNU] '__alignof' '(' type-name ')'
+/// [C11] '_Alignof' '(' type-name ')'
/// [C++11] 'alignof' '(' type-id ')'
/// [GNU] '&&' identifier
/// [C++11] 'noexcept' '(' expression ')' [C++11 5.3.7]
@@ -921,12 +922,15 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
return move(Res);
}
- case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
- // unary-expression: 'sizeof' '(' type-name ')'
- case tok::kw_alignof:
+ case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')'
+ if (!getLangOpts().C11)
+ Diag(Tok, diag::ext_c11_alignment) << Tok.getName();
+ // fallthrough
+ case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')'
case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
// unary-expression: '__alignof' '(' type-name ')'
- // unary-expression: 'alignof' '(' type-id ')'
+ case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
+ // unary-expression: 'sizeof' '(' type-name ')'
case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression
return ParseUnaryExprOrTypeTraitExpression();
case tok::ampamp: { // unary-expression: '&&' identifier
@@ -1514,6 +1518,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
/// 'sizeof' '(' type-name ')'
/// [GNU] '__alignof' unary-expression
/// [GNU] '__alignof' '(' type-name ')'
+/// [C11] '_Alignof' '(' type-name ')'
/// [C++0x] 'alignof' '(' type-id ')'
///
/// [GNU] typeof-specifier:
@@ -1533,7 +1538,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) ||
- OpTok.is(tok::kw_vec_step)) &&
+ OpTok.is(tok::kw__Alignof) || OpTok.is(tok::kw_vec_step)) &&
"Not a typeof/sizeof/alignof/vec_step expression!");
ExprResult Operand;
@@ -1591,11 +1596,13 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
/// [C++0x] 'sizeof' '...' '(' identifier ')'
/// [GNU] '__alignof' unary-expression
/// [GNU] '__alignof' '(' type-name ')'
+/// [C11] '_Alignof' '(' type-name ')'
/// [C++0x] 'alignof' '(' type-id ')'
/// \endverbatim
ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
- assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof)
- || Tok.is(tok::kw_alignof) || Tok.is(tok::kw_vec_step)) &&
+ assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) ||
+ Tok.is(tok::kw_alignof) || Tok.is(tok::kw__Alignof) ||
+ Tok.is(tok::kw_vec_step)) &&
"Not a sizeof/alignof/vec_step expression!");
Token OpTok = Tok;
ConsumeToken();
@@ -1643,7 +1650,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
RParenLoc);
}
- if (OpTok.is(tok::kw_alignof))
+ if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof))
Diag(OpTok, diag::warn_cxx98_compat_alignof);
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
@@ -1657,7 +1664,8 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
CastRange);
UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;
- if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof))
+ if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof) ||
+ OpTok.is(tok::kw__Alignof))
ExprKind = UETT_AlignOf;
else if (OpTok.is(tok::kw_vec_step))
ExprKind = UETT_VecStep;
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 8a5e7266d3..41d793f3f2 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -735,6 +735,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw_alignof:
case tok::kw_noexcept:
case tok::kw_nullptr:
+ case tok::kw__Alignof:
case tok::kw___null:
case tok::kw___alignof:
case tok::kw___builtin_choose_expr:
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 5cab990d33..ff83324de2 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1955,6 +1955,19 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
AddObjCExpressionResults(Results, true);
}
+ if (SemaRef.getLangOpts().C11) {
+ // _Alignof
+ Builder.AddResultTypeChunk("size_t");
+ if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition())
+ Builder.AddTypedTextChunk("alignof");
+ else
+ Builder.AddTypedTextChunk("_Alignof");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
// sizeof expression
Builder.AddResultTypeChunk("size_t");
Builder.AddTypedTextChunk("sizeof");
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 827cfbcfff..94efb2fff3 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -3604,6 +3604,12 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
Consumer.addKeywordResult("nullptr");
}
}
+
+ if (SemaRef.getLangOpts().C11) {
+ // FIXME: We should not suggest _Alignof if the alignof macro
+ // is present.
+ Consumer.addKeywordResult("_Alignof");
+ }
}
if (CCC.WantRemainingKeywords) {
diff --git a/test/Parser/c1x-alignas.c b/test/Parser/c1x-alignas.c
index 5dccc99035..81cd681630 100644
--- a/test/Parser/c1x-alignas.c
+++ b/test/Parser/c1x-alignas.c
@@ -1,7 +1,13 @@
-// RUN: %clang_cc1 -std=c1x -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify %s
+// RUN: not %clang_cc1 -pedantic -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-EXT %s
_Alignas(4) char c1;
unsigned _Alignas(long) char c2;
char _Alignas(16) c3;
char c4 _Alignas(32); // expected-error {{expected ';' after top level declarator}}
+
+char _Alignas(_Alignof(int)) c5;
+
+// CHECK-EXT: _Alignas is a C11-specific feature
+// CHECK-EXT: _Alignof is a C11-specific feature
diff --git a/test/Sema/alignas.c b/test/Sema/alignas.c
index 5832393e3b..d9a0164010 100644
--- a/test/Sema/alignas.c
+++ b/test/Sema/alignas.c
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c1x %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -Dalignof=__alignof %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -Dalignof=_Alignof %s
_Alignas(3) int align_illegal; //expected-error {{requested alignment is not a power of 2}}
_Alignas(int) char align_big;
@@ -11,9 +12,9 @@ struct align_member {
typedef _Alignas(8) char align_typedef; // FIXME: this should be rejected
-_Static_assert(__alignof(align_big) == __alignof(int), "k's alignment is wrong");
-_Static_assert(__alignof(align_small) == 1, "j's alignment is wrong");
-_Static_assert(__alignof(align_multiple) == 8, "l's alignment is wrong");
-_Static_assert(__alignof(struct align_member) == 8, "quuux's alignment is wrong");
+_Static_assert(alignof(align_big) == alignof(int), "k's alignment is wrong");
+_Static_assert(alignof(align_small) == 1, "j's alignment is wrong");
+_Static_assert(alignof(align_multiple) == 8, "l's alignment is wrong");
+_Static_assert(alignof(struct align_member) == 8, "quuux's alignment is wrong");
_Static_assert(sizeof(struct align_member) == 8, "quuux's size is wrong");
-_Static_assert(__alignof(align_typedef) == 8, "typedef's alignment is wrong");
+_Static_assert(alignof(align_typedef) == 8, "typedef's alignment is wrong");