[cfe-commits] r83485 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp test/SemaCXX/builtin-ptrtomember-overload-1.cpp

Fariborz Jahanian fjahanian at apple.com
Wed Oct 7 13:43:37 PDT 2009


Author: fjahanian
Date: Wed Oct  7 15:43:36 2009
New Revision: 83485

URL: http://llvm.org/viewvc/llvm-project?rev=83485&view=rev
Log:
Fixes problem in finding visible convertion functions of a class
where matching conversion types in base classes were still visible.
Plus refactoring and cleanup.
Added a test case.


Added:
    cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=83485&r1=83484&r2=83485&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Oct  7 15:43:36 2009
@@ -17,6 +17,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/Decl.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
 
 namespace clang {
 
@@ -394,7 +395,11 @@
   llvm::PointerUnion<ClassTemplateDecl*, CXXRecordDecl*>
     TemplateOrInstantiation;
   
-  void getNestedVisibleConversionFunctions(CXXRecordDecl *RD);
+  void getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
+          const llvm::SmallPtrSet<QualType, 8> &TopConversionsTypeSet,
+          const llvm::SmallPtrSet<QualType, 8> &HiddenConversionTypes);
+  void collectConversionFunctions(
+    llvm::SmallPtrSet<QualType, 8>& ConversionsTypeSet);
   
 protected:
   CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=83485&r1=83484&r2=83485&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Oct  7 15:43:36 2009
@@ -285,39 +285,45 @@
   PlainOldData = false;
 }
 
+void
+CXXRecordDecl::collectConversionFunctions(
+                        llvm::SmallPtrSet<QualType, 8>& ConversionsTypeSet) {
+  OverloadedFunctionDecl *TopConversions = getConversionFunctions();
+  for (OverloadedFunctionDecl::function_iterator
+       TFunc = TopConversions->function_begin(),
+       TFuncEnd = TopConversions->function_end();
+       TFunc != TFuncEnd; ++TFunc) {
+    NamedDecl *TopConv = TFunc->get();
+    QualType TConvType;
+    if (FunctionTemplateDecl *TConversionTemplate =
+        dyn_cast<FunctionTemplateDecl>(TopConv))
+      TConvType = 
+        getASTContext().getCanonicalType(
+                    TConversionTemplate->getTemplatedDecl()->getResultType());
+    else 
+      TConvType = 
+        getASTContext().getCanonicalType(
+                      cast<CXXConversionDecl>(TopConv)->getConversionType());
+    ConversionsTypeSet.insert(TConvType);
+  }  
+}
+
 /// getNestedVisibleConversionFunctions - imports unique conversion 
 /// functions from base classes into the visible conversion function
 /// list of the class 'RD'. This is a private helper method.
+/// TopConversionsTypeSet is the set of conversion functions of the class
+/// we are interested in. HiddenConversionTypes is set of conversion functions
+/// of the immediate derived class which  hides the conversion functions found 
+/// in current class.
 void
-CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD) {
+CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
+                const llvm::SmallPtrSet<QualType, 8> &TopConversionsTypeSet,                               
+                const llvm::SmallPtrSet<QualType, 8> &HiddenConversionTypes) {
+  bool inTopClass = (RD == this);
   QualType ClassType = getASTContext().getTypeDeclType(this);
   if (const RecordType *Record = ClassType->getAs<RecordType>()) {
     OverloadedFunctionDecl *Conversions
       = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
-    llvm::SmallPtrSet<QualType, 8> TopConversionsTypeSet;
-    bool inTopClass = (RD == this);
-    if (!inTopClass && 
-        (Conversions->function_begin() != Conversions->function_end())) {
-      // populate the TypeSet with the type of current class's conversions.
-      OverloadedFunctionDecl *TopConversions = RD->getConversionFunctions();
-      for (OverloadedFunctionDecl::function_iterator
-           TFunc = TopConversions->function_begin(),
-           TFuncEnd = TopConversions->function_end();
-           TFunc != TFuncEnd; ++TFunc) {
-        NamedDecl *TopConv = TFunc->get();
-        QualType TConvType;
-        if (FunctionTemplateDecl *TConversionTemplate =
-            dyn_cast<FunctionTemplateDecl>(TopConv))
-          TConvType = 
-            getASTContext().getCanonicalType(
-                      TConversionTemplate->getTemplatedDecl()->getResultType());
-        else 
-          TConvType = 
-            getASTContext().getCanonicalType(
-                        cast<CXXConversionDecl>(TopConv)->getConversionType());
-        TopConversionsTypeSet.insert(TConvType);
-      }
-    }
     
     for (OverloadedFunctionDecl::function_iterator
          Func = Conversions->function_begin(),
@@ -336,7 +342,12 @@
         ConvType = 
           getASTContext().getCanonicalType(
                           cast<CXXConversionDecl>(Conv)->getConversionType());
-      if (inTopClass || !TopConversionsTypeSet.count(ConvType)) {
+      // We only add conversion functions found in the base class if they
+      // are not hidden by those found in HiddenConversionTypes which are
+      // the conversion functions in its derived class.
+      if (inTopClass || 
+          (!TopConversionsTypeSet.count(ConvType) && 
+           !HiddenConversionTypes.count(ConvType)) ) {
         if (FunctionTemplateDecl *ConversionTemplate =
               dyn_cast<FunctionTemplateDecl>(Conv))
           RD->addVisibleConversionFunction(ConversionTemplate);
@@ -350,7 +361,17 @@
        E = vbases_end(); VBase != E; ++VBase) {
     CXXRecordDecl *VBaseClassDecl
       = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
-    VBaseClassDecl->getNestedVisibleConversionFunctions(RD);
+    if (inTopClass)
+      VBaseClassDecl->getNestedVisibleConversionFunctions(RD,
+                                                        TopConversionsTypeSet,
+                                                        TopConversionsTypeSet);
+    else {
+      llvm::SmallPtrSet<QualType, 8> HiddenConversionTypes;
+        collectConversionFunctions(HiddenConversionTypes);
+      VBaseClassDecl->getNestedVisibleConversionFunctions(RD,
+                                                        TopConversionsTypeSet,
+                                                        HiddenConversionTypes);
+    }
   }
   for (CXXRecordDecl::base_class_iterator Base = bases_begin(),
        E = bases_end(); Base != E; ++Base) {
@@ -358,7 +379,17 @@
       continue;
     CXXRecordDecl *BaseClassDecl
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-    BaseClassDecl->getNestedVisibleConversionFunctions(RD);
+    if (inTopClass)
+      BaseClassDecl->getNestedVisibleConversionFunctions(RD,
+                                                         TopConversionsTypeSet,
+                                                         TopConversionsTypeSet);
+    else {
+      llvm::SmallPtrSet<QualType, 8> HiddenConversionTypes;
+      collectConversionFunctions(HiddenConversionTypes);
+      BaseClassDecl->getNestedVisibleConversionFunctions(RD,
+                                                         TopConversionsTypeSet,
+                                                         HiddenConversionTypes);
+    }
   }
 }
 
@@ -372,7 +403,10 @@
   // If visible conversion list is already evaluated, return it.
   if (ComputedVisibleConversions)
     return &VisibleConversions;
-  getNestedVisibleConversionFunctions(this);
+  llvm::SmallPtrSet<QualType, 8> TopConversionsTypeSet;
+  collectConversionFunctions(TopConversionsTypeSet);
+  getNestedVisibleConversionFunctions(this, TopConversionsTypeSet,
+                                      TopConversionsTypeSet);
   ComputedVisibleConversions = true;
   return &VisibleConversions;
 }

Added: cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp?rev=83485&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp (added)
+++ cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp Wed Oct  7 15:43:36 2009
@@ -0,0 +1,44 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+struct A {};
+struct E {};
+
+struct R {
+    operator A*();
+    operator E*();
+};
+
+
+struct S {
+    operator A*();
+    operator E*();
+};
+
+struct B  : R {
+    operator A*();
+};
+
+struct C : B {
+
+};
+
+void foo(C c, int A::* pmf) {
+	int i = c->*pmf; 
+}
+
+struct B1  : R, S {
+    operator A*();
+};
+
+struct C1 : B1 {
+
+};
+
+void foo1(C1 c1, int A::* pmf) {
+        int i = c1->*pmf;
+}
+
+void foo1(C1 c1, int E::* pmf) {
+        // FIXME. Error reporting needs much improvement here.
+        int i = c1->*pmf;	// expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct C1'}}
+}





More information about the cfe-commits mailing list