[cfe-commits] r126589 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Parse/Parser.cpp lib/Sema/SemaTemplate.cpp

Douglas Gregor dgregor at apple.com
Sun Feb 27 14:46:49 PST 2011


Author: dgregor
Date: Sun Feb 27 16:46:49 2011
New Revision: 126589

URL: http://llvm.org/viewvc/llvm-project?rev=126589&view=rev
Log:
Eliminate a silly little Parse/Sema dance when parsing typename
specifiers such as

  typename T::template apply<U>

Previously, we would turn T::template apply<U> into a
TemplateSpecializationType. Then, we'd reprocess that
TemplateSpecializationType and turn it into either a
TemplateSpecializationType wrapped in an ElaboratedType (when we could
resolve "apply" to a template declaration) or a
DependentTemplateSpecializationType. We now produce the same ASTs but
without generating the intermediate TemplateSpecializationType.

The end goal here is to avoid generating TemplateSpecializationTypes
with dependent template-names, ever. We're not there yet.




Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=126589&r1=126588&r2=126589&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sun Feb 27 16:46:49 2011
@@ -3384,11 +3384,20 @@
   /// \param TypenameLoc the location of the 'typename' keyword
   /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
   /// \param TemplateLoc the location of the 'template' keyword, if any.
-  /// \param Ty the type that the typename specifier refers to.
+  /// \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  ('>').
   TypeResult
   ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, 
-                    const CXXScopeSpec &SS, SourceLocation TemplateLoc, 
-                    ParsedType Ty);
+                    const CXXScopeSpec &SS, 
+                    SourceLocation TemplateLoc, 
+                    TemplateTy Template,
+                    SourceLocation TemplateNameLoc,
+                    SourceLocation LAngleLoc,
+                    ASTTemplateArgsPtr TemplateArgs,
+                    SourceLocation RAngleLoc);
 
   QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
                              NestedNameSpecifier *NNS,

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=126589&r1=126588&r2=126589&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sun Feb 27 16:46:49 2011
@@ -1051,15 +1051,17 @@
         return true;
       }
 
-      AnnotateTemplateIdTokenAsType(0);
-      assert(Tok.is(tok::annot_typename) &&
-             "AnnotateTemplateIdTokenAsType isn't working properly");
-      if (Tok.getAnnotationValue())
-        Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, 
-                                       SourceLocation(),
-                                       getTypeAnnotation(Tok));
-      else
-        Ty = true;
+      ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+                                         TemplateId->getTemplateArgs(),
+                                         TemplateId->NumArgs);
+      
+      Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS,
+                                     /*FIXME:*/SourceLocation(),
+                                     TemplateId->Template,
+                                     TemplateId->TemplateNameLoc,
+                                     TemplateId->LAngleLoc,
+                                     TemplateArgsPtr, 
+                                     TemplateId->RAngleLoc);
     } else {
       Diag(Tok, diag::err_expected_type_name_after_typename)
         << SS.getRange();

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=126589&r1=126588&r2=126589&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sun Feb 27 16:46:49 2011
@@ -5923,75 +5923,87 @@
 }
 
 TypeResult
-Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
-                        const CXXScopeSpec &SS, SourceLocation TemplateLoc,
-                        ParsedType Ty) {
+Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, 
+                        const CXXScopeSpec &SS, 
+                        SourceLocation TemplateLoc, 
+                        TemplateTy TemplateIn,
+                        SourceLocation TemplateNameLoc,
+                        SourceLocation LAngleLoc,
+                        ASTTemplateArgsPtr TemplateArgsIn,
+                        SourceLocation RAngleLoc) {
   if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
       !getLangOptions().CPlusPlus0x)
     Diag(TypenameLoc, diag::ext_typename_outside_of_template)
-      << FixItHint::CreateRemoval(TypenameLoc);
-
-  TypeSourceInfo *InnerTSI = 0;
-  QualType T = GetTypeFromParser(Ty, &InnerTSI);
-
-  assert(isa<TemplateSpecializationType>(T) &&
-         "Expected a template specialization type");
-
+    << FixItHint::CreateRemoval(TypenameLoc);
+  
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+  
+  TemplateName Template = TemplateIn.get();
+  
   if (computeDeclContext(SS, false)) {
     // If we can compute a declaration context, then the "typename"
     // keyword was superfluous. Just build an ElaboratedType to keep
     // track of the nested-name-specifier.
-
-    // Push the inner type, preserving its source locations if possible.
+    
+    QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
+    if (T.isNull())
+      return true;
+    
+    // Provide source-location information for the template specialization 
+    // type.
     TypeLocBuilder Builder;
-    if (InnerTSI)
-      Builder.pushFullCopy(InnerTSI->getTypeLoc());
-    else
-      Builder.push<TemplateSpecializationTypeLoc>(T).initialize(Context,
-                                                                TemplateLoc);
-
+    TemplateSpecializationTypeLoc SpecTL 
+    = Builder.push<TemplateSpecializationTypeLoc>(T);
+    
+    // FIXME: No place to set the location of the 'template' keyword!
+    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());
+    
+    // FIXME: This is a hack. We really want to push the nested-name-specifier
+    // into TemplateSpecializationType.
+    
     /* Note: NNS already embedded in template specialization type T. */
     T = Context.getElaboratedType(ETK_Typename, /*NNS=*/0, T);
     ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
     TL.setKeywordLoc(TypenameLoc);
     TL.setQualifierRange(SS.getRange());
-
+    
     TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
     return CreateParsedType(T, TSI);
   }
-
-  // TODO: it's really silly that we make a template specialization
-  // type earlier only to drop it again here.
-  const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T);
-  DependentTemplateName *DTN =
-    TST->getTemplateName().getAsDependentTemplateName();
+  
+  // Construct a dependent template specialization type.
+  DependentTemplateName *DTN = Template.getAsDependentTemplateName();
   assert(DTN && "dependent template has non-dependent name?");
   assert(DTN->getQualifier()
          == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
-  T = Context.getDependentTemplateSpecializationType(ETK_Typename,
-                                                     DTN->getQualifier(),
-                                                     DTN->getIdentifier(),
-                                                     TST->getNumArgs(),
-                                                     TST->getArgs());
-  TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
-  DependentTemplateSpecializationTypeLoc TL =
-    cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc());
-  if (InnerTSI) {
-    TemplateSpecializationTypeLoc TSTL =
-      cast<TemplateSpecializationTypeLoc>(InnerTSI->getTypeLoc());
-    TL.setLAngleLoc(TSTL.getLAngleLoc());
-    TL.setRAngleLoc(TSTL.getRAngleLoc());
-    for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I)
-      TL.setArgLocInfo(I, TSTL.getArgLocInfo(I));
-  } else {
-    // FIXME: Poor source-location information here.
-    TL.initializeLocal(Context, TemplateLoc);
-  }
-  TL.setKeywordLoc(TypenameLoc);
-  TL.setQualifierRange(SS.getRange());
-  return CreateParsedType(T, TSI);
+  QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename,
+                                                          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(TypenameLoc);
+  SpecTL.setNameLoc(TemplateNameLoc);
+  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+    SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+  
+  // FIXME: Nested-name-specifier source locations.
+  SpecTL.setQualifierRange(SS.getRange());
+  return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
 }
 
+
 /// \brief Build the type that describes a C++ typename specifier,
 /// e.g., "typename T::type".
 QualType





More information about the cfe-commits mailing list