[cfe-commits] r86060 - in /cfe/trunk: lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaExprCXX.cpp test/SemaTemplate/member-template-access-expr.cpp

Douglas Gregor dgregor at apple.com
Wed Nov 4 14:49:19 PST 2009


Author: dgregor
Date: Wed Nov  4 16:49:18 2009
New Revision: 86060

URL: http://llvm.org/viewvc/llvm-project?rev=86060&view=rev
Log:
When starting a C++ member access expression, make sure to compute the
type of the object even when it is dependent. Specifically, this makes
sure that we get the right type for "this->", which is important when
performing name lookup into this scope to determine whether an
identifier or operator-function-id is a template name.


Modified:
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Wed Nov  4 16:49:18 2009
@@ -22,6 +22,72 @@
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
 
+/// \brief Find the current instantiation that associated with the given type.
+static CXXRecordDecl *
+getCurrentInstantiationOf(ASTContext &Context, DeclContext *CurContext, 
+                          QualType T) {
+  if (T.isNull())
+    return 0;
+  
+  T = Context.getCanonicalType(T);
+  
+  for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getParent()) {
+    // If we've hit a namespace or the global scope, then the
+    // nested-name-specifier can't refer to the current instantiation.
+    if (Ctx->isFileContext())
+      return 0;
+    
+    // Skip non-class contexts.
+    CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
+    if (!Record)
+      continue;
+    
+    // If this record type is not dependent,
+    if (!Record->isDependentType())
+      return 0;
+    
+    // C++ [temp.dep.type]p1:
+    //
+    //   In the definition of a class template, a nested class of a
+    //   class template, a member of a class template, or a member of a
+    //   nested class of a class template, a name refers to the current
+    //   instantiation if it is
+    //     -- the injected-class-name (9) of the class template or
+    //        nested class,
+    //     -- in the definition of a primary class template, the name
+    //        of the class template followed by the template argument
+    //        list of the primary template (as described below)
+    //        enclosed in <>,
+    //     -- in the definition of a nested class of a class template,
+    //        the name of the nested class referenced as a member of
+    //        the current instantiation, or
+    //     -- in the definition of a partial specialization, the name
+    //        of the class template followed by the template argument
+    //        list of the partial specialization enclosed in <>. If
+    //        the nth template parameter is a parameter pack, the nth
+    //        template argument is a pack expansion (14.6.3) whose
+    //        pattern is the name of the parameter pack.
+    //        (FIXME: parameter packs)
+    //
+    // All of these options come down to having the
+    // nested-name-specifier type that is equivalent to the
+    // injected-class-name of one of the types that is currently in
+    // our context.
+    if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
+      return Record;
+    
+    if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
+      QualType InjectedClassName
+        = Template->getInjectedClassNameType(Context);
+      if (T == Context.getCanonicalType(InjectedClassName))
+        return Template->getTemplatedDecl();
+    }
+    // FIXME: check for class template partial specializations
+  }  
+  
+  return 0;
+}
+
 /// \brief Compute the DeclContext that is associated with the given type.
 ///
 /// \param T the type for which we are attempting to find a DeclContext.
@@ -33,7 +99,7 @@
   if (const TagType *Tag = T->getAs<TagType>())
     return Tag->getDecl();
 
-  return 0;
+  return ::getCurrentInstantiationOf(Context, CurContext, T);
 }
 
 /// \brief Compute the DeclContext that is associated with the given
@@ -156,68 +222,7 @@
     return 0;
 
   QualType T = QualType(NNS->getAsType(), 0);
-  // If the nested name specifier does not refer to a type, then it
-  // does not refer to the current instantiation.
-  if (T.isNull())
-    return 0;
-
-  T = Context.getCanonicalType(T);
-
-  for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getParent()) {
-    // If we've hit a namespace or the global scope, then the
-    // nested-name-specifier can't refer to the current instantiation.
-    if (Ctx->isFileContext())
-      return 0;
-
-    // Skip non-class contexts.
-    CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
-    if (!Record)
-      continue;
-
-    // If this record type is not dependent,
-    if (!Record->isDependentType())
-      return 0;
-
-    // C++ [temp.dep.type]p1:
-    //
-    //   In the definition of a class template, a nested class of a
-    //   class template, a member of a class template, or a member of a
-    //   nested class of a class template, a name refers to the current
-    //   instantiation if it is
-    //     -- the injected-class-name (9) of the class template or
-    //        nested class,
-    //     -- in the definition of a primary class template, the name
-    //        of the class template followed by the template argument
-    //        list of the primary template (as described below)
-    //        enclosed in <>,
-    //     -- in the definition of a nested class of a class template,
-    //        the name of the nested class referenced as a member of
-    //        the current instantiation, or
-    //     -- in the definition of a partial specialization, the name
-    //        of the class template followed by the template argument
-    //        list of the partial specialization enclosed in <>. If
-    //        the nth template parameter is a parameter pack, the nth
-    //        template argument is a pack expansion (14.6.3) whose
-    //        pattern is the name of the parameter pack.
-    //        (FIXME: parameter packs)
-    //
-    // All of these options come down to having the
-    // nested-name-specifier type that is equivalent to the
-    // injected-class-name of one of the types that is currently in
-    // our context.
-    if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
-      return Record;
-
-    if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
-      QualType InjectedClassName
-        = Template->getInjectedClassNameType(Context);
-      if (T == Context.getCanonicalType(InjectedClassName))
-        return Template->getTemplatedDecl();
-    }
-    // FIXME: check for class template partial specializations
-  }
-
-  return 0;
+  return ::getCurrentInstantiationOf(Context, CurContext, T);
 }
 
 /// \brief Require that the context specified by SS be complete.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Nov  4 16:49:18 2009
@@ -2030,7 +2030,13 @@
 
   QualType BaseType = BaseExpr->getType();
   if (BaseType->isDependentType()) {
-    // FIXME: member of the current instantiation
+    // If we have a pointer to a dependent type and are using the -> operator,
+    // the object type is the type that the pointer points to. We might still
+    // have enough information about that type to do something useful.
+    if (OpKind == tok::arrow)
+      if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+        BaseType = Ptr->getPointeeType();
+    
     ObjectType = BaseType.getAsOpaquePtr();
     return move(Base);
   }

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=86060&r1=86059&r2=86060&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp (original)
+++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Wed Nov  4 16:49:18 2009
@@ -93,3 +93,13 @@
   X2<sizeof(int)> x2;
   x4i.f<X2<sizeof(int)> >(x2);
 }
+
+template<typename T>
+struct X5 {
+  template<typename U>
+  void f();
+  
+  void g() {
+    this->f<T*>();
+  }
+};





More information about the cfe-commits mailing list