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
This commit is contained in:
David Blaikie 2012-01-24 06:03:59 +00:00
Родитель 5e089fe1af
Коммит f211662199
4 изменённых файлов: 50 добавлений и 12 удалений

Просмотреть файл

@ -3507,6 +3507,7 @@ public:
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
@ -3518,6 +3519,7 @@ public:
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
Expr *InitList,
SourceLocation EllipsisLoc);
@ -3527,6 +3529,7 @@ public:
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
const MultiInitializer &Init,
SourceLocation EllipsisLoc);

Просмотреть файл

@ -2414,15 +2414,28 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
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 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
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 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
EllipsisLoc = ConsumeToken();
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
TemplateTypeTy, IdLoc,
TemplateTypeTy, DS, IdLoc,
T.getOpenLocation(), ArgExprs.take(),
ArgExprs.size(), T.getCloseLocation(),
EllipsisLoc);

Просмотреть файл

@ -1722,11 +1722,13 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
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 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
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 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
const MultiInitializer &Args,
SourceLocation EllipsisLoc) {
@ -1831,6 +1835,8 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
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);

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
class S {
public:
@ -74,3 +74,19 @@ namespace test4 {
A(long _) : a(0), d(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}}
};
}
namespace test5 {
struct Base {
Base(int);
};
struct A : Base {
A() : decltype(Base(1))(3) {
}
A(int) : Base(3), // expected-note {{previous initialization is here}}
decltype(Base(1))(2), // expected-error {{multiple initializations given for base 'decltype(test5::Base(1))' (aka 'test5::Base')}}
decltype(int())() { // expected-error {{constructor initializer 'decltype(int())' (aka 'int') does not name a class}}
}
A(float) : decltype(A())(3) {
}
};
}