summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-06-19 11:42:00 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-06-19 11:42:00 +0000
commit955bf016ee1b01884c15de92b631b709a1015707 (patch)
treea8c50a90499edf23a9f1c5fe718b3ba4a840c4df /clang/lib
parent562fd7534c1c82b105565e6f01429ebfdd0fa8eb (diff)
downloadbcm5719-llvm-955bf016ee1b01884c15de92b631b709a1015707.tar.gz
bcm5719-llvm-955bf016ee1b01884c15de92b631b709a1015707.zip
[c++1z] Implement N3994: a range-based for loop can declare a variable with super-terse notation
for (x : range) { ... } which is equivalent to for (auto &&x : range) { ... } llvm-svn: 211267
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp22
-rw-r--r--clang/lib/Parse/ParseStmt.cpp42
-rw-r--r--clang/lib/Sema/SemaDecl.cpp31
3 files changed, 87 insertions, 8 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 5ec899f5898..33e3cab8671 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3390,13 +3390,23 @@ void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
}
void Parser::DiagnoseAndSkipCXX11Attributes() {
- if (!isCXX11AttributeSpecifier())
- return;
-
// Start and end location of an attribute or an attribute list.
SourceLocation StartLoc = Tok.getLocation();
+ SourceLocation EndLoc = SkipCXX11Attributes();
+
+ if (EndLoc.isValid()) {
+ SourceRange Range(StartLoc, EndLoc);
+ Diag(StartLoc, diag::err_attributes_not_allowed)
+ << Range;
+ }
+}
+
+SourceLocation Parser::SkipCXX11Attributes() {
SourceLocation EndLoc;
+ if (!isCXX11AttributeSpecifier())
+ return EndLoc;
+
do {
if (Tok.is(tok::l_square)) {
BalancedDelimiterTracker T(*this, tok::l_square);
@@ -3413,11 +3423,7 @@ void Parser::DiagnoseAndSkipCXX11Attributes() {
}
} while (isCXX11AttributeSpecifier());
- if (EndLoc.isValid()) {
- SourceRange Range(StartLoc, EndLoc);
- Diag(StartLoc, diag::err_attributes_not_allowed)
- << Range;
- }
+ return EndLoc;
}
/// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr]
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 059c2b6a3f8..536e92c0cc6 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1388,6 +1388,25 @@ StmtResult Parser::ParseDoStatement() {
Cond.get(), T.getCloseLocation());
}
+bool Parser::isForRangeIdentifier() {
+ assert(Tok.is(tok::identifier));
+
+ const Token &Next = NextToken();
+ if (Next.is(tok::colon))
+ return true;
+
+ if (Next.is(tok::l_square) || Next.is(tok::kw_alignas)) {
+ TentativeParsingAction PA(*this);
+ ConsumeToken();
+ SkipCXX11Attributes();
+ bool Result = Tok.is(tok::colon);
+ PA.Revert();
+ return Result;
+ }
+
+ return false;
+}
+
/// ParseForStatement
/// for-statement: [C99 6.8.5.3]
/// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
@@ -1471,6 +1490,29 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
ProhibitAttributes(attrs);
// no first part, eat the ';'.
ConsumeToken();
+ } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) &&
+ isForRangeIdentifier()) {
+ ProhibitAttributes(attrs);
+ IdentifierInfo *Name = Tok.getIdentifierInfo();
+ SourceLocation Loc = ConsumeToken();
+ MaybeParseCXX11Attributes(attrs);
+
+ ForRangeInit.ColonLoc = ConsumeToken();
+ if (Tok.is(tok::l_brace))
+ ForRangeInit.RangeExpr = ParseBraceInitializer();
+ else
+ ForRangeInit.RangeExpr = ParseExpression();
+
+ Diag(Loc, getLangOpts().CPlusPlus1z
+ ? diag::warn_cxx1y_compat_for_range_identifier
+ : diag::ext_for_range_identifier)
+ << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus1z)
+ ? FixItHint::CreateInsertion(Loc, "auto &&")
+ : FixItHint());
+
+ FirstPart = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name,
+ attrs, attrs.Range.getEnd());
+ ForRange = true;
} else if (isForInitDeclaration()) { // for (int X = 4;
// Parse declaration, which eats the ';'.
if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e4b2096bec7..bdc8609116f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8941,6 +8941,37 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
}
}
+StmtResult
+Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
+ IdentifierInfo *Ident,
+ ParsedAttributes &Attrs,
+ SourceLocation AttrEnd) {
+ // C++1y [stmt.iter]p1:
+ // A range-based for statement of the form
+ // for ( for-range-identifier : for-range-initializer ) statement
+ // is equivalent to
+ // for ( auto&& for-range-identifier : for-range-initializer ) statement
+ DeclSpec DS(Attrs.getPool().getFactory());
+
+ const char *PrevSpec;
+ unsigned DiagID;
+ DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID,
+ getPrintingPolicy());
+
+ Declarator D(DS, Declarator::ForContext);
+ D.SetIdentifier(Ident, IdentLoc);
+ D.takeAttributes(Attrs, AttrEnd);
+
+ ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory());
+ D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false),
+ EmptyAttrs, IdentLoc);
+ Decl *Var = ActOnDeclarator(S, D);
+ cast<VarDecl>(Var)->setCXXForRangeDecl(true);
+ FinalizeDeclaration(Var);
+ return ActOnDeclStmt(FinalizeDeclaratorGroup(S, DS, Var), IdentLoc,
+ AttrEnd.isValid() ? AttrEnd : IdentLoc);
+}
+
void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (var->isInvalidDecl()) return;
OpenPOWER on IntegriCloud