[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