[cfe-commits] r86866 - in /cfe/trunk/lib/Sema: Sema.h SemaTemplate.cpp

Douglas Gregor dgregor at apple.com
Wed Nov 11 11:31:23 PST 2009


Author: dgregor
Date: Wed Nov 11 13:31:23 2009
New Revision: 86866

URL: http://llvm.org/viewvc/llvm-project?rev=86866&view=rev
Log:
Refactoring of template-argument checking code to reduce nesting,
increase sanity. No intended functionality change.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 11 13:31:23 2009
@@ -2585,6 +2585,17 @@
                                                 SourceLocation TemplateLoc,
                                                 Declarator &D);
     
+  bool CheckTemplateArgument(NamedDecl *Param,
+                             const TemplateArgumentLoc &Arg,
+                             unsigned ArgIdx,
+                             TemplateDecl *Template,
+                             SourceLocation TemplateLoc,
+                             SourceLocation LAngleLoc,
+                             const TemplateArgumentLoc *TemplateArgs,
+                             unsigned NumTemplateArgs,
+                             SourceLocation RAngleLoc,
+                             TemplateArgumentListBuilder &Converted);
+  
   bool CheckTemplateArgumentList(TemplateDecl *Template,
                                  SourceLocation TemplateLoc,
                                  SourceLocation LAngleLoc,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Nov 11 13:31:23 2009
@@ -1606,6 +1606,209 @@
                                    AllTemplateArgs);
 }
 
+/// \brief Check that the given template argument corresponds to the given
+/// template parameter.
+bool Sema::CheckTemplateArgument(NamedDecl *Param,
+                                 const TemplateArgumentLoc &Arg,
+                                 unsigned ArgIdx,
+                                 TemplateDecl *Template,
+                                 SourceLocation TemplateLoc,
+                                 SourceLocation LAngleLoc,
+                                 const TemplateArgumentLoc *TemplateArgs,
+                                 unsigned NumTemplateArgs,
+                                 SourceLocation RAngleLoc,
+                                 TemplateArgumentListBuilder &Converted) {
+  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+    // Check template type parameters.
+    if (TTP->isParameterPack()) {
+      // Check all the remaining arguments (if any).
+      Converted.BeginPack();
+      for (; ArgIdx < NumTemplateArgs; ++ArgIdx) {
+        if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted))
+          return true;
+      }
+      
+      Converted.EndPack();
+      return false;
+    } 
+    
+    return CheckTemplateTypeArgument(TTP, Arg, Converted);
+  }
+  
+  if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+    // Check non-type template parameters.
+    
+    // Do substitution on the type of the non-type template parameter
+    // with the template arguments we've seen thus far.
+    QualType NTTPType = NTTP->getType();
+    if (NTTPType->isDependentType()) {
+      // Do substitution on the type of the non-type template parameter.
+      InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+                                 NTTP, Converted.getFlatArguments(),
+                                 Converted.flatSize(),
+                                 SourceRange(TemplateLoc, RAngleLoc));
+      
+      TemplateArgumentList TemplateArgs(Context, Converted,
+                                        /*TakeArgs=*/false);
+      NTTPType = SubstType(NTTPType,
+                           MultiLevelTemplateArgumentList(TemplateArgs),
+                           NTTP->getLocation(),
+                           NTTP->getDeclName());
+      // If that worked, check the non-type template parameter type
+      // for validity.
+      if (!NTTPType.isNull())
+        NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
+                                                     NTTP->getLocation());
+      if (NTTPType.isNull())
+        return true;
+    }
+    
+    switch (Arg.getArgument().getKind()) {
+    case TemplateArgument::Null:
+      assert(false && "Should never see a NULL template argument here");
+      return true;
+      
+    case TemplateArgument::Expression: {
+      Expr *E = Arg.getArgument().getAsExpr();
+      TemplateArgument Result;
+      if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+        return true;
+      
+      Converted.Append(Result);
+      break;
+    }
+      
+    case TemplateArgument::Declaration:
+    case TemplateArgument::Integral:
+      // We've already checked this template argument, so just copy
+      // it to the list of converted arguments.
+      Converted.Append(Arg.getArgument());
+      break;
+      
+    case TemplateArgument::Template:
+      // We were given a template template argument. It may not be ill-formed;
+      // see below.
+      if (DependentTemplateName *DTN
+            = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
+        // We have a template argument such as \c T::template X, which we
+        // parsed as a template template argument. However, since we now
+        // know that we need a non-type template argument, convert this
+        // template name into an expression.          
+        Expr *E = new (Context) UnresolvedDeclRefExpr(DTN->getIdentifier(),
+                                                      Context.DependentTy,
+                                                      Arg.getTemplateNameLoc(),
+                                               Arg.getTemplateQualifierRange(),
+                                                      DTN->getQualifier(),
+                                                  /*isAddressOfOperand=*/false);
+        
+        TemplateArgument Result;
+        if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+          return true;
+        
+        Converted.Append(Result);
+        break;
+      }
+      
+      // We have a template argument that actually does refer to a class
+      // template, template alias, or template template parameter, and
+      // therefore cannot be a non-type template argument.
+      Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)
+        << Arg.getSourceRange();
+      
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+      
+    case TemplateArgument::Type: {
+      // We have a non-type template parameter but the template
+      // argument is a type.
+      
+      // C++ [temp.arg]p2:
+      //   In a template-argument, an ambiguity between a type-id and
+      //   an expression is resolved to a type-id, regardless of the
+      //   form of the corresponding template-parameter.
+      //
+      // We warn specifically about this case, since it can be rather
+      // confusing for users.
+      QualType T = Arg.getArgument().getAsType();
+      SourceRange SR = Arg.getSourceRange();
+      if (T->isFunctionType())
+        Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T;
+      else
+        Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+      
+    case TemplateArgument::Pack:
+      assert(0 && "FIXME: Implement!");
+      break;
+    }
+    
+    return false;
+  } 
+  
+  
+  // Check template template parameters.
+  TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);
+    
+  // Substitute into the template parameter list of the template
+  // template parameter, since previously-supplied template arguments
+  // may appear within the template template parameter.
+  {
+    // Set up a template instantiation context.
+    LocalInstantiationScope Scope(*this);
+    InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+                               TempParm, Converted.getFlatArguments(),
+                               Converted.flatSize(),
+                               SourceRange(TemplateLoc, RAngleLoc));
+    
+    TemplateArgumentList TemplateArgs(Context, Converted,
+                                      /*TakeArgs=*/false);
+    TempParm = cast_or_null<TemplateTemplateParmDecl>(
+                      SubstDecl(TempParm, CurContext, 
+                                MultiLevelTemplateArgumentList(TemplateArgs)));
+    if (!TempParm)
+      return true;
+    
+    // FIXME: TempParam is leaked.
+  }
+    
+  switch (Arg.getArgument().getKind()) {
+  case TemplateArgument::Null:
+    assert(false && "Should never see a NULL template argument here");
+    return true;
+    
+  case TemplateArgument::Template:
+    if (CheckTemplateArgument(TempParm, Arg))
+      return true;
+      
+    Converted.Append(Arg.getArgument());
+    break;
+    
+  case TemplateArgument::Expression:
+  case TemplateArgument::Type:
+    // We have a template template parameter but the template
+    // argument does not refer to a template.
+    Diag(Arg.getLocation(), diag::err_template_arg_must_be_template);
+    return true;
+      
+  case TemplateArgument::Declaration:
+    llvm::llvm_unreachable(
+                       "Declaration argument with template template parameter");
+    break;
+  case TemplateArgument::Integral:
+    llvm::llvm_unreachable(
+                          "Integral argument with template template parameter");
+    break;
+    
+  case TemplateArgument::Pack:
+    assert(0 && "FIXME: Implement!");
+    break;
+  }
+  
+  return false;
+}
+
 /// \brief Check that the given template argument list is well-formed
 /// for specializing the given template.
 bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
@@ -1722,200 +1925,11 @@
       // Retrieve the template argument produced by the user.
       Arg = TemplateArgs[ArgIdx];
     }
-
-
-    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
-      if (TTP->isParameterPack()) {
-        Converted.BeginPack();
-        // Check all the remaining arguments (if any).
-        for (; ArgIdx < NumArgs; ++ArgIdx) {
-          if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted))
-            Invalid = true;
-        }
-
-        Converted.EndPack();
-      } else {
-        if (CheckTemplateTypeArgument(TTP, Arg, Converted))
-          Invalid = true;
-      }
-    } else if (NonTypeTemplateParmDecl *NTTP
-                 = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
-      // Check non-type template parameters.
-
-      // Do substitution on the type of the non-type template parameter
-      // with the template arguments we've seen thus far.
-      QualType NTTPType = NTTP->getType();
-      if (NTTPType->isDependentType()) {
-        // Do substitution on the type of the non-type template parameter.
-        InstantiatingTemplate Inst(*this, TemplateLoc, Template,
-                                   NTTP, Converted.getFlatArguments(),
-                                   Converted.flatSize(),
-                                   SourceRange(TemplateLoc, RAngleLoc));
-
-        TemplateArgumentList TemplateArgs(Context, Converted,
-                                          /*TakeArgs=*/false);
-        NTTPType = SubstType(NTTPType,
-                             MultiLevelTemplateArgumentList(TemplateArgs),
-                             NTTP->getLocation(),
-                             NTTP->getDeclName());
-        // If that worked, check the non-type template parameter type
-        // for validity.
-        if (!NTTPType.isNull())
-          NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
-                                                       NTTP->getLocation());
-        if (NTTPType.isNull()) {
-          Invalid = true;
-          break;
-        }
-      }
-
-      switch (Arg.getArgument().getKind()) {
-      case TemplateArgument::Null:
-        assert(false && "Should never see a NULL template argument here");
-        break;
-
-      case TemplateArgument::Expression: {
-        Expr *E = Arg.getArgument().getAsExpr();
-        TemplateArgument Result;
-        if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
-          Invalid = true;
-        else
-          Converted.Append(Result);
-        break;
-      }
-
-      case TemplateArgument::Declaration:
-      case TemplateArgument::Integral:
-        // We've already checked this template argument, so just copy
-        // it to the list of converted arguments.
-        Converted.Append(Arg.getArgument());
-        break;
-
-      case TemplateArgument::Template:
-        // We were given a template template argument. It may not be ill-formed;
-        // see below.
-        if (DependentTemplateName *DTN
-             = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
-          // We have a template argument such as \c T::template X, which we
-          // parsed as a template template argument. However, since we now
-          // know that we need a non-type template argument, convert this
-          // template name into an expression.          
-          Expr *E = new (Context) UnresolvedDeclRefExpr(DTN->getIdentifier(),
-                                                        Context.DependentTy,
-                                                      Arg.getTemplateNameLoc(),
-                                                Arg.getTemplateQualifierRange(),
-                                                        DTN->getQualifier(),
-                                                  /*isAddressOfOperand=*/false);
-                                                        
-          TemplateArgument Result;
-          if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
-            Invalid = true;
-          else
-            Converted.Append(Result);
-          
-          break;
-        }
-          
-        // We have a template argument that actually does refer to a class
-        // template, template alias, or template template parameter, and
-        // therefore cannot be a non-type template argument.
-        Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)
-          << Arg.getSourceRange();
-          
-        Diag((*Param)->getLocation(), diag::note_template_param_here);
-        Invalid = true;
-        break;
-          
-      case TemplateArgument::Type: {
-        // We have a non-type template parameter but the template
-        // argument is a type.
-
-        // C++ [temp.arg]p2:
-        //   In a template-argument, an ambiguity between a type-id and
-        //   an expression is resolved to a type-id, regardless of the
-        //   form of the corresponding template-parameter.
-        //
-        // We warn specifically about this case, since it can be rather
-        // confusing for users.
-        QualType T = Arg.getArgument().getAsType();
-        SourceRange SR = Arg.getSourceRange();
-        if (T->isFunctionType())
-          Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig)
-            << SR << T;
-        else
-          Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
-        Diag((*Param)->getLocation(), diag::note_template_param_here);
-        Invalid = true;
-        break;
-      }
-
-      case TemplateArgument::Pack:
-        assert(0 && "FIXME: Implement!");
-        break;
-      }
-    } else {
-      // Check template template parameters.
-      TemplateTemplateParmDecl *TempParm
-        = cast<TemplateTemplateParmDecl>(*Param);
-
-      // Substitute into the template parameter list of the template
-      // template parameter, since previously-supplied template arguments
-      // may appear within the template template parameter.
-      {
-        // Set up a template instantiation context.
-        LocalInstantiationScope Scope(*this);
-        InstantiatingTemplate Inst(*this, TemplateLoc, Template,
-                                   TempParm, Converted.getFlatArguments(),
-                                   Converted.flatSize(),
-                                   SourceRange(TemplateLoc, RAngleLoc));
-      
-        TemplateArgumentList TemplateArgs(Context, Converted,
-                                          /*TakeArgs=*/false);
-        TempParm = cast_or_null<TemplateTemplateParmDecl>(
-                        SubstDecl(TempParm, CurContext, 
-                                 MultiLevelTemplateArgumentList(TemplateArgs)));
-        if (!TempParm) {
-          Invalid = true;
-          break;
-        }
-        
-        // FIXME: TempParam is leaked.
-      }
-      
-      switch (Arg.getArgument().getKind()) {
-      case TemplateArgument::Null:
-        assert(false && "Should never see a NULL template argument here");
-        break;
-
-      case TemplateArgument::Template:
-        if (CheckTemplateArgument(TempParm, Arg))
-          Invalid = true;
-        else
-          Converted.Append(Arg.getArgument());
-        break;
-          
-      case TemplateArgument::Expression:
-      case TemplateArgument::Type:
-        // We have a template template parameter but the template
-        // argument does not refer to a template.
-        Diag(Arg.getLocation(), diag::err_template_arg_must_be_template);
-        Invalid = true;
-        break;
-
-      case TemplateArgument::Declaration:
-        llvm::llvm_unreachable(
-                       "Declaration argument with template template parameter");
-        break;
-      case TemplateArgument::Integral:
-        llvm::llvm_unreachable(
-                          "Integral argument with template template parameter");
-        break;
-
-      case TemplateArgument::Pack:
-        assert(0 && "FIXME: Implement!");
-        break;
-      }
-    }
+    
+    if (CheckTemplateArgument(*Param, Arg, ArgIdx, Template, TemplateLoc,
+                              LAngleLoc, TemplateArgs, NumTemplateArgs, 
+                              RAngleLoc, Converted))
+      return true;
   }
 
   return Invalid;





More information about the cfe-commits mailing list