[cfe-commits] r106167 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/ParseExprCXX.cpp lib/Parse/ParseTemplate.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/TreeTransform.h test/SemaTemplate/nested-name-spec-template.cpp

Douglas Gregor dgregor at apple.com
Wed Jun 16 16:00:59 PDT 2010


Author: dgregor
Date: Wed Jun 16 18:00:59 2010
New Revision: 106167

URL: http://llvm.org/viewvc/llvm-project?rev=106167&view=rev
Log:
When we see a 'template' disambiguator that marks the next identifier
(or operator-function-id) as a template, but the context is actually
non-dependent or the current instantiation, allow us to use knowledge
of what kind of template it is, e.g., type template vs. function
template, for further syntactic disambiguation. This allows us to
parse properly in the presence of stray "template" keywords, which is
necessary in C++0x and it's good recovery in C++98/03.

Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=106167&r1=106166&r2=106167&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Jun 16 18:00:59 2010
@@ -2006,13 +2006,21 @@
   ///
   /// \param EnteringContext whether we are entering the context of this
   /// template.
-  virtual TemplateTy ActOnDependentTemplateName(Scope *S, 
+  ///
+  /// \param Template Will be set to the dependent template name, on success.
+  ///
+  /// \returns The kind of template name that was produced. Generally, this will
+  /// be \c TNK_Dependent_template_name. However, if the nested-name-specifier
+  /// is not dependent, or refers to the current instantiation, then we may
+  /// be able to resolve the template kind more specifically.
+  virtual TemplateNameKind ActOnDependentTemplateName(Scope *S, 
                                                 SourceLocation TemplateKWLoc,
                                                 CXXScopeSpec &SS,
                                                 UnqualifiedId &Name,
                                                 TypeTy *ObjectType,
-                                                bool EnteringContext) {
-    return TemplateTy();
+                                                bool EnteringContext,
+                                                TemplateTy &Template) {
+    return TNK_Non_template;
   }
 
   /// \brief Process the declaration or definition of an explicit

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=106167&r1=106166&r2=106167&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Jun 16 18:00:59 2010
@@ -164,14 +164,18 @@
       
       // Commit to parsing the template-id.
       TPA.Commit();
-      TemplateTy Template
-        = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, 
-                                             TemplateName,
-                                             ObjectType, EnteringContext);
-      if (!Template)
-        return true;
-      if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
-                                  &SS, TemplateName, TemplateKWLoc, false))
+      TemplateTy Template;
+      if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(CurScope, 
+                                                                TemplateKWLoc, 
+                                                                    SS, 
+                                                                  TemplateName,
+                                                                    ObjectType, 
+                                                                EnteringContext,
+                                                                    Template)) {
+        if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, 
+                                    TemplateKWLoc, false))
+          return true;
+      } else
         return true;
 
       continue;
@@ -320,19 +324,20 @@
           << II.getName()
           << FixItHint::CreateInsertion(Tok.getLocation(), "template ");
         
-        Template = Actions.ActOnDependentTemplateName(CurScope, 
-                                                      Tok.getLocation(), SS, 
-                                                      TemplateName, ObjectType,
-                                                      EnteringContext);
-        if (!Template.get())
+        if (TemplateNameKind TNK 
+              = Actions.ActOnDependentTemplateName(CurScope, 
+                                                   Tok.getLocation(), SS, 
+                                                   TemplateName, ObjectType,
+                                                   EnteringContext, Template)) {
+          // Consume the identifier.
+          ConsumeToken();
+          if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, 
+                                      SourceLocation(), false))
+            return true;                
+        }
+        else
           return true;     
-        
-        // Consume the identifier.
-        ConsumeToken();
-        if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, &SS,
-                                    TemplateName, SourceLocation(), false))
-          return true;
-        
+                
         continue;        
       }
     }
@@ -1013,12 +1018,11 @@
   case UnqualifiedId::IK_OperatorFunctionId:
   case UnqualifiedId::IK_LiteralOperatorId:
     if (AssumeTemplateId) {
-      Template = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, 
-                                                    Id, ObjectType,
-                                                    EnteringContext);
-      TNK = TNK_Dependent_template_name;
-      if (!Template.get())
-        return true;      
+      TNK = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, 
+                                               Id, ObjectType, EnteringContext,
+                                               Template);
+      if (TNK == TNK_Non_template)
+        return true;
     } else {
       bool MemberOfUnknownSpecialization;
       TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, 
@@ -1044,11 +1048,10 @@
         Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword)
           << Name
           << FixItHint::CreateInsertion(Id.StartLocation, "template ");
-        Template = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc,
-                                                      SS, Id, ObjectType,
-                                                      EnteringContext);
-        TNK = TNK_Dependent_template_name;
-        if (!Template.get())
+        TNK = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc,
+                                                 SS, Id, ObjectType,
+                                                 EnteringContext, Template);
+        if (TNK == TNK_Non_template)
           return true;              
       }
     }
@@ -1069,11 +1072,10 @@
     bool MemberOfUnknownSpecialization;
     TemplateName.setIdentifier(Name, NameLoc);
     if (ObjectType) {
-      Template = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, 
-                                                    TemplateName, ObjectType,
-                                                    EnteringContext);
-      TNK = TNK_Dependent_template_name;
-      if (!Template.get())
+      TNK = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, 
+                                               TemplateName, ObjectType,
+                                               EnteringContext, Template);
+      if (TNK == TNK_Non_template)
         return true;
     } else {
       TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, 

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=106167&r1=106166&r2=106167&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Jun 16 18:00:59 2010
@@ -914,15 +914,14 @@
       // If the next token signals the end of a template argument,
       // then we have a dependent template name that could be a template
       // template argument.
-      if (isEndOfTemplateArgument(Tok)) {
-        TemplateTy Template
-          = Actions.ActOnDependentTemplateName(CurScope, TemplateLoc, SS, Name, 
-                                               /*ObjectType=*/0,
-                                               /*EnteringContext=*/false);
-        if (Template.get())
-          return ParsedTemplateArgument(SS, Template, Name.StartLocation);
-      }
-    } 
+      TemplateTy Template;
+      if (isEndOfTemplateArgument(Tok) &&
+          Actions.ActOnDependentTemplateName(CurScope, TemplateLoc, SS, Name, 
+                                             /*ObjectType=*/0,
+                                             /*EnteringContext=*/false,
+                                             Template))
+        return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+    }
   } else if (Tok.is(tok::identifier)) {
     // We may have a (non-dependent) template name.
     TemplateTy Template;

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=106167&r1=106166&r2=106167&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Jun 16 18:00:59 2010
@@ -2937,12 +2937,13 @@
                                                 SourceLocation NameLoc,
                                const TemplateArgumentListInfo &TemplateArgs);
 
-  virtual TemplateTy ActOnDependentTemplateName(Scope *S,
-                                                SourceLocation TemplateKWLoc,
-                                                CXXScopeSpec &SS,
-                                                UnqualifiedId &Name,
-                                                TypeTy *ObjectType,
-                                                bool EnteringContext);
+  virtual TemplateNameKind ActOnDependentTemplateName(Scope *S,
+                                                  SourceLocation TemplateKWLoc,
+                                                      CXXScopeSpec &SS,
+                                                      UnqualifiedId &Name,
+                                                      TypeTy *ObjectType,
+                                                      bool EnteringContext,
+                                                      TemplateTy &Template);
 
   bool CheckClassTemplatePartialSpecializationArgs(
                                         TemplateParameterList *TemplateParams,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=106167&r1=106166&r2=106167&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jun 16 18:00:59 2010
@@ -1686,12 +1686,13 @@
 /// example, given "MetaFun::template apply", the scope specifier \p
 /// SS will be "MetaFun::", \p TemplateKWLoc contains the location
 /// of the "template" keyword, and "apply" is the \p Name.
-Sema::TemplateTy
-Sema::ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc,
-                                 CXXScopeSpec &SS,
-                                 UnqualifiedId &Name,
-                                 TypeTy *ObjectType,
-                                 bool EnteringContext) {
+TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, 
+                                                  SourceLocation TemplateKWLoc,
+                                                  CXXScopeSpec &SS,
+                                                  UnqualifiedId &Name,
+                                                  TypeTy *ObjectType,
+                                                  bool EnteringContext,
+                                                  TemplateTy &Result) {
   if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() &&
       !getLangOptions().CPlusPlus0x)
     Diag(TemplateKWLoc, diag::ext_template_outside_of_template)
@@ -1719,25 +1720,24 @@
     // dependent name. C++ DR468 relaxed this requirement (the
     // "template" keyword is now permitted). We follow the C++0x
     // rules, even in C++03 mode with a warning, retroactively applying the DR.
-    TemplateTy Template;
     bool MemberOfUnknownSpecialization;
     TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
-                                          EnteringContext, Template,
+                                          EnteringContext, Result,
                                           MemberOfUnknownSpecialization);
     if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
         isa<CXXRecordDecl>(LookupCtx) &&
         cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) {
-      // This is a dependent template.
+      // This is a dependent template. Handle it below.
     } else if (TNK == TNK_Non_template) {
       Diag(Name.getSourceRange().getBegin(), 
            diag::err_template_kw_refers_to_non_template)
         << GetNameFromUnqualifiedId(Name)
         << Name.getSourceRange()
         << TemplateKWLoc;
-      return TemplateTy();
+      return TNK_Non_template;
     } else {
       // We found something; return it.
-      return Template;
+      return TNK;
     }
   }
 
@@ -1746,12 +1746,14 @@
   
   switch (Name.getKind()) {
   case UnqualifiedId::IK_Identifier:
-    return TemplateTy::make(Context.getDependentTemplateName(Qualifier, 
-                                                             Name.Identifier));
+    Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, 
+                                                              Name.Identifier));
+    return TNK_Dependent_template_name;
     
   case UnqualifiedId::IK_OperatorFunctionId:
-    return TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+    Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
                                              Name.OperatorFunctionId.Operator));
+    return TNK_Dependent_template_name;
 
   case UnqualifiedId::IK_LiteralOperatorId:
     assert(false && "We don't support these; Parse shouldn't have allowed propagation");
@@ -1765,7 +1767,7 @@
     << GetNameFromUnqualifiedId(Name)
     << Name.getSourceRange()
     << TemplateKWLoc;
-  return TemplateTy();
+  return TNK_Non_template;
 }
 
 bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=106167&r1=106166&r2=106167&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Jun 16 18:00:59 2010
@@ -6495,13 +6495,15 @@
   SS.setScopeRep(Qualifier);
   UnqualifiedId Name;
   Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
-  return getSema().ActOnDependentTemplateName(/*Scope=*/0,
-                                      /*FIXME:*/getDerived().getBaseLocation(),
-                                              SS,
-                                              Name,
-                                              ObjectType.getAsOpaquePtr(),
-                                              /*EnteringContext=*/false)
-           .template getAsVal<TemplateName>();
+  Sema::TemplateTy Template;
+  getSema().ActOnDependentTemplateName(/*Scope=*/0,
+                                       /*FIXME:*/getDerived().getBaseLocation(),
+                                       SS,
+                                       Name,
+                                       ObjectType.getAsOpaquePtr(),
+                                       /*EnteringContext=*/false,
+                                       Template);
+  return Template.template getAsVal<TemplateName>();
 }
 
 template<typename Derived>
@@ -6516,13 +6518,15 @@
   SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
   Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
                              Operator, SymbolLocations);
-  return getSema().ActOnDependentTemplateName(/*Scope=*/0,
+  Sema::TemplateTy Template;
+  getSema().ActOnDependentTemplateName(/*Scope=*/0,
                                        /*FIXME:*/getDerived().getBaseLocation(),
-                                              SS,
-                                              Name,
-                                              ObjectType.getAsOpaquePtr(),
-                                              /*EnteringContext=*/false)
-           .template getAsVal<TemplateName>();
+                                       SS,
+                                       Name,
+                                       ObjectType.getAsOpaquePtr(),
+                                       /*EnteringContext=*/false,
+                                       Template);
+  return Template.template getAsVal<TemplateName>();
 }
   
 template<typename Derived>

Modified: cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp?rev=106167&r1=106166&r2=106167&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp Wed Jun 16 18:00:59 2010
@@ -22,6 +22,7 @@
 
   M::Promote<int>::type *ret_intptr3(int* ip) { return ip; }
   M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } // expected-warning{{'template' keyword outside of a template}}
+  M::template Promote<int> pi; // expected-warning{{'template' keyword outside of a template}}
 }
 
 N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; }





More information about the cfe-commits mailing list