зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
5e089fe1af
Коммит
f211662199
|
@ -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) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче