Patch to implement template types in ctor-initializer list.
Also has fix for bugzilla-4469. llvm-svn: 74631
This commit is contained in:
@@ -1205,6 +1205,7 @@ public:
|
|||||||
Scope *S,
|
Scope *S,
|
||||||
const CXXScopeSpec &SS,
|
const CXXScopeSpec &SS,
|
||||||
IdentifierInfo *MemberOrBase,
|
IdentifierInfo *MemberOrBase,
|
||||||
|
TypeTy *TemplateTypeTy,
|
||||||
SourceLocation IdLoc,
|
SourceLocation IdLoc,
|
||||||
SourceLocation LParenLoc,
|
SourceLocation LParenLoc,
|
||||||
ExprTy **Args, unsigned NumArgs,
|
ExprTy **Args, unsigned NumArgs,
|
||||||
|
|||||||
@@ -1280,15 +1280,25 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
|
|||||||
// parse '::'[opt] nested-name-specifier[opt]
|
// parse '::'[opt] nested-name-specifier[opt]
|
||||||
CXXScopeSpec SS;
|
CXXScopeSpec SS;
|
||||||
ParseOptionalCXXScopeSpecifier(SS);
|
ParseOptionalCXXScopeSpecifier(SS);
|
||||||
|
TypeTy *TemplateTypeTy = 0;
|
||||||
if (Tok.isNot(tok::identifier)) {
|
if (Tok.is(tok::annot_template_id)) {
|
||||||
|
TemplateIdAnnotation *TemplateId
|
||||||
|
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
|
||||||
|
if (TemplateId->Kind == TNK_Type_template) {
|
||||||
|
AnnotateTemplateIdTokenAsType(&SS);
|
||||||
|
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
|
||||||
|
TemplateTypeTy = Tok.getAnnotationValue();
|
||||||
|
}
|
||||||
|
// FIXME. May need to check for TNK_Dependent_template as well.
|
||||||
|
}
|
||||||
|
if (!TemplateTypeTy && Tok.isNot(tok::identifier)) {
|
||||||
Diag(Tok, diag::err_expected_member_or_base_name);
|
Diag(Tok, diag::err_expected_member_or_base_name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the identifier. This may be a member name or a class name,
|
// Get the identifier. This may be a member name or a class name,
|
||||||
// but we'll let the semantic analysis determine which it is.
|
// but we'll let the semantic analysis determine which it is.
|
||||||
IdentifierInfo *II = Tok.getIdentifierInfo();
|
IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0;
|
||||||
SourceLocation IdLoc = ConsumeToken();
|
SourceLocation IdLoc = ConsumeToken();
|
||||||
|
|
||||||
// Parse the '('.
|
// Parse the '('.
|
||||||
@@ -1308,7 +1318,8 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
|
|||||||
|
|
||||||
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
|
|
||||||
return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, SS, II, IdLoc,
|
return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, SS, II,
|
||||||
|
TemplateTypeTy, IdLoc,
|
||||||
LParenLoc, ArgExprs.take(),
|
LParenLoc, ArgExprs.take(),
|
||||||
ArgExprs.size(), CommaLocs.data(),
|
ArgExprs.size(), CommaLocs.data(),
|
||||||
RParenLoc);
|
RParenLoc);
|
||||||
|
|||||||
@@ -1899,6 +1899,7 @@ public:
|
|||||||
Scope *S,
|
Scope *S,
|
||||||
const CXXScopeSpec &SS,
|
const CXXScopeSpec &SS,
|
||||||
IdentifierInfo *MemberOrBase,
|
IdentifierInfo *MemberOrBase,
|
||||||
|
TypeTy *TemplateTypeTy,
|
||||||
SourceLocation IdLoc,
|
SourceLocation IdLoc,
|
||||||
SourceLocation LParenLoc,
|
SourceLocation LParenLoc,
|
||||||
ExprTy **Args, unsigned NumArgs,
|
ExprTy **Args, unsigned NumArgs,
|
||||||
|
|||||||
@@ -648,6 +648,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
|
|||||||
Scope *S,
|
Scope *S,
|
||||||
const CXXScopeSpec &SS,
|
const CXXScopeSpec &SS,
|
||||||
IdentifierInfo *MemberOrBase,
|
IdentifierInfo *MemberOrBase,
|
||||||
|
TypeTy *TemplateTypeTy,
|
||||||
SourceLocation IdLoc,
|
SourceLocation IdLoc,
|
||||||
SourceLocation LParenLoc,
|
SourceLocation LParenLoc,
|
||||||
ExprTy **Args, unsigned NumArgs,
|
ExprTy **Args, unsigned NumArgs,
|
||||||
@@ -678,7 +679,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
|
|||||||
// composed of a single identifier refers to the class member. A
|
// composed of a single identifier refers to the class member. A
|
||||||
// mem-initializer-id for the hidden base class may be specified
|
// mem-initializer-id for the hidden base class may be specified
|
||||||
// using a qualified name. ]
|
// using a qualified name. ]
|
||||||
if (!SS.getScopeRep()) {
|
if (!SS.getScopeRep() && !TemplateTypeTy) {
|
||||||
// Look for a member, first.
|
// Look for a member, first.
|
||||||
FieldDecl *Member = 0;
|
FieldDecl *Member = 0;
|
||||||
DeclContext::lookup_result Result
|
DeclContext::lookup_result Result
|
||||||
@@ -695,13 +696,14 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// It didn't name a member, so see if it names a class.
|
// It didn't name a member, so see if it names a class.
|
||||||
TypeTy *BaseTy = getTypeName(*MemberOrBase, IdLoc, S, &SS);
|
TypeTy *BaseTy = TemplateTypeTy ? TemplateTypeTy
|
||||||
|
: getTypeName(*MemberOrBase, IdLoc, S, &SS);
|
||||||
if (!BaseTy)
|
if (!BaseTy)
|
||||||
return Diag(IdLoc, diag::err_mem_init_not_member_or_class)
|
return Diag(IdLoc, diag::err_mem_init_not_member_or_class)
|
||||||
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
|
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
|
||||||
|
|
||||||
QualType BaseType = QualType::getFromOpaquePtr(BaseTy);
|
QualType BaseType = QualType::getFromOpaquePtr(BaseTy);
|
||||||
if (!BaseType->isRecordType())
|
if (!BaseType->isRecordType() && !BaseType->isDependentType())
|
||||||
return Diag(IdLoc, diag::err_base_init_does_not_name_class)
|
return Diag(IdLoc, diag::err_base_init_does_not_name_class)
|
||||||
<< BaseType << SourceRange(IdLoc, RParenLoc);
|
<< BaseType << SourceRange(IdLoc, RParenLoc);
|
||||||
|
|
||||||
|
|||||||
33
clang/test/SemaTemplate/class-template-ctor-initializer.cpp
Normal file
33
clang/test/SemaTemplate/class-template-ctor-initializer.cpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// RUN: clang-cc -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
template<class X> struct A {};
|
||||||
|
|
||||||
|
template<class X> struct B : A<X> {
|
||||||
|
B() : A<X>() {}
|
||||||
|
};
|
||||||
|
B<int> x;
|
||||||
|
|
||||||
|
template<class X> struct B1 : A<X> {
|
||||||
|
typedef A<X> Base;
|
||||||
|
B1() : Base() {}
|
||||||
|
};
|
||||||
|
B1<int> x1;
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T> struct Tmpl { };
|
||||||
|
|
||||||
|
template<typename T> struct TmplB { };
|
||||||
|
|
||||||
|
struct TmplC : Tmpl<int> {
|
||||||
|
TmplC() :
|
||||||
|
Tmpl<int>(),
|
||||||
|
TmplB<int>() { } // expected-error {{type 'TmplB<int>' is not a direct or virtual base of 'TmplC'}}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct TmplD : Tmpl<char>, TmplB<char> {
|
||||||
|
TmplD():
|
||||||
|
Tmpl<int>(), // expected-error {{type 'Tmpl<int>' is not a direct or virtual base of 'TmplD'}}
|
||||||
|
TmplB<char>() {}
|
||||||
|
};
|
||||||
|
|
||||||
Reference in New Issue
Block a user