]> granicus.if.org Git - clang/commitdiff
Implement tree transformations for DeclarationNames. Among other
authorDouglas Gregor <dgregor@apple.com>
Thu, 3 Sep 2009 22:13:48 +0000 (22:13 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 3 Sep 2009 22:13:48 +0000 (22:13 +0000)
things, this means that we can properly cope with member access
expressions such as

  t->operator T()

where T is a template parameter (or other dependent type).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80957 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/TreeTransform.h
test/SemaTemplate/member-access-expr.cpp

index 7babcf76b7acc8eb2c03a91f0a4577b5ee9a2b48..2faaa44daf9cd67d760cf14dd3b8cb682a78464e 100644 (file)
@@ -247,6 +247,15 @@ public:
                                               QualType ObjectType = QualType(),
                                           NamedDecl *FirstQualifierInScope = 0);
   
+  /// \brief Transform the given declaration name.
+  ///
+  /// By default, transforms the types of conversion function, constructor,
+  /// and destructor names and then (if needed) rebuilds the declaration name.
+  /// Identifiers and selectors are returned unmodified. Sublcasses may
+  /// override this function to provide alternate behavior.
+  DeclarationName TransformDeclarationName(DeclarationName Name,
+                                           SourceLocation Loc);
+  
   /// \brief Transform the given template name.
   /// 
   /// By default, transforms the template name by transforming the declarations
@@ -1667,6 +1676,39 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
   return 0;  
 }
 
+template<typename Derived>
+DeclarationName 
+TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
+                                                 SourceLocation Loc) {
+  if (!Name)
+    return Name;
+
+  switch (Name.getNameKind()) {
+  case DeclarationName::Identifier:
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+  case DeclarationName::CXXOperatorName:
+  case DeclarationName::CXXUsingDirective:
+    return Name;
+      
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName: {
+    TemporaryBase Rebase(*this, Loc, Name);
+    QualType T = getDerived().TransformType(Name.getCXXNameType());
+    if (T.isNull())
+      return DeclarationName();
+    
+    return SemaRef.Context.DeclarationNames.getCXXSpecialName(
+                                                           Name.getNameKind(), 
+                                          SemaRef.Context.getCanonicalType(T));
+  }      
+  }
+  
+  return DeclarationName();
+}
+
 template<typename Derived>
 TemplateName 
 TreeTransform<Derived>::TransformTemplateName(TemplateName Name) {
@@ -3838,8 +3880,10 @@ TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(
   if (!NNS)
     return SemaRef.ExprError();
   
-  // FIXME: Transform the declaration name
-  DeclarationName Name = E->getDeclName();
+  DeclarationName Name 
+    = getDerived().TransformDeclarationName(E->getDeclName(), E->getLocation());
+  if (!Name)
+    return SemaRef.ExprError();
   
   if (!getDerived().AlwaysRebuild() && 
       NNS == E->getQualifier() &&
@@ -4078,9 +4122,11 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
       return SemaRef.ExprError();
   }
   
-  // FIXME: Transform the declaration name
-  DeclarationName Name = E->getMember();
-    
+  DeclarationName Name 
+    = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc());
+  if (!Name)
+    return SemaRef.ExprError();
+  
   if (!getDerived().AlwaysRebuild() &&
       Base.get() == E->getBase() &&
       Qualifier == E->getQualifier() &&
index 408e2bb53c4a043e30f1808ceba1350a1780ca90..40dbffe0cf8362f465934256dd2d82a32144d75e 100644 (file)
@@ -46,3 +46,16 @@ void test_f0_through_typedef2(X0 x0, X1 x1) {
 }
 
 
+struct X2 {
+  operator int() const;
+};
+
+template<typename T, typename U>
+T convert(const U& value) {
+  return value.operator T(); // expected-error{{operator long}}
+}
+
+void test_convert(X2 x2) {
+  convert<int>(x2);
+  convert<long>(x2); // expected-note{{instantiation}}
+}