aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Blaikie <dblaikie@gmail.com>2012-01-24 06:03:59 +0000
committerDavid Blaikie <dblaikie@gmail.com>2012-01-24 06:03:59 +0000
commitf211662199c87461f3b1475a549ab439c63ca83b (patch)
treeb85f9799d11d1211e13acdd6350f97bfb786f51b
parent5e089fe1affb63d670ea02010b104bd9fa3477a1 (diff)
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
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/Parse/ParseDeclCXX.cpp29
-rw-r--r--lib/Sema/SemaDeclCXX.cpp12
-rw-r--r--test/SemaCXX/class-base-member-init.cpp18
4 files changed, 50 insertions, 12 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index ecff2ec58d..28ae40444c 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -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);
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 050b1b19c4..14c8955949 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -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);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b706cdc9fb..3f8f585bb0 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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);
diff --git a/test/SemaCXX/class-base-member-init.cpp b/test/SemaCXX/class-base-member-init.cpp
index 9d030c28de..e84e57b747 100644
--- a/test/SemaCXX/class-base-member-init.cpp
+++ b/test/SemaCXX/class-base-member-init.cpp
@@ -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) {
+ }
+ };
+}