diff options
| author | Douglas Gregor <dgregor@apple.com> | 2009-10-20 05:58:46 +0000 | 
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2009-10-20 05:58:46 +0000 | 
| commit | a5cb6da0cdd2a2f97698c30bf09a043b1d38c052 (patch) | |
| tree | 506d4663d7ac8ef802414a65f9deb9d871fcbfb7 | |
| parent | 227767b4e508d07afa41882738225203acb1bb3f (diff) | |
| download | bcm5719-llvm-a5cb6da0cdd2a2f97698c30bf09a043b1d38c052.tar.gz bcm5719-llvm-a5cb6da0cdd2a2f97698c30bf09a043b1d38c052.zip | |
Handle substitutions into the "first qualifier in scope" of a
qualified member access expression (e.g., t->U::member) when that
first qualifier refers to a template parameters.
llvm-svn: 84612
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 29 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 24 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/member-template-access-expr.cpp | 3 | 
3 files changed, 49 insertions, 7 deletions
| diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 7f8960a2bf4..75719b0de97 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -400,6 +400,10 @@ namespace {      /// instantiating it.      Decl *TransformDefinition(Decl *D); +    /// \bried Transform the first qualifier within a scope by instantiating the +    /// declaration. +    NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc); +            /// \brief Rebuild the exception declaration and register the declaration      /// as an instantiated local.      VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, QualType T, @@ -457,6 +461,31 @@ Decl *TemplateInstantiator::TransformDefinition(Decl *D) {    return Inst;  } +NamedDecl * +TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,  +                                                     SourceLocation Loc) { +  // If the first part of the nested-name-specifier was a template type  +  // parameter, instantiate that type parameter down to a tag type. +  if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) { +    const TemplateTypeParmType *TTP  +      = cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD)); +    if (TTP->getDepth() < TemplateArgs.getNumLevels()) { +      QualType T = TemplateArgs(TTP->getDepth(), TTP->getIndex()).getAsType(); +      if (T.isNull()) +        return cast_or_null<NamedDecl>(TransformDecl(D)); +       +      if (const TagType *Tag = T->getAs<TagType>()) +        return Tag->getDecl(); +       +      // The resulting type is not a tag; complain. +      getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T; +      return 0; +    } +  } +   +  return cast_or_null<NamedDecl>(TransformDecl(D)); +} +  VarDecl *  TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,                                             QualType T, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7360b8fc7a8..fb0e2b1ae9b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -236,6 +236,19 @@ public:    /// Subclasses may override this function to provide alternate behavior.    Decl *TransformDefinition(Decl *D) { return getDerived().TransformDecl(D); } +  /// \brief Transform the given declaration, which was the first part of a +  /// nested-name-specifier in a member access expression. +  /// +  /// This specific declaration transformation only applies to the first  +  /// identifier in a nested-name-specifier of a member access expression, e.g., +  /// the \c T in \c x->T::member +  /// +  /// By default, invokes TransformDecl() to transform the declaration. +  /// Subclasses may override this function to provide alternate behavior. +  NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc) {  +    return cast_or_null<NamedDecl>(getDerived().TransformDecl(D));  +  } +      /// \brief Transform the given nested-name-specifier.    ///    /// By default, transforms all of the types and declarations within the @@ -4195,6 +4208,7 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(    if (Base.isInvalid())      return SemaRef.ExprError(); +  // Start the member reference and compute the object's type.    Sema::TypeTy *ObjectType = 0;    Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),                                                E->getOperatorLoc(), @@ -4203,12 +4217,12 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(    if (Base.isInvalid())      return SemaRef.ExprError(); -  // FIXME: The first qualifier found might be a template type parameter, -  // in which case there is no transformed declaration to refer to (it might -  // refer to a built-in type!). +  // Transform the first part of the nested-name-specifier that qualifies +  // the member name.    NamedDecl *FirstQualifierInScope -    = cast_or_null<NamedDecl>( -               getDerived().TransformDecl(E->getFirstQualifierFoundInScope())); +    = getDerived().TransformFirstQualifierInScope( +                                          E->getFirstQualifierFoundInScope(), +                                          E->getQualifierRange().getBegin());    NestedNameSpecifier *Qualifier = 0;    if (E->getQualifier()) { diff --git a/clang/test/SemaTemplate/member-template-access-expr.cpp b/clang/test/SemaTemplate/member-template-access-expr.cpp index 9f227c05e1d..0f9f21f339d 100644 --- a/clang/test/SemaTemplate/member-template-access-expr.cpp +++ b/clang/test/SemaTemplate/member-template-access-expr.cpp @@ -24,8 +24,7 @@ struct XDerived : public X {  };  void test_f1(XDerived xd) { -  // FIXME: Not quite functional yet. -//  int &ir = f1<X>(xd); +  int &ir = f1<X>(xd);  }  // PR5213 | 

