[cfe-commits] r107354 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Parse/Template.h lib/Parse/ParseTemplate.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp

Douglas Gregor dgregor at apple.com
Wed Jun 30 17:00:45 PDT 2010


Author: dgregor
Date: Wed Jun 30 19:00:45 2010
New Revision: 107354

URL: http://llvm.org/viewvc/llvm-project?rev=107354&view=rev
Log:
Implement C++ DR481, which clarifies that the scope of template
parameters starts at the end of the template-parameter rather than at
the point where the template parameter name is encounted. For example,
given:

  typedef unsigned char T;
  template<typename T = T> struct X0 { };

The "T" in the default argument refers to the typedef of "unsigned
char", rather than referring to the newly-introduced template type
parameter 'T'. 

Addresses <rdar://problem/8122812>.

Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Template.h
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Jun 30 19:00:45 2010
@@ -1833,46 +1833,87 @@
 
   //===---------------------------C++ Templates----------------------------===//
 
-  /// ActOnTypeParameter - Called when a C++ template type parameter
-  /// (e.g., "typename T") has been parsed. Typename specifies whether
-  /// the keyword "typename" was used to declare the type parameter
-  /// (otherwise, "class" was used), ellipsis specifies whether this is a
-  /// C++0x parameter pack, EllipsisLoc specifies the start of the ellipsis,
-  /// and KeyLoc is the location of the "class" or "typename" keyword.
-  //  ParamName is the name of the parameter (NULL indicates an unnamed template
-  //  parameter) and ParamNameLoc is the location of the parameter name (if any)
-  /// If the type parameter has a default argument, it will be added
-  /// later via ActOnTypeParameterDefault. Depth and Position provide
-  /// the number of enclosing templates (see
-  /// ActOnTemplateParameterList) and the number of previous
-  /// parameters within this template parameter list.
+  /// \brief Called when a C++ template type parameter(e.g., "typename T") has 
+  /// been parsed. 
+  ///
+  /// Given
+  ///
+  /// \code
+  /// template<typename T, typename U = T> struct pair;
+  /// \endcode
+  ///
+  /// this callback will be invoked twice: once for the type parameter \c T
+  /// with \p Depth=0 and \p Position=0, and once for the type parameter \c U
+  /// with \p Depth=0 and \p Position=1.
+  ///
+  /// \param Typename Specifies whether the keyword "typename" was used to 
+  /// declare the type parameter (otherwise, "class" was used).
+  ///
+  /// \param Ellipsis Specifies whether this is a C++0x parameter pack.
+  ///
+  /// \param EllipsisLoc Specifies the start of the ellipsis.
+  ///
+  /// \param KeyLoc The location of the "class" or "typename" keyword.
+  ///
+  /// \param ParamName The name of the parameter, where NULL indicates an 
+  /// unnamed template parameter.
+  ///
+  /// \param ParamNameLoc The location of the parameter name (if any).
+  ///
+  /// \param Depth The depth of this template parameter, e.g., the number of
+  /// template parameter lists that occurred outside the template parameter
+  /// list in which this template type parameter occurs.
+  ///
+  /// \param Position The zero-based position of this template parameter within
+  /// its template parameter list, which is also the number of template
+  /// parameters that precede this parameter in the template parameter list.
+  ///
+  /// \param EqualLoc The location of the '=' sign for the default template
+  /// argument, if any.
+  ///
+  /// \param DefaultArg The default argument, if provided.
   virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
                                        SourceLocation EllipsisLoc,
                                        SourceLocation KeyLoc,
                                        IdentifierInfo *ParamName,
                                        SourceLocation ParamNameLoc,
-                                       unsigned Depth, unsigned Position) {
+                                       unsigned Depth, unsigned Position,
+                                       SourceLocation EqualLoc,
+                                       TypeTy *DefaultArg) {
     return DeclPtrTy();
   }
 
-  /// ActOnTypeParameterDefault - Adds a default argument (the type
-  /// Default) to the given template type parameter (TypeParam).
-  virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam,
-                                         SourceLocation EqualLoc,
-                                         SourceLocation DefaultLoc,
-                                         TypeTy *Default) {
-  }
-
-  /// ActOnNonTypeTemplateParameter - Called when a C++ non-type
-  /// template parameter (e.g., "int Size" in "template<int Size>
-  /// class Array") has been parsed. S is the current scope and D is
-  /// the parsed declarator. Depth and Position provide the number of
-  /// enclosing templates (see
-  /// ActOnTemplateParameterList) and the number of previous
-  /// parameters within this template parameter list.
+  /// \brief Called when a C++ non-type template parameter has been parsed.
+  ///
+  /// Given
+  ///
+  /// \code
+  /// template<int Size> class Array;
+  /// \endcode
+  ///
+  /// This callback will be invoked for the 'Size' non-type template parameter.
+  ///
+  /// \param S The current scope.
+  ///
+  /// \param D The parsed declarator.
+  ///
+  /// \param Depth The depth of this template parameter, e.g., the number of
+  /// template parameter lists that occurred outside the template parameter
+  /// list in which this template type parameter occurs.
+  ///
+  /// \param Position The zero-based position of this template parameter within
+  /// its template parameter list, which is also the number of template
+  /// parameters that precede this parameter in the template parameter list.
+  ///
+  /// \param EqualLoc The location of the '=' sign for the default template
+  /// argument, if any.
+  ///
+  /// \param DefaultArg The default argument, if provided.
   virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
                                                   unsigned Depth,
-                                                  unsigned Position) {
+                                                  unsigned Position,
+                                                  SourceLocation EqualLoc,
+                                                  ExprArg DefaultArg) {
     return DeclPtrTy();
   }
 
@@ -1883,29 +1924,50 @@
                                                     ExprArg Default) {
   }
 
-  /// ActOnTemplateTemplateParameter - Called when a C++ template template
-  /// parameter (e.g., "int T" in "template<template <typename> class T> class
-  /// Array") has been parsed. TmpLoc is the location of the "template" keyword,
-  /// TemplateParams is the sequence of parameters required by the template,
-  /// ParamName is the name of the parameter (null if unnamed), and ParamNameLoc
-  /// is the source location of the identifier (if given).
+  /// \brief Called when a C++ template template parameter has been parsed. 
+  ///
+  /// Given
+  ///
+  /// \code
+  /// template<template <typename> class T> class X;
+  /// \endcode
+  ///
+  /// this callback will be invoked for the template template parameter \c T.
+  ///
+  /// \param S The scope in which this template template parameter occurs.
+  ///
+  /// \param TmpLoc The location of the "template" keyword.
+  ///
+  /// \param TemplateParams The template parameters required by the template.
+  ///
+  /// \param ParamName The name of the parameter, or NULL if unnamed.
+  ///
+  /// \param ParamNameLoc The source location of the parameter name (if given).
+  ///
+  /// \param Depth The depth of this template parameter, e.g., the number of
+  /// template parameter lists that occurred outside the template parameter
+  /// list in which this template parameter occurs.
+  ///
+  /// \param Position The zero-based position of this template parameter within
+  /// its template parameter list, which is also the number of template
+  /// parameters that precede this parameter in the template parameter list.
+  ///
+  /// \param EqualLoc The location of the '=' sign for the default template
+  /// argument, if any.
+  ///
+  /// \param DefaultArg The default argument, if provided.
   virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
                                                    SourceLocation TmpLoc,
                                                    TemplateParamsTy *Params,
                                                    IdentifierInfo *ParamName,
                                                    SourceLocation ParamNameLoc,
                                                    unsigned Depth,
-                                                   unsigned Position) {
+                                                   unsigned Position,
+                                                   SourceLocation EqualLoc,
+                                    const ParsedTemplateArgument &DefaultArg) {
     return DeclPtrTy();
   }
 
-  /// \brief Adds a default argument to the given template template
-  /// parameter.
-  virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
-                                                     SourceLocation EqualLoc,
-                                        const ParsedTemplateArgument &Default) {
-  }
-
   /// ActOnTemplateParameterList - Called when a complete template
   /// parameter list has been parsed, e.g.,
   ///

Modified: cfe/trunk/include/clang/Parse/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Template.h?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Template.h (original)
+++ cfe/trunk/include/clang/Parse/Template.h Wed Jun 30 19:00:45 2010
@@ -58,7 +58,7 @@
         Loc(TemplateLoc), SS(SS) { }
     
     /// \brief Determine whether the given template argument is invalid.
-    bool isInvalid() { return Arg == 0; }
+    bool isInvalid() const { return Arg == 0; }
     
     /// \brief Determine what kind of template argument we have.
     KindType getKind() const { return Kind; }

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Jun 30 19:00:45 2010
@@ -471,22 +471,19 @@
     return DeclPtrTy();
   }
 
-  DeclPtrTy TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
-                                                   Ellipsis, EllipsisLoc,
-                                                   KeyLoc, ParamName, NameLoc,
-                                                   Depth, Position);
-
-  // Grab a default type id (if given).
+  // Grab a default argument (if available).
+  // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
+  // we introduce the type parameter into the local scope.
+  SourceLocation EqualLoc;
+  TypeTy *DefaultArg = 0;
   if (Tok.is(tok::equal)) {
-    SourceLocation EqualLoc = ConsumeToken();
-    SourceLocation DefaultLoc = Tok.getLocation();
-    TypeResult DefaultType = ParseTypeName();
-    if (!DefaultType.isInvalid())
-      Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
-                                        DefaultType.get());
+    EqualLoc = ConsumeToken();
+    DefaultArg = ParseTypeName().get();
   }
-
-  return TypeParam;
+  
+  return Actions.ActOnTypeParameter(CurScope, TypenameKeyword, Ellipsis, 
+                                    EllipsisLoc, KeyLoc, ParamName, NameLoc,
+                                    Depth, Position, EqualLoc, DefaultArg);
 }
 
 /// ParseTemplateTemplateParameter - Handle the parsing of template
@@ -541,28 +538,28 @@
                                        TemplateParams.size(),
                                        RAngleLoc);
 
-  Parser::DeclPtrTy Param
-    = Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
-                                             ParamList, ParamName,
-                                             NameLoc, Depth, Position);
-
-  // Get the a default value, if given.
+  // Grab a default argument (if available).
+  // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
+  // we introduce the template parameter into the local scope.
+  SourceLocation EqualLoc;
+  ParsedTemplateArgument DefaultArg;
   if (Tok.is(tok::equal)) {
-    SourceLocation EqualLoc = ConsumeToken();
-    ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
-    if (Default.isInvalid()) {
+    EqualLoc = ConsumeToken();
+    DefaultArg = ParseTemplateTemplateArgument();
+    if (DefaultArg.isInvalid()) {
       Diag(Tok.getLocation(), 
            diag::err_default_template_template_parameter_not_template);
       static const tok::TokenKind EndToks[] = { 
         tok::comma, tok::greater, tok::greatergreater
       };
       SkipUntil(EndToks, 3, true, true);
-      return Param;
-    } else if (Param)
-      Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default);
+    }
   }
-
-  return Param;
+  
+  return Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
+                                                ParamList, ParamName,
+                                                NameLoc, Depth, Position,
+                                                EqualLoc, DefaultArg);
 }
 
 /// ParseNonTypeTemplateParameter - Handle the parsing of non-type
@@ -571,13 +568,6 @@
 ///       template-parameter:
 ///         ...
 ///         parameter-declaration
-///
-/// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
-/// but that didn't work out to well. Instead, this tries to recrate the basic
-/// parsing of parameter declarations, but tries to constrain it for template
-/// parameters.
-/// FIXME: We need to make a ParseParameterDeclaration that works for
-/// non-type template parameters and normal function parameters.
 Parser::DeclPtrTy
 Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
   SourceLocation StartLoc = Tok.getLocation();
@@ -601,13 +591,13 @@
     return DeclPtrTy();
   }
 
-  // Create the parameter.
-  DeclPtrTy Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
-                                                          Depth, Position);
-
   // If there is a default value, parse it.
+  // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
+  // we introduce the template parameter into the local scope.
+  SourceLocation EqualLoc;
+  OwningExprResult DefaultArg(Actions);
   if (Tok.is(tok::equal)) {
-    SourceLocation EqualLoc = ConsumeToken();
+    EqualLoc = ConsumeToken();
 
     // C++ [temp.param]p15:
     //   When parsing a default template-argument for a non-type
@@ -616,15 +606,15 @@
     //   operator.
     GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
 
-    OwningExprResult DefaultArg = ParseAssignmentExpression();
+    DefaultArg = ParseAssignmentExpression();
     if (DefaultArg.isInvalid())
       SkipUntil(tok::comma, tok::greater, true, true);
-    else if (Param)
-      Actions.ActOnNonTypeTemplateParameterDefault(Param, EqualLoc,
-                                                   move(DefaultArg));
   }
 
-  return Param;
+  // Create the parameter.
+  return Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl, 
+                                               Depth, Position, EqualLoc, 
+                                               move(DefaultArg));
 }
 
 /// \brief Parses a template-id that after the template name has

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Jun 30 19:00:45 2010
@@ -2861,29 +2861,25 @@
                                        SourceLocation KeyLoc,
                                        IdentifierInfo *ParamName,
                                        SourceLocation ParamNameLoc,
-                                       unsigned Depth, unsigned Position);
-  virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam,
-                                         SourceLocation EqualLoc,
-                                         SourceLocation DefaultLoc,
-                                         TypeTy *Default);
+                                       unsigned Depth, unsigned Position,
+                                       SourceLocation EqualLoc,
+                                       TypeTy *DefaultArg);
 
   QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
   virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
                                                   unsigned Depth,
-                                                  unsigned Position);
-  virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam,
-                                                    SourceLocation EqualLoc,
-                                                    ExprArg Default);
+                                                  unsigned Position,
+                                                  SourceLocation EqualLoc,
+                                                  ExprArg DefaultArg);
   virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
                                                    SourceLocation TmpLoc,
                                                    TemplateParamsTy *Params,
                                                    IdentifierInfo *ParamName,
                                                    SourceLocation ParamNameLoc,
                                                    unsigned Depth,
-                                                   unsigned Position);
-  virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
-                                                     SourceLocation EqualLoc,
-                                        const ParsedTemplateArgument &Default);
+                                                   unsigned Position,
+                                                   SourceLocation EqualLoc,
+                                     const ParsedTemplateArgument &DefaultArg);
 
   virtual TemplateParamsTy *
   ActOnTemplateParameterList(unsigned Depth,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jun 30 19:00:45 2010
@@ -459,7 +459,9 @@
                                          SourceLocation KeyLoc,
                                          IdentifierInfo *ParamName,
                                          SourceLocation ParamNameLoc,
-                                         unsigned Depth, unsigned Position) {
+                                         unsigned Depth, unsigned Position,
+                                         SourceLocation EqualLoc,
+                                         TypeTy *DefaultArg) {
   assert(S->isTemplateParamScope() &&
          "Template type parameter not in template parameter scope!");
   bool Invalid = false;
@@ -490,42 +492,31 @@
     IdResolver.AddDecl(Param);
   }
 
-  return DeclPtrTy::make(Param);
-}
-
-/// ActOnTypeParameterDefault - Adds a default argument (the type
-/// Default) to the given template type parameter (TypeParam).
-void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
-                                     SourceLocation EqualLoc,
-                                     SourceLocation DefaultLoc,
-                                     TypeTy *DefaultT) {
-  TemplateTypeParmDecl *Parm
-    = cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>());
-
-  TypeSourceInfo *DefaultTInfo;
-  GetTypeFromParser(DefaultT, &DefaultTInfo);
-
-  assert(DefaultTInfo && "expected source information for type");
-
-  // C++0x [temp.param]p9:
-  // A default template-argument may be specified for any kind of
-  // template-parameter that is not a template parameter pack.
-  if (Parm->isParameterPack()) {
-    Diag(DefaultLoc, diag::err_template_param_pack_default_arg);
-    return;
-  }
-
-  // C++ [temp.param]p14:
-  //   A template-parameter shall not be used in its own default argument.
-  // FIXME: Implement this check! Needs a recursive walk over the types.
-
-  // Check the template argument itself.
-  if (CheckTemplateArgument(Parm, DefaultTInfo)) {
-    Parm->setInvalidDecl();
-    return;
+  // Handle the default argument, if provided.
+  if (DefaultArg) {
+    TypeSourceInfo *DefaultTInfo;
+    GetTypeFromParser(DefaultArg, &DefaultTInfo);
+    
+    assert(DefaultTInfo && "expected source information for type");
+    
+    // C++0x [temp.param]p9:
+    // A default template-argument may be specified for any kind of
+    // template-parameter that is not a template parameter pack.
+    if (Ellipsis) {
+      Diag(EqualLoc, diag::err_template_param_pack_default_arg);
+      return DeclPtrTy::make(Param);
+    }
+    
+    // Check the template argument itself.
+    if (CheckTemplateArgument(Param, DefaultTInfo)) {
+      Param->setInvalidDecl();
+      return DeclPtrTy::make(Param);;
+    }
+    
+    Param->setDefaultArgument(DefaultTInfo, false);
   }
-
-  Parm->setDefaultArgument(DefaultTInfo, false);
+  
+  return DeclPtrTy::make(Param);
 }
 
 /// \brief Check that the type of a non-type template parameter is
@@ -580,13 +571,11 @@
   return QualType();
 }
 
-/// ActOnNonTypeTemplateParameter - Called when a C++ non-type
-/// template parameter (e.g., "int Size" in "template<int Size>
-/// class Array") has been parsed. S is the current scope and D is
-/// the parsed declarator.
 Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
                                                     unsigned Depth,
-                                                    unsigned Position) {
+                                                    unsigned Position,
+                                                    SourceLocation EqualLoc,
+                                                    ExprArg DefaultArg) {
   TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
   QualType T = TInfo->getType();
 
@@ -622,34 +611,21 @@
     S->AddDecl(DeclPtrTy::make(Param));
     IdResolver.AddDecl(Param);
   }
-  return DeclPtrTy::make(Param);
-}
-
-/// \brief Adds a default argument to the given non-type template
-/// parameter.
-void Sema::ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParamD,
-                                                SourceLocation EqualLoc,
-                                                ExprArg DefaultE) {
-  NonTypeTemplateParmDecl *TemplateParm
-    = cast<NonTypeTemplateParmDecl>(TemplateParamD.getAs<Decl>());
-  Expr *Default = static_cast<Expr *>(DefaultE.get());
-
-  // C++ [temp.param]p14:
-  //   A template-parameter shall not be used in its own default argument.
-  // FIXME: Implement this check! Needs a recursive walk over the types.
-
-  // Check the well-formedness of the default template argument.
-  TemplateArgument Converted;
-  if (CheckTemplateArgument(TemplateParm, TemplateParm->getType(), Default,
-                            Converted)) {
-    TemplateParm->setInvalidDecl();
-    return;
+  
+  // Check the well-formedness of the default template argument, if provided.
+  if (Expr *Default = static_cast<Expr *>(DefaultArg.get())) {  
+    TemplateArgument Converted;
+    if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) {
+      Param->setInvalidDecl();
+      return DeclPtrTy::make(Param);;
+    }
+  
+    Param->setDefaultArgument(DefaultArg.takeAs<Expr>(), false);
   }
-
-  TemplateParm->setDefaultArgument(DefaultE.takeAs<Expr>(), false);
+  
+  return DeclPtrTy::make(Param);
 }
 
-
 /// ActOnTemplateTemplateParameter - Called when a C++ template template
 /// parameter (e.g. T in template <template <typename> class T> class array)
 /// has been parsed. S is the current scope.
@@ -659,7 +635,9 @@
                                                      IdentifierInfo *Name,
                                                      SourceLocation NameLoc,
                                                      unsigned Depth,
-                                                     unsigned Position) {
+                                                     unsigned Position,
+                                                     SourceLocation EqualLoc,
+                                       const ParsedTemplateArgument &Default) {
   assert(S->isTemplateParamScope() &&
          "Template template parameter not in template parameter scope!");
 
@@ -669,53 +647,33 @@
                                      TmpLoc, Depth, Position, Name,
                                      (TemplateParameterList*)Params);
 
-  // Make sure the parameter is valid.
-  // FIXME: Decl object is not currently invalidated anywhere so this doesn't
-  // do anything yet. However, if the template parameter list or (eventual)
-  // default value is ever invalidated, that will propagate here.
-  bool Invalid = false;
-  if (Invalid) {
-    Param->setInvalidDecl();
-  }
-
-  // If the tt-param has a name, then link the identifier into the scope
-  // and lookup mechanisms.
+  // If the template template parameter has a name, then link the identifier 
+  // into the scope and lookup mechanisms.
   if (Name) {
     S->AddDecl(DeclPtrTy::make(Param));
     IdResolver.AddDecl(Param);
   }
 
-  return DeclPtrTy::make(Param);
-}
-
-/// \brief Adds a default argument to the given template template
-/// parameter.
-void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD,
-                                                 SourceLocation EqualLoc,
-                                        const ParsedTemplateArgument &Default) {
-  TemplateTemplateParmDecl *TemplateParm
-    = cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>());
-  
-  // C++ [temp.param]p14:
-  //   A template-parameter shall not be used in its own default argument.
-  // FIXME: Implement this check! Needs a recursive walk over the types.
-
-  // Check only that we have a template template argument. We don't want to
-  // try to check well-formedness now, because our template template parameter
-  // might have dependent types in its template parameters, which we wouldn't
-  // be able to match now.
-  //
-  // If none of the template template parameter's template arguments mention
-  // other template parameters, we could actually perform more checking here.
-  // However, it isn't worth doing.
-  TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
-  if (DefaultArg.getArgument().getAsTemplate().isNull()) {
-    Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
-      << DefaultArg.getSourceRange();
-    return;
+  if (!Default.isInvalid()) {
+    // Check only that we have a template template argument. We don't want to
+    // try to check well-formedness now, because our template template parameter
+    // might have dependent types in its template parameters, which we wouldn't
+    // be able to match now.
+    //
+    // If none of the template template parameter's template arguments mention
+    // other template parameters, we could actually perform more checking here.
+    // However, it isn't worth doing.
+    TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
+    if (DefaultArg.getArgument().getAsTemplate().isNull()) {
+      Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
+        << DefaultArg.getSourceRange();
+      return DeclPtrTy::make(Param);
+    }
+    
+    Param->setDefaultArgument(DefaultArg, false);
   }
   
-  TemplateParm->setDefaultArgument(DefaultArg, false);
+  return DeclPtrTy::make(Param);
 }
 
 /// ActOnTemplateParameterList - Builds a TemplateParameterList that





More information about the cfe-commits mailing list