[cfe-commits] r84612 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h test/SemaTemplate/member-template-access-expr.cpp

Douglas Gregor dgregor at apple.com
Mon Oct 19 22:58:46 PDT 2009


Author: dgregor
Date: Tue Oct 20 00:58:46 2009
New Revision: 84612

URL: http://llvm.org/viewvc/llvm-project?rev=84612&view=rev
Log:
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.


Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Oct 20 00:58:46 2009
@@ -400,6 +400,10 @@
     /// 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 @@
   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,

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

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Oct 20 00:58:46 2009
@@ -236,6 +236,19 @@
   /// 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 @@
   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 @@
   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()) {

Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=84612&r1=84611&r2=84612&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp (original)
+++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Tue Oct 20 00:58:46 2009
@@ -24,8 +24,7 @@
 };
 
 void test_f1(XDerived xd) {
-  // FIXME: Not quite functional yet.
-//  int &ir = f1<X>(xd);
+  int &ir = f1<X>(xd);
 }
 
 // PR5213





More information about the cfe-commits mailing list