]> granicus.if.org Git - clang/commitdiff
Implementing parsing of template-ids as class-names, so that we can
authorDouglas Gregor <dgregor@apple.com>
Wed, 25 Feb 2009 23:52:28 +0000 (23:52 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 25 Feb 2009 23:52:28 +0000 (23:52 +0000)
derive from a class template specialization, e.g.,

  class B : public A<int> { };

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65488 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
test/SemaTemplate/class-template-id-2.cpp [new file with mode: 0644]

index 9ef23d48657ae31b90b4705ba2200201730197ae..1e3ea317dabc39874954a1c9fd993b52d9fa117b 100644 (file)
@@ -968,7 +968,8 @@ private:
 
   //===--------------------------------------------------------------------===//
   // C++ 9: classes [class] and C structs/unions.
-  TypeTy *ParseClassName(const CXXScopeSpec *SS = 0);
+  TypeTy *ParseClassName(SourceLocation &EndLocation, 
+                         const CXXScopeSpec *SS = 0);
   void ParseClassSpecifier(DeclSpec &DS, 
                            TemplateParameterLists *TemplateParams = 0);
   void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
index bdd352f341920b7fdf226ce1fd3512170e1880ce..b961bc2dc0932897ff2e6f64be48acb33f3e50b2 100644 (file)
@@ -1822,7 +1822,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
         if (Tok.is(tok::identifier)) {
           // FIXME: Inaccurate.
           SourceLocation NameLoc = Tok.getLocation();
-          if (TypeTy *Type = ParseClassName()) {
+          SourceLocation EndLoc;
+          if (TypeTy *Type = ParseClassName(EndLoc)) {
             D.setDestructor(Type, TildeLoc, NameLoc);
           } else {
             D.SetIdentifier(0, TildeLoc);
index 3ef3f93fdfd1a8d4f1fd608d95fe2308a2438d0b..9f704d2ea8a5ec70be223acbadb618438d2f1946 100644 (file)
@@ -216,16 +216,33 @@ Parser::DeclTy *Parser::ParseUsingDeclaration(unsigned Context,
 /// ParseClassName - Parse a C++ class-name, which names a class. Note
 /// that we only check that the result names a type; semantic analysis
 /// will need to verify that the type names a class. The result is
-/// either a type or NULL, dependending on whether a type name was
+/// either a type or NULL, depending on whether a type name was
 /// found.
 ///
 ///       class-name: [C++ 9.1]
 ///         identifier
-///         template-id   [TODO]
+///         simple-template-id
 /// 
-Parser::TypeTy *Parser::ParseClassName(const CXXScopeSpec *SS) {
-  // Parse the class-name.
-  // FIXME: Alternatively, parse a simple-template-id.
+Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation,
+                                       const CXXScopeSpec *SS) {
+  // Check whether we have a template-id that names a type.
+  if (Tok.is(tok::annot_template_id)) {
+    TemplateIdAnnotation *TemplateId 
+      = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+    if (TemplateId->Kind == TNK_Class_template) {
+      if (AnnotateTemplateIdTokenAsType(SS))
+        return 0;
+
+      assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
+      TypeTy *Type = Tok.getAnnotationValue();
+      EndLocation = Tok.getAnnotationEndLoc();
+      ConsumeToken();
+      return Type;
+    }
+
+    // Fall through to produce an error below.
+  }
+
   if (Tok.isNot(tok::identifier)) {
     Diag(Tok, diag::err_expected_class_name);
     return 0;
@@ -240,8 +257,7 @@ Parser::TypeTy *Parser::ParseClassName(const CXXScopeSpec *SS) {
   }
 
   // Consume the identifier.
-  ConsumeToken();
-
+  EndLocation = ConsumeToken();
   return Type;
 }
 
@@ -510,12 +526,13 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclTy *ClassDecl)
   SourceLocation BaseLoc = Tok.getLocation();
 
   // Parse the class-name.
-  TypeTy *BaseType = ParseClassName(&SS);
+  SourceLocation EndLocation;
+  TypeTy *BaseType = ParseClassName(EndLocation, &SS);
   if (!BaseType)
     return true;
   
   // Find the complete source range for the base-specifier.  
-  SourceRange Range(StartLoc, BaseLoc);
+  SourceRange Range(StartLoc, EndLocation);
   
   // Notify semantic analysis that we have parsed a complete
   // base-specifier.
diff --git a/test/SemaTemplate/class-template-id-2.cpp b/test/SemaTemplate/class-template-id-2.cpp
new file mode 100644 (file)
index 0000000..dee4735
--- /dev/null
@@ -0,0 +1,23 @@
+// RUN: clang -fsyntax-only -verify %s
+namespace N {
+  template<typename T> class A; 
+
+  template<> class A<int> { };
+
+  class B : public A<int> { };
+}
+
+class C1 : public N::A<int> { };
+
+class C2 : public N::A<float> { }; // expected-error{{base class has incomplete type}} \
+           // FIXME: expected-note{{forward declaration of 'class A'}}
+
+struct D1 {
+  operator N::A<int>();
+};
+
+namespace N {
+  struct D2 {
+    operator A<int>();
+  };
+}