aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-04-26 16:15:35 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-04-26 16:15:35 +0000
commita2c3646c35dd09d21b74826240aa916545b1873f (patch)
treee2a57dcc3d41734ea9734c76a9d759c8951392f4 /lib/Parse
parentbebf5b1bcfbf591dd3cd80c4aebd6486bb34f41c (diff)
Implement C++1y decltype(auto).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180610 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp3
-rw-r--r--lib/Parse/ParseDecl.cpp3
-rw-r--r--lib/Parse/ParseDeclCXX.cpp79
-rw-r--r--lib/Parse/ParseExpr.cpp8
-rw-r--r--lib/Parse/ParseExprCXX.cpp2
-rw-r--r--lib/Parse/ParseTentative.cpp1
6 files changed, 60 insertions, 36 deletions
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index bc634b57d9..5d77f81ee4 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -57,8 +57,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
if (FnD) {
Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs,
false, true);
- bool TypeSpecContainsAuto
- = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+ bool TypeSpecContainsAuto = D.getDeclSpec().containsPlaceholderType();
if (Init.isUsable())
Actions.AddInitializerToDecl(FnD, Init.get(), false,
TypeSpecContainsAuto);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 697e95a73e..957e2eb164 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1809,8 +1809,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
}
}
- bool TypeContainsAuto =
- D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+ bool TypeContainsAuto = D.getDeclSpec().containsPlaceholderType();
// Parse declarator '=' initializer.
// If a '==' or '+=' is found, suggest a fixit to '='.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index d7f8e982aa..f1fbbb15fe 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -674,15 +674,15 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
T.getCloseLocation());
}
-/// ParseDecltypeSpecifier - Parse a C++0x decltype specifier.
+/// ParseDecltypeSpecifier - Parse a C++11 decltype specifier.
///
/// 'decltype' ( expression )
+/// 'decltype' ( 'auto' ) [C++1y]
///
SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
assert((Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))
&& "Not a decltype specifier");
-
ExprResult Result;
SourceLocation StartLoc = Tok.getLocation();
SourceLocation EndLoc;
@@ -709,29 +709,44 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
StartLoc : T.getOpenLocation();
}
- // Parse the expression
-
- // C++0x [dcl.type.simple]p4:
- // The operand of the decltype specifier is an unevaluated operand.
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
- 0, /*IsDecltype=*/true);
- Result = ParseExpression();
- if (Result.isInvalid()) {
- DS.SetTypeSpecError();
- if (SkipUntil(tok::r_paren, /*StopAtSemi=*/true, /*DontConsume=*/true)) {
- EndLoc = ConsumeParen();
- } else {
- if (PP.isBacktrackEnabled() && Tok.is(tok::semi)) {
- // Backtrack to get the location of the last token before the semi.
- PP.RevertCachedTokens(2);
- ConsumeToken(); // the semi.
- EndLoc = ConsumeAnyToken();
- assert(Tok.is(tok::semi));
+ // Check for C++1y 'decltype(auto)'.
+ if (Tok.is(tok::kw_auto)) {
+ // No need to disambiguate here: an expression can't start with 'auto',
+ // because the typename-specifier in a function-style cast operation can't
+ // be 'auto'.
+ Diag(Tok.getLocation(),
+ getLangOpts().CPlusPlus1y
+ ? diag::warn_cxx11_compat_decltype_auto_type_specifier
+ : diag::ext_decltype_auto_type_specifier);
+ ConsumeToken();
+ } else {
+ // Parse the expression
+
+ // C++11 [dcl.type.simple]p4:
+ // The operand of the decltype specifier is an unevaluated operand.
+ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
+ 0, /*IsDecltype=*/true);
+ Result = ParseExpression();
+ if (Result.isInvalid()) {
+ DS.SetTypeSpecError();
+ if (SkipUntil(tok::r_paren, /*StopAtSemi=*/true,
+ /*DontConsume=*/true)) {
+ EndLoc = ConsumeParen();
} else {
- EndLoc = Tok.getLocation();
+ if (PP.isBacktrackEnabled() && Tok.is(tok::semi)) {
+ // Backtrack to get the location of the last token before the semi.
+ PP.RevertCachedTokens(2);
+ ConsumeToken(); // the semi.
+ EndLoc = ConsumeAnyToken();
+ assert(Tok.is(tok::semi));
+ } else {
+ EndLoc = Tok.getLocation();
+ }
}
+ return EndLoc;
}
- return EndLoc;
+
+ Result = Actions.ActOnDecltypeExpression(Result.take());
}
// Match the ')'
@@ -743,7 +758,6 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
return T.getCloseLocation();
}
- Result = Actions.ActOnDecltypeExpression(Result.take());
if (Result.isInvalid()) {
DS.SetTypeSpecError();
return T.getCloseLocation();
@@ -751,12 +765,16 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
EndLoc = T.getCloseLocation();
}
+ assert(!Result.isInvalid());
const char *PrevSpec = 0;
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int decltype(a)").
- if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
- DiagID, Result.release())) {
+ if (Result.get()
+ ? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
+ DiagID, Result.release())
+ : DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc, PrevSpec,
+ DiagID)) {
Diag(StartLoc, DiagID) << PrevSpec;
DS.SetTypeSpecError();
}
@@ -773,8 +791,10 @@ void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec& DS,
PP.EnterToken(Tok);
Tok.setKind(tok::annot_decltype);
- setExprAnnotation(Tok, DS.getTypeSpecType() == TST_decltype ?
- DS.getRepAsExpr() : ExprResult());
+ setExprAnnotation(Tok,
+ DS.getTypeSpecType() == TST_decltype ? DS.getRepAsExpr() :
+ DS.getTypeSpecType() == TST_decltype_auto ? ExprResult() :
+ ExprError());
Tok.setAnnotationEndLoc(EndLoc);
Tok.setLocation(StartLoc);
PP.AnnotateCachedTokens(Tok);
@@ -2267,11 +2287,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SkipUntil(tok::comma, true, true);
else if (ThisDecl)
Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid(),
- DS.getTypeSpecType() == DeclSpec::TST_auto);
+ DS.containsPlaceholderType());
} else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) {
// No initializer.
- Actions.ActOnUninitializedDecl(ThisDecl,
- DS.getTypeSpecType() == DeclSpec::TST_auto);
+ Actions.ActOnUninitializedDecl(ThisDecl, DS.containsPlaceholderType());
}
if (ThisDecl) {
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 956ba36d3c..326056daf4 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -691,8 +691,14 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Res = getExprAnnotation(Tok);
ConsumeToken();
break;
-
+
case tok::kw_decltype:
+ // Annotate the token and tail recurse.
+ if (TryAnnotateTypeOrScopeToken())
+ return ExprError();
+ assert(Tok.isNot(tok::kw_decltype));
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+
case tok::identifier: { // primary-expression: identifier
// unqualified-id: identifier
// constant: enumeration-constant
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 17c4adf7d7..ab8be570c1 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1455,7 +1455,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
if (!InitExpr.isInvalid())
Actions.AddInitializerToDecl(DeclOut, InitExpr.take(), !CopyInitialization,
- DS.getTypeSpecType() == DeclSpec::TST_auto);
+ DS.containsPlaceholderType());
// FIXME: Build a reference to this declaration? Convert it to bool?
// (This is currently handled by Sema).
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 00ca3d8465..dff3b64c5b 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -942,6 +942,7 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
/// [GNU] '_Complex'
/// [C++11] 'auto'
/// [C++11] 'decltype' ( expression )
+/// [C++1y] 'decltype' ( 'auto' )
///
/// type-name:
/// class-name