]> granicus.if.org Git - clang/commitdiff
Patch to implement template types in ctor-initializer list.
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 1 Jul 2009 19:21:19 +0000 (19:21 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 1 Jul 2009 19:21:19 +0000 (19:21 +0000)
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
lib/Parse/ParseDeclCXX.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
test/SemaTemplate/class-template-ctor-initializer.cpp [new file with mode: 0644]

index a8e52b2a86eba63434d535833016ad9046310500..24262a1126c95457f4b84d654297c0302cf0a918 100644 (file)
@@ -1205,6 +1205,7 @@ public:
                                             Scope *S,
                                             const CXXScopeSpec &SS,
                                             IdentifierInfo *MemberOrBase,
+                                            TypeTy *TemplateTypeTy,
                                             SourceLocation IdLoc,
                                             SourceLocation LParenLoc,
                                             ExprTy **Args, unsigned NumArgs,
index 44cd5e6bc0c05f7649d60be316a7c5cdafda63d0..373d22fd9f4fdeef867305141c9109d988dd4abe 100644 (file)
@@ -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<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);
     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);
index 7576be8af14739916863ed000081b640aaf2c620..338221e4d4118c253585ab826769503d8965f392 100644 (file)
@@ -1899,6 +1899,7 @@ public:
                                             Scope *S,
                                             const CXXScopeSpec &SS,
                                             IdentifierInfo *MemberOrBase,
+                                            TypeTy *TemplateTypeTy,
                                             SourceLocation IdLoc,
                                             SourceLocation LParenLoc,
                                             ExprTy **Args, unsigned NumArgs,
index a0bc94808bbed297263772c166c1ac8355072cda..bbb173a02adc5f2e25defd9f1202075762aa995c 100644 (file)
@@ -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 (file)
index 0000000..d7649f5
--- /dev/null
@@ -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>() {}
+};
+