Support decltype in member initializers.
This is the last piece of N3031 (decltype in weird places) - supporting
the use of decltype in a class ctor's member-initializer-list to
specify the base classes to initialize.
Reviewed by Richard Smith.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148789 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 050b1b1..14c8955 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -2414,15 +2414,28 @@
TemplateTypeTy = getTypeAnnotation(Tok);
}
}
- if (!TemplateTypeTy && Tok.isNot(tok::identifier)) {
+ // Uses of decltype will already have been converted to annot_decltype by
+ // ParseOptionalCXXScopeSpecifier at this point.
+ if (!TemplateTypeTy && Tok.isNot(tok::identifier)
+ && Tok.isNot(tok::annot_decltype)) {
Diag(Tok, diag::err_expected_member_or_base_name);
return true;
}
- // Get the identifier. This may be a member name or a class name,
- // but we'll let the semantic analysis determine which it is.
- IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0;
- SourceLocation IdLoc = ConsumeToken();
+ IdentifierInfo *II = 0;
+ DeclSpec DS(AttrFactory);
+ SourceLocation IdLoc = Tok.getLocation();
+ if (Tok.is(tok::annot_decltype)) {
+ // Get the decltype expression, if there is one.
+ ParseDecltypeSpecifier(DS);
+ } else {
+ if (Tok.is(tok::identifier))
+ // Get the identifier. This may be a member name or a class name,
+ // but we'll let the semantic analysis determine which it is.
+ II = Tok.getIdentifierInfo();
+ ConsumeToken();
+ }
+
// Parse the '('.
if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
@@ -2437,8 +2450,8 @@
EllipsisLoc = ConsumeToken();
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
- TemplateTypeTy, IdLoc, InitList.take(),
- EllipsisLoc);
+ TemplateTypeTy, DS, IdLoc,
+ InitList.take(), EllipsisLoc);
} else if(Tok.is(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
@@ -2458,7 +2471,7 @@
EllipsisLoc = ConsumeToken();
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
- TemplateTypeTy, IdLoc,
+ TemplateTypeTy, DS, IdLoc,
T.getOpenLocation(), ArgExprs.take(),
ArgExprs.size(), T.getCloseLocation(),
EllipsisLoc);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b706cdc..3f8f585 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1722,11 +1722,13 @@
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
SourceLocation IdLoc,
Expr *InitList,
SourceLocation EllipsisLoc) {
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
- IdLoc, MultiInitializer(InitList), EllipsisLoc);
+ DS, IdLoc, MultiInitializer(InitList),
+ EllipsisLoc);
}
/// \brief Handle a C++ member initializer using parentheses syntax.
@@ -1736,14 +1738,15 @@
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
SourceLocation IdLoc,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc) {
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
- IdLoc, MultiInitializer(LParenLoc, Args, NumArgs,
- RParenLoc),
+ DS, IdLoc, MultiInitializer(LParenLoc, Args,
+ NumArgs, RParenLoc),
EllipsisLoc);
}
@@ -1779,6 +1782,7 @@
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
SourceLocation IdLoc,
const MultiInitializer &Args,
SourceLocation EllipsisLoc) {
@@ -1831,6 +1835,8 @@
if (TemplateTypeTy) {
BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
+ } else if (DS.getTypeSpecType() == TST_decltype) {
+ BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
} else {
LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
LookupParsedName(R, S, &SS);