]> granicus.if.org Git - clang/commitdiff
When we see a 'template' disambiguator that marks the next identifier
authorDouglas Gregor <dgregor@apple.com>
Wed, 16 Jun 2010 23:00:59 +0000 (23:00 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 16 Jun 2010 23:00:59 +0000 (23:00 +0000)
(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.

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

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

index baca3fb50222e38970294a812269981459d46eca..d8bb8a5b6158c335dc4c87f299c74436c9a22d5a 100644 (file)
@@ -2006,13 +2006,21 @@ public:
   ///
   /// \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
index 843baa2fe7295dd3ae9cb895d01a13b0b4c16784..dd74c4e998c93e43e8f71b4e2a33f4c13d1f51b9 100644 (file)
@@ -164,14 +164,18 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
       
       // 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 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
           << 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 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
   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 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
         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 Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
     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, 
index ec0e31e703c9bedf9302a175117d3d826852a53a..9e95ca9f11fccbda8b4c53cebc3d9339d6ad400e 100644 (file)
@@ -914,15 +914,14 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
       // 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;
index c81c12bb86cf4affd21a772cfe05c0b1ece05f66..e719cd745377c375f0d57519e4bf9434991d7dba 100644 (file)
@@ -2937,12 +2937,13 @@ public:
                                                 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,
index b30d4e3e9c31f908751d75ae8b6579ecb93aedd5..735809f18546c7eebea89fb7c7443e2db64db580 100644 (file)
@@ -1686,12 +1686,13 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
 /// 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 @@ Sema::ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc,
     // 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 @@ Sema::ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc,
   
   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 @@ Sema::ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc,
     << GetNameFromUnqualifiedId(Name)
     << Name.getSourceRange()
     << TemplateKWLoc;
-  return TemplateTy();
+  return TNK_Non_template;
 }
 
 bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
index 86e3a25ea25e9776be7ffac09abdeae75144b86a..d2995778fc643b0afefe5f4e6b08dfa5856e0aab 100644 (file)
@@ -6495,13 +6495,15 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
   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 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
   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>
index 0251894f35ad62267416713502c31915f647ae90..e1e7246bd7edc9d626f5cba216dcd86010bb9ed2 100644 (file)
@@ -22,6 +22,7 @@ namespace N {
 
   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; }