[cfe-commits] r81576 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/conversion-delete-expr.cpp

Fariborz Jahanian fjahanian at apple.com
Fri Sep 11 14:44:33 PDT 2009


Author: fjahanian
Date: Fri Sep 11 16:44:33 2009
New Revision: 81576

URL: http://llvm.org/viewvc/llvm-project?rev=81576&view=rev
Log:
Patch to build visible conversion function list lazily and make its 
first use in calling the conversion function on delete statements.


Added:
    cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Sep 11 16:44:33 2009
@@ -367,9 +367,15 @@
   /// Conversions - Overload set containing the conversion functions
   /// of this C++ class (but not its inherited conversion
   /// functions). Each of the entries in this overload set is a
-  /// CXXConversionDecl.
+  /// CXXConversionDecl. 
   OverloadedFunctionDecl Conversions;
 
+  /// VisibleConversions - Overload set containing the conversion functions
+  /// of this C++ class and all those inherited conversion functions that
+  /// are visible in this class. Each of the entries in this overload set is
+  /// a CXXConversionDecl or a FunctionTemplateDecl.
+  OverloadedFunctionDecl VisibleConversions;
+  
   /// \brief The template or declaration that this declaration
   /// describes or was instantiated from, respectively.
   ///
@@ -570,6 +576,20 @@
     return &Conversions;
   }
 
+  /// getVisibleConversionFunctions - get all conversion functions visible
+  /// in current class; including conversion function templates.
+  OverloadedFunctionDecl *getVisibleConversionFunctions(ASTContext &Context,
+                                                        CXXRecordDecl *RD);
+  /// addVisibleConversionFunction - Add a new conversion function to the
+  /// list of visible conversion functions.
+  void addVisibleConversionFunction(ASTContext &Context, 
+                                    CXXConversionDecl *ConvDecl);
+  
+  /// \brief Add a new conversion function template to the list of visible
+  /// conversion functions.
+  void addVisibleConversionFunction(ASTContext &Context,
+                                    FunctionTemplateDecl *ConvDecl);
+  
   /// addConversionFunction - Add a new conversion function to the
   /// list of conversion functions.
   void addConversionFunction(ASTContext &Context, CXXConversionDecl *ConvDecl);

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

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Sep 11 16:44:33 2009
@@ -35,6 +35,7 @@
     HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
     HasTrivialDestructor(true), Bases(0), NumBases(0), VBases(0), NumVBases(0),
     Conversions(DC, DeclarationName()),
+    VisibleConversions(DC, DeclarationName()),
     TemplateOrInstantiation() { }
 
 CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -282,6 +283,89 @@
   PlainOldData = false;
 }
 
+/// getVisibleConversionFunctions - get all conversion functions visible
+/// in current class; including conversion function templates.
+OverloadedFunctionDecl *
+CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
+                                             CXXRecordDecl *RD) {
+  // If visible conversion list is already evaluated, return it.
+  if (RD == this &&
+      VisibleConversions.function_begin() != VisibleConversions.function_end())
+    return &VisibleConversions;
+    
+  QualType ClassType = Context.getTypeDeclType(this);
+  if (const RecordType *Record = ClassType->getAs<RecordType>()) {
+    OverloadedFunctionDecl *Conversions
+      = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
+    for (OverloadedFunctionDecl::function_iterator
+         Func = Conversions->function_begin(),
+         FuncEnd = Conversions->function_end();
+         Func != FuncEnd; ++Func) {
+      if (FunctionTemplateDecl *ConversionTemplate = 
+            dyn_cast<FunctionTemplateDecl>(*Func)) {
+        RD->addVisibleConversionFunction(Context, ConversionTemplate);
+        continue;
+      }
+      CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
+      bool Candidate = true;
+      // Only those conversions not exact match of conversions in current
+      // class are candidateconversion routines.
+      if (RD != this) {
+        OverloadedFunctionDecl *TopConversions = RD->getConversionFunctions();
+        QualType ConvType = Context.getCanonicalType(Conv->getType());
+        for (OverloadedFunctionDecl::function_iterator
+             TFunc = TopConversions->function_begin(),
+             TFuncEnd = TopConversions->function_end();
+             TFunc != TFuncEnd; ++TFunc) {
+          CXXConversionDecl *TopConv = cast<CXXConversionDecl>(*TFunc);
+          QualType TConvType = Context.getCanonicalType(TopConv->getType());
+          if (ConvType == TConvType) {
+            Candidate = false;
+            break;
+          }
+        }
+      }
+      if (Candidate) {
+        if (FunctionTemplateDecl *ConversionTemplate
+              = Conv->getDescribedFunctionTemplate())
+          RD->addVisibleConversionFunction(Context, ConversionTemplate);
+        else if (!Conv->getPrimaryTemplate()) // ignore specializations
+          RD->addVisibleConversionFunction(Context, Conv);
+      }
+    }
+  }
+  
+  for (CXXRecordDecl::base_class_iterator VBase = vbases_begin(),
+       E = vbases_end(); VBase != E; ++VBase) {
+    CXXRecordDecl *VBaseClassDecl
+      = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
+    VBaseClassDecl->getVisibleConversionFunctions(Context, RD);
+  }
+  for (CXXRecordDecl::base_class_iterator Base = bases_begin(),
+       E = bases_end(); Base != E; ++Base) {
+    if (Base->isVirtual())
+      continue;
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    BaseClassDecl->getVisibleConversionFunctions(Context, RD);
+  }
+  return &VisibleConversions;
+}
+
+void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context,
+                                          CXXConversionDecl *ConvDecl) {
+  assert(!ConvDecl->getDescribedFunctionTemplate() &&
+         "Conversion function templates should cast to FunctionTemplateDecl.");
+  VisibleConversions.addOverload(ConvDecl);
+}
+
+void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context,
+                                          FunctionTemplateDecl *ConvDecl) {
+  assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
+         "Function template is not a conversion function template");
+  VisibleConversions.addOverload(ConvDecl);
+}
+
 void CXXRecordDecl::addConversionFunction(ASTContext &Context,
                                           CXXConversionDecl *ConvDecl) {
   assert(!ConvDecl->getDescribedFunctionTemplate() &&

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Sep 11 16:44:33 2009
@@ -736,11 +736,11 @@
     QualType Type = Ex->getType();
 
     if (const RecordType *Record = Type->getAs<RecordType>()) {
-      // FIXME: Inherited conversion functions!
       llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions;
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+      OverloadedFunctionDecl *Conversions = 
+        RD->getVisibleConversionFunctions(Context, RD);
       
-      OverloadedFunctionDecl *Conversions
-        = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
       for (OverloadedFunctionDecl::function_iterator
              Func = Conversions->function_begin(),
              FuncEnd = Conversions->function_end();

Added: cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp?rev=81576&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp (added)
+++ cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp Fri Sep 11 16:44:33 2009
@@ -0,0 +1,83 @@
+// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
+
+// Test1
+struct B {
+  operator char *();
+};
+
+struct D : B {
+  operator int *();
+};
+
+void f (D d)
+{
+   delete d; // expected-error {{cannot delete expression of type 'struct D'}}
+}
+
+// Test2
+struct B1 {
+  operator int *();
+};
+
+struct D1 : B1 {
+  operator int *();
+};
+
+void f1 (D1 d)
+{
+   delete d;
+}
+
+// Test3
+struct B2 {
+  operator const int *();
+};
+
+struct D2 : B2 {
+  operator int *();
+};
+
+void f2 (D2 d)
+{
+   delete d; // expected-error {{cannot delete expression of type 'struct D2'}}
+}
+
+// Test4
+
+struct B3 {
+  operator const int *();
+};
+
+struct A3 {
+  operator const int *();
+};
+
+struct D3 : A3, B3 {
+};
+
+void f3 (D3 d)
+{
+   delete d; // expected-error {{cannot delete expression of type 'struct D3'}}
+}
+
+// Test5
+struct X {
+   operator int();
+   operator int*();
+};
+
+void f4(X x) { delete x; delete x; }
+
+// Test6
+
+struct X1 {
+   operator int();
+   operator int*();
+   template<typename T> operator T*() const; // converts to any pointer!
+};
+
+void f5(X1 x) { delete x; } // FIXME. May have to issue error here too.
+
+
+
+





More information about the cfe-commits mailing list