From 961743326fd18776f897bf4461345dba680ef637 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 1 Jul 2009 19:21:19 +0000 Subject: [PATCH] Patch to implement template types in ctor-initializer list. Also has fix for bugzilla-4469. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74631 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/Action.h | 1 + lib/Parse/ParseDeclCXX.cpp | 21 +++++++++--- lib/Sema/Sema.h | 1 + lib/Sema/SemaDeclCXX.cpp | 8 +++-- .../class-template-ctor-initializer.cpp | 33 +++++++++++++++++++ 5 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 test/SemaTemplate/class-template-ctor-initializer.cpp diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index a8e52b2a86..24262a1126 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1205,6 +1205,7 @@ public: Scope *S, const CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, + TypeTy *TemplateTypeTy, SourceLocation IdLoc, SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 44cd5e6bc0..373d22fd9f 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1280,15 +1280,25 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) { // parse '::'[opt] nested-name-specifier[opt] CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS); - - if (Tok.isNot(tok::identifier)) { + TypeTy *TemplateTypeTy = 0; + if (Tok.is(tok::annot_template_id)) { + TemplateIdAnnotation *TemplateId + = static_cast(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); 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.getIdentifierInfo(); + IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0; SourceLocation IdLoc = ConsumeToken(); // Parse the '('. @@ -1308,7 +1318,8 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) { 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(), ArgExprs.size(), CommaLocs.data(), RParenLoc); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 7576be8af1..338221e4d4 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1899,6 +1899,7 @@ public: Scope *S, const CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, + TypeTy *TemplateTypeTy, SourceLocation IdLoc, SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index a0bc94808b..bbb173a02a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -648,6 +648,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, Scope *S, const CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, + TypeTy *TemplateTypeTy, SourceLocation IdLoc, SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, @@ -678,7 +679,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, // composed of a single identifier refers to the class member. A // mem-initializer-id for the hidden base class may be specified // using a qualified name. ] - if (!SS.getScopeRep()) { + if (!SS.getScopeRep() && !TemplateTypeTy) { // Look for a member, first. FieldDecl *Member = 0; 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. - TypeTy *BaseTy = getTypeName(*MemberOrBase, IdLoc, S, &SS); + TypeTy *BaseTy = TemplateTypeTy ? TemplateTypeTy + : getTypeName(*MemberOrBase, IdLoc, S, &SS); if (!BaseTy) return Diag(IdLoc, diag::err_mem_init_not_member_or_class) << MemberOrBase << SourceRange(IdLoc, RParenLoc); QualType BaseType = QualType::getFromOpaquePtr(BaseTy); - if (!BaseType->isRecordType()) + if (!BaseType->isRecordType() && !BaseType->isDependentType()) return Diag(IdLoc, diag::err_base_init_does_not_name_class) << BaseType << SourceRange(IdLoc, RParenLoc); diff --git a/test/SemaTemplate/class-template-ctor-initializer.cpp b/test/SemaTemplate/class-template-ctor-initializer.cpp new file mode 100644 index 0000000000..d7649f5268 --- /dev/null +++ b/test/SemaTemplate/class-template-ctor-initializer.cpp @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template struct A {}; + +template struct B : A { + B() : A() {} +}; +B x; + +template struct B1 : A { + typedef A Base; + B1() : Base() {} +}; +B1 x1; + + +template struct Tmpl { }; + +template struct TmplB { }; + +struct TmplC : Tmpl { + TmplC() : + Tmpl(), + TmplB() { } // expected-error {{type 'TmplB' is not a direct or virtual base of 'TmplC'}} +}; + + +struct TmplD : Tmpl, TmplB { + TmplD(): + Tmpl(), // expected-error {{type 'Tmpl' is not a direct or virtual base of 'TmplD'}} + TmplB() {} +}; + -- 2.40.0