[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