]> granicus.if.org Git - clang/commitdiff
When we encounter a dependent template name within a
authorDouglas Gregor <dgregor@apple.com>
Mon, 28 Feb 2011 00:04:36 +0000 (00:04 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 28 Feb 2011 00:04:36 +0000 (00:04 +0000)
nested-name-specifier, e.g.,

  T::template apply<U>::

represent the dependent template name specialization as a
DependentTemplateSpecializationType, rather than a
TemplateSpecializationType with a dependent TemplateName.

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

include/clang/Sema/Sema.h
lib/AST/ASTContext.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/Type.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/Parser.cpp
lib/Sema/SemaCXXScopeSpec.cpp
lib/Sema/TreeTransform.h

index b124bbe475871de80970c53cfcbdb4dbf34244a4..d215df92a027e5c0585947001ff0793eb6d8a63e 100644 (file)
@@ -2659,25 +2659,41 @@ public:
                                  ParsedType ObjectType,
                                  bool EnteringContext);
 
-  /// \brief The parser has parsed a nested-name-specifier 'type::'.
+  /// \brief The parser has parsed a nested-name-specifier 
+  /// 'template[opt] template-name < template-args >::'.
   ///
   /// \param S The scope in which this nested-name-specifier occurs.
   ///
-  /// \param Type The type, which will be a template specialization
-  /// type, preceding the '::'.
-  ///
-  /// \param CCLoc The location of the '::'.
+  /// \param TemplateLoc The location of the 'template' keyword, if any.
   ///
   /// \param SS The nested-name-specifier, which is both an input
   /// parameter (the nested-name-specifier before this type) and an
   /// output parameter (containing the full nested-name-specifier,
   /// including this new type).
+  /// 
+  /// \param TemplateLoc the location of the 'template' keyword, if any.
+  /// \param TemplateName The template name.
+  /// \param TemplateNameLoc The location of the template name.
+  /// \param LAngleLoc The location of the opening angle bracket  ('<').
+  /// \param TemplateArgs The template arguments.
+  /// \param RAngleLoc The location of the closing angle bracket  ('>').
+  /// \param CCLoc The location of the '::'.
+  
+  /// \param EnteringContext Whether we're entering the context of the 
+  /// nested-name-specifier.
+  ///
   ///
   /// \returns true if an error occurred, false otherwise.
   bool ActOnCXXNestedNameSpecifier(Scope *S,
-                                   ParsedType Type,
+                                   SourceLocation TemplateLoc, 
+                                   CXXScopeSpec &SS, 
+                                   TemplateTy Template,
+                                   SourceLocation TemplateNameLoc,
+                                   SourceLocation LAngleLoc,
+                                   ASTTemplateArgsPtr TemplateArgs,
+                                   SourceLocation RAngleLoc,
                                    SourceLocation CCLoc,
-                                   CXXScopeSpec &SS);
+                                   bool EnteringContext);
 
   /// \brief Given a C++ nested-name-specifier, produce an annotation value
   /// that the parser can use later to reconstruct the given 
index 9c2455034d6800b904fd7b0575adabd8b64c40de..ef9e7b313383ab1d3f7b875e99eab783abd755c2 100644 (file)
@@ -2377,7 +2377,8 @@ ASTContext::getDependentTemplateSpecializationType(
                                  const IdentifierInfo *Name,
                                  unsigned NumArgs,
                                  const TemplateArgument *Args) const {
-  assert(NNS->isDependent() && "nested-name-specifier must be dependent");
+  assert((!NNS || NNS->isDependent()) && 
+         "nested-name-specifier must be dependent");
 
   llvm::FoldingSetNodeID ID;
   DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS,
@@ -3014,10 +3015,11 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
           = T->getAs<DependentTemplateSpecializationType>()) {
       NestedNameSpecifier *Prefix
         = getCanonicalNestedNameSpecifier(DTST->getQualifier());
-      TemplateName Name
-        = getDependentTemplateName(Prefix, DTST->getIdentifier());
-      T = getTemplateSpecializationType(Name, 
-                                        DTST->getArgs(), DTST->getNumArgs());
+      
+      T = getDependentTemplateSpecializationType(DTST->getKeyword(),
+                                                 Prefix, DTST->getIdentifier(),
+                                                 DTST->getNumArgs(),
+                                                 DTST->getArgs());
       T = getCanonicalType(T);
     }
     
index 939ca7a924aa03eb9c432ea4d077333ee18a5115..8474ea363325f396071524ff2d9cc7b17177ed19 100644 (file)
@@ -625,6 +625,17 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
                            TST->getNumArgs());
         addSubstitution(QualType(TST, 0));
       }
+    } else if (const DependentTemplateSpecializationType *DTST
+                         = dyn_cast<DependentTemplateSpecializationType>(QTy)) {
+      TemplateName Template
+        = getASTContext().getDependentTemplateName(DTST->getQualifier(), 
+                                                   DTST->getIdentifier());
+      mangleTemplatePrefix(Template);
+
+      // FIXME: GCC does not appear to mangle the template arguments when
+      // the template in question is a dependent template name. Should we
+      // emulate that badness?
+      mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs());
     } else {
       // We use the QualType mangle type variant here because it handles
       // substitutions.
@@ -1596,7 +1607,7 @@ void CXXNameMangler::mangleType(const DependentNameType *T) {
 }
 
 void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
-  // Dependently-scoped template types are always nested
+  // Dependently-scoped template types are nested if they have a prefix.
   Out << 'N';
 
   // TODO: avoid making this TemplateName.
index b03314e11d13f704762052401122be3d284061fa..d1136adbab2aa7b206d3895a6a9680d3cc4b14a9 100644 (file)
@@ -1040,9 +1040,9 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType(
                          QualType Canon)
   : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true,
                     /*VariablyModified=*/false,
-                    NNS->containsUnexpandedParameterPack()),
+                    NNS && NNS->containsUnexpandedParameterPack()),
     NNS(NNS), Name(Name), NumArgs(NumArgs) {
-  assert(NNS && NNS->isDependent() &&
+  assert((!NNS || NNS->isDependent()) &&
          "DependentTemplateSpecializatonType requires dependent qualifier");
   for (unsigned I = 0; I != NumArgs; ++I) {
     if (Args[I].containsUnexpandedParameterPack())
index d8db711809edbefdbc64b9d8551204b9c14ec1ef..a059e0b75a8b81ec42354848337cdbcc3e0e5bb7 100644 (file)
@@ -199,29 +199,32 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
 
       if (TemplateId->Kind == TNK_Type_template ||
           TemplateId->Kind == TNK_Dependent_template_name) {
-        AnnotateTemplateIdTokenAsType(&SS);
-
-        assert(Tok.is(tok::annot_typename) &&
-               "AnnotateTemplateIdTokenAsType isn't working");
-        Token TypeToken = Tok;
+        // Consume the template-id token.
         ConsumeToken();
+        
         assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
         SourceLocation CCLoc = ConsumeToken();
 
         if (!HasScopeSpecifier)
           HasScopeSpecifier = true;
-
-        if (ParsedType T = getTypeAnnotation(TypeToken)) {
-          if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), T, CCLoc, SS))
-            SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc));
-          
-          continue;
-        } else {
-          SourceLocation Start = SS.getBeginLoc().isValid()? SS.getBeginLoc() 
-                                                           : CCLoc;
-          SS.SetInvalid(SourceRange(Start, CCLoc));
-        }
         
+        ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+                                           TemplateId->getTemplateArgs(),
+                                           TemplateId->NumArgs);
+        
+        if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(),
+                                                /*FIXME:*/SourceLocation(),
+                                                SS, 
+                                                TemplateId->Template,
+                                                TemplateId->TemplateNameLoc,
+                                                TemplateId->LAngleLoc,
+                                                TemplateArgsPtr,
+                                                TemplateId->RAngleLoc,
+                                                CCLoc,
+                                                EnteringContext))
+          SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc));
+        
+        TemplateId->Destroy();
         continue;
       }
 
index 69d1853c0fe1cd756ff43ce5e828d376410b77ae..3ed070321dae5cc07649ef07dccf83dd2f755ffa 100644 (file)
@@ -1062,6 +1062,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
                                      TemplateId->LAngleLoc,
                                      TemplateArgsPtr, 
                                      TemplateId->RAngleLoc);
+      TemplateId->Destroy();
     } else {
       Diag(Tok, diag::err_expected_type_name_after_typename)
         << SS.getRange();
index 7ad4b459451dfe6cc92380ae9e5043b082ef2db1..8eb628f59bc6340f962bfa5ee4fde99ce01100b6 100644 (file)
@@ -641,20 +641,73 @@ bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
 }
 
 bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
-                                       ParsedType Type,
+                                       SourceLocation TemplateLoc, 
+                                       CXXScopeSpec &SS, 
+                                       TemplateTy Template,
+                                       SourceLocation TemplateNameLoc,
+                                       SourceLocation LAngleLoc,
+                                       ASTTemplateArgsPtr TemplateArgsIn,
+                                       SourceLocation RAngleLoc,
                                        SourceLocation CCLoc,
-                                       CXXScopeSpec &SS) {
+                                       bool EnteringContext) {
   if (SS.isInvalid())
     return true;
   
-  TypeSourceInfo *TSInfo;
-  QualType T = GetTypeFromParser(Type, &TSInfo);
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+  if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){
+    // Handle a dependent template specialization for which we cannot resolve
+    // the template name.
+    assert(DTN->getQualifier()
+             == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+    QualType T = Context.getDependentTemplateSpecializationType(ETK_None,
+                                                                DTN->getQualifier(),
+                                                                DTN->getIdentifier(),
+                                                                TemplateArgs);
+    
+    // Create source-location information for this type.
+    TypeLocBuilder Builder;
+    DependentTemplateSpecializationTypeLoc SpecTL 
+      = Builder.push<DependentTemplateSpecializationTypeLoc>(T);
+    SpecTL.setLAngleLoc(LAngleLoc);
+    SpecTL.setRAngleLoc(RAngleLoc);
+    SpecTL.setKeywordLoc(SourceLocation());
+    SpecTL.setNameLoc(TemplateNameLoc);
+    for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+      SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+    
+    SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), 
+              CCLoc);
+    return false;
+  }
+  
+  // We were able to resolve the template name to an actual template. 
+  // Build an appropriate nested-name-specifier.
+  QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc, 
+                                   TemplateArgs);
   if (T.isNull())
     return true;
 
-  assert(TSInfo && "Not TypeSourceInfo in nested-name-specifier?");
-  // FIXME: location of the 'template' keyword?
-  SS.Extend(Context, SourceLocation(), TSInfo->getTypeLoc(), CCLoc);
+  // FIXME: Template aliases will need to check the resulting type to make
+  // sure that it's either dependent or a tag type.
+
+  // Provide source-location information for the template specialization 
+  // type.
+  TypeLocBuilder Builder;
+  TemplateSpecializationTypeLoc SpecTL 
+    = Builder.push<TemplateSpecializationTypeLoc>(T);
+  
+  SpecTL.setLAngleLoc(LAngleLoc);
+  SpecTL.setRAngleLoc(RAngleLoc);
+  SpecTL.setTemplateNameLoc(TemplateNameLoc);
+  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+    SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+
+
+  SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), 
+            CCLoc);
   return false;
 }
 
index 57a44ad9d984f5461024c42e50d3944bfe18a3d6..fa4637a27e8a85d8775c551cf3a2e9effeaee071 100644 (file)
@@ -754,6 +754,9 @@ public:
       getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
     if (T.isNull()) return QualType();
 
+    if (Keyword == ETK_None)
+      return T;
+    
     // NOTE: NNS is already recorded in template specialization type T.
     return SemaRef.Context.getElaboratedType(Keyword, /*NNS=*/0, T);
   }