[cfe-commits] r80977 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/Parse/Action.h lib/AST/Decl.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp

John McCall rjmccall at apple.com
Thu Sep 3 18:14:42 PDT 2009


Author: rjmccall
Date: Thu Sep  3 20:14:41 2009
New Revision: 80977

URL: http://llvm.org/viewvc/llvm-project?rev=80977&view=rev
Log:
Correctly handle elaborated template ids.  Still not handled properly for friends.


Added:
    cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=80977&r1=80976&r2=80977&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Sep  3 20:14:41 2009
@@ -1340,6 +1340,11 @@
     }
   }
 
+  /// getTagKindForTypeSpec - Converts a type specifier (DeclSpec::TST)
+  /// into a tag kind.  It is an error to provide a type specifier
+  /// which *isn't* a tag kind here.
+  static TagKind getTagKindForTypeSpec(unsigned TypeSpec);
+
   TagKind getTagKind() const {
     return TagKind(TagDeclKind);
   }

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=80977&r1=80976&r2=80977&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Thu Sep  3 20:14:41 2009
@@ -1591,15 +1591,17 @@
   /// \param Template  A template whose specialization results in a
   /// type, e.g., a class template or template template parameter.
   /// 
-  /// \param IsSpecialization true when we are naming the class
-  /// template specialization as part of an explicit class
-  /// specialization or class template partial specialization.
+  /// \param TagSpec The tag spec that was provided as part of the
+  /// elaborated-type-specifier, or TST_unspecified if this was not
+  /// an elaborated type.
   virtual TypeResult ActOnTemplateIdType(TemplateTy Template,
                                          SourceLocation TemplateLoc,
                                          SourceLocation LAngleLoc,
                                          ASTTemplateArgsPtr TemplateArgs,
                                          SourceLocation *TemplateArgLocs,
-                                         SourceLocation RAngleLoc) {
+                                         SourceLocation RAngleLoc,
+                        DeclSpec::TST TagSpec = DeclSpec::TST_unspecified,
+                        SourceLocation TagLoc = SourceLocation()) {
     return TypeResult();
   };
 

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=80977&r1=80976&r2=80977&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Sep  3 20:14:41 2009
@@ -22,6 +22,8 @@
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
+#include "clang/Parse/DeclSpec.h"
+#include "llvm/Support/ErrorHandling.h"
 #include <vector>
 
 using namespace clang;
@@ -708,6 +710,16 @@
   return 0;
 }
 
+TagDecl::TagKind TagDecl::getTagKindForTypeSpec(unsigned TypeSpec) {
+  switch (TypeSpec) {
+  default: llvm::llvm_unreachable("unexpected type specifier");
+  case DeclSpec::TST_struct: return TK_struct;
+  case DeclSpec::TST_class: return TK_class;
+  case DeclSpec::TST_union: return TK_union;
+  case DeclSpec::TST_enum: return TK_enum;
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // RecordDecl Implementation
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=80977&r1=80976&r2=80977&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Sep  3 20:14:41 2009
@@ -606,7 +606,7 @@
   // to turn that template-id into a type.
 
   bool Owned = false;
-  if (TemplateId && TUK != Action::TUK_Reference && TUK != Action::TUK_Friend) {
+  if (TemplateId) {
     // Explicit specialization, class template partial specialization,
     // or explicit instantiation.
     ASTTemplateArgsPtr TemplateArgsPtr(Actions, 
@@ -629,6 +629,31 @@
                                       TemplateId->getTemplateArgLocations(),
                                              TemplateId->RAngleLoc, 
                                              Attr);
+    } else if (TUK == Action::TUK_Reference || TUK == Action::TUK_Friend) {
+      Action::TypeResult TypeResult =
+        Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+                                    TemplateId->TemplateNameLoc,
+                                    TemplateId->LAngleLoc,
+                                    TemplateArgsPtr,
+                                    TemplateId->getTemplateArgLocations(),
+                                    TemplateId->RAngleLoc,
+                                    TagType, StartLoc);
+
+      TemplateId->Destroy();
+
+      if (TypeResult.isInvalid()) {
+        DS.SetTypeSpecError();
+        return;
+      }
+  
+      const char *PrevSpec = 0;
+      unsigned DiagID;
+      if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, PrevSpec,
+                             DiagID, TypeResult.get()))
+        Diag(StartLoc, DiagID) << PrevSpec;
+
+      return;
+      
     } else {
       // This is an explicit specialization or a class template
       // partial specialization.

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=80977&r1=80976&r2=80977&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Sep  3 20:14:41 2009
@@ -2396,7 +2396,9 @@
                       SourceLocation LAngleLoc,
                       ASTTemplateArgsPtr TemplateArgs,
                       SourceLocation *TemplateArgLocs,
-                      SourceLocation RAngleLoc);
+                      SourceLocation RAngleLoc,
+                      DeclSpec::TST TagSpec,
+                      SourceLocation TagLoc);
   
   OwningExprResult BuildTemplateIdExpr(TemplateName Template,
                                        SourceLocation TemplateNameLoc,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=80977&r1=80976&r2=80977&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep  3 20:14:41 2009
@@ -3966,14 +3966,7 @@
          "Nameless record must be a definition!");
 
   OwnedDecl = false;
-  TagDecl::TagKind Kind;
-  switch (TagSpec) {
-  default: assert(0 && "Unknown tag type!");
-  case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;
-  case DeclSpec::TST_union:  Kind = TagDecl::TK_union; break;
-  case DeclSpec::TST_class:  Kind = TagDecl::TK_class; break;
-  case DeclSpec::TST_enum:   Kind = TagDecl::TK_enum; break;
-  }
+  TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec);
   
   if (TUK != TUK_Reference) {
     if (TemplateParameterList *TemplateParams

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=80977&r1=80976&r2=80977&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Sep  3 20:14:41 2009
@@ -1121,7 +1121,9 @@
                           SourceLocation LAngleLoc, 
                           ASTTemplateArgsPtr TemplateArgsIn,
                           SourceLocation *TemplateArgLocs,
-                          SourceLocation RAngleLoc) {
+                          SourceLocation RAngleLoc,
+                          DeclSpec::TST TagSpec,
+                          SourceLocation TagLoc) {
   TemplateName Template = TemplateD.getAsVal<TemplateName>();
 
   // Translate the parser's template argument list in our AST format.
@@ -1137,6 +1139,25 @@
   if (Result.isNull())
     return true;
 
+  // If we were given a tag specifier, verify it.
+  if (TagSpec != DeclSpec::TST_unspecified) {
+    TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec);
+
+    if (const RecordType *T = Result->getAs<RecordType>()) {
+      RecordDecl *D = T->getDecl();
+
+      IdentifierInfo *Id = D->getIdentifier();
+      assert(Id && "templated class must have an identifier");
+
+      if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) {
+        Diag(TagLoc, diag::err_use_with_wrong_tag)
+          << Id
+          << CodeModificationHint::CreateReplacement(SourceRange(TagLoc),
+                                                     D->getKindName());
+      }
+    }
+  }
+
   return Result.getAsOpaquePtr();
 }
 
@@ -2497,6 +2518,8 @@
                                        SourceLocation RAngleLoc,
                                        AttributeList *Attr,
                                MultiTemplateParamsArg TemplateParameterLists) {
+  assert(TUK == TUK_Declaration || TUK == TUK_Definition);
+
   // Find the class template we're specializing
   TemplateName Name = TemplateD.getAsVal<TemplateName>();
   ClassTemplateDecl *ClassTemplate 

Added: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp?rev=80977&view=auto

==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp Thu Sep  3 20:14:41 2009
@@ -0,0 +1,18 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// elaborated-type-specifier:
+//   class-key '::'? nested-name-specifier? 'template'? simple-template-id
+// Tests that this form is accepted by the compiler but does not follow
+// the elaborated lookup rules of [basic.lookup.elab].
+
+template <typename> class Ident {};
+
+namespace A {
+  template <typename> void Ident();
+
+  class Ident<int> AIdent; // expected-error {{refers to a function template}}
+  class ::Ident<int> AnotherIdent;
+}
+
+class Ident<int> GlobalIdent;
+union Ident<int> GlobalIdent; // expected-error {{ tag type that does not match }}





More information about the cfe-commits mailing list