diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-07-01 00:00:45 +0000 | 
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-07-01 00:00:45 +0000 | 
| commit | dc13ded6063942ff62f32b234ed016f70774d4f7 (patch) | |
| tree | dd406ffc295c68a51fd18d5dcedb156cece86b6e /clang/lib/Sema/SemaTemplate.cpp | |
| parent | 9dcde4bdec98ae6a0a84afaa00e81edf71e67d77 (diff) | |
| download | bcm5719-llvm-dc13ded6063942ff62f32b234ed016f70774d4f7.tar.gz bcm5719-llvm-dc13ded6063942ff62f32b234ed016f70774d4f7.zip | |
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>.
llvm-svn: 107354
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 172 | 
1 files changed, 65 insertions, 107 deletions
| diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 7e5377ab9a9..336a7bf9d04 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -459,7 +459,9 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,                                           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 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,      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 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {    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 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,      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 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,                                                       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 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,                                       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 | 

