[cfe-commits] r90410 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaOverload.cpp test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp test/Parser/cxx-using-declaration.cpp
John McCall
rjmccall at apple.com
Wed Dec 2 20:06:58 PST 2009
Author: rjmccall
Date: Wed Dec 2 22:06:58 2009
New Revision: 90410
URL: http://llvm.org/viewvc/llvm-project?rev=90410&view=rev
Log:
Honor using declarations in overload resolution. Most of the code for
overloaded-operator resolution is wildly untested, but the parallel code for
methods seems to satisfy some trivial tests.
Also change some overload-resolution APIs to take a type instead of an expression,
which lets us avoid creating a spurious CXXThisExpr when resolving implicit
member accesses.
Added:
cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/Parser/cxx-using-declaration.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=90410&r1=90409&r2=90410&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Dec 2 22:06:58 2009
@@ -896,7 +896,8 @@
const char *Flavor, bool Elidable = false);
ImplicitConversionSequence
- TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method);
+ TryObjectArgumentInitialization(QualType FromType, CXXMethodDecl *Method,
+ CXXRecordDecl *ActingContext);
bool PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method);
ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From);
@@ -922,18 +923,20 @@
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false);
void AddMethodCandidate(NamedDecl *Decl,
- Expr *Object, Expr **Args, unsigned NumArgs,
+ QualType ObjectType, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversion = false,
bool ForceRValue = false);
- void AddMethodCandidate(CXXMethodDecl *Method,
- Expr *Object, Expr **Args, unsigned NumArgs,
+ void AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext,
+ QualType ObjectType, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool ForceRValue = false);
void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+ CXXRecordDecl *ActingContext,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
- Expr *Object, Expr **Args, unsigned NumArgs,
+ QualType ObjectType,
+ Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool ForceRValue = false);
@@ -944,14 +947,17 @@
bool SuppressUserConversions = false,
bool ForceRValue = false);
void AddConversionCandidate(CXXConversionDecl *Conversion,
+ CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet);
void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet);
void AddSurrogateCandidate(CXXConversionDecl *Conversion,
+ CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
- Expr *Object, Expr **Args, unsigned NumArgs,
+ QualType ObjectTy, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet);
void AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
SourceLocation OpLoc,
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=90410&r1=90409&r2=90410&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Dec 2 22:06:58 2009
@@ -3906,23 +3906,28 @@
= T2RecordDecl->getVisibleConversionFunctions();
for (UnresolvedSet::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
FunctionTemplateDecl *ConvTemplate
- = dyn_cast<FunctionTemplateDecl>(*I);
+ = dyn_cast<FunctionTemplateDecl>(D);
CXXConversionDecl *Conv;
if (ConvTemplate)
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
- Conv = cast<CXXConversionDecl>(*I);
+ Conv = cast<CXXConversionDecl>(D);
// If the conversion function doesn't return a reference type,
// it can't be considered for this conversion.
if (Conv->getConversionType()->isLValueReferenceType() &&
(AllowExplicit || !Conv->isExplicit())) {
if (ConvTemplate)
- AddTemplateConversionCandidate(ConvTemplate, Init, DeclType,
- CandidateSet);
+ AddTemplateConversionCandidate(ConvTemplate, ActingDC,
+ Init, DeclType, CandidateSet);
else
- AddConversionCandidate(Conv, Init, DeclType, CandidateSet);
+ AddConversionCandidate(Conv, ActingDC, Init, DeclType, CandidateSet);
}
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=90410&r1=90409&r2=90410&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Dec 2 22:06:58 2009
@@ -1447,6 +1447,11 @@
= FromRecordDecl->getVisibleConversionFunctions();
for (UnresolvedSet::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
CXXConversionDecl *Conv;
FunctionTemplateDecl *ConvTemplate;
if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(*I)))
@@ -1456,10 +1461,11 @@
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
- AddTemplateConversionCandidate(ConvTemplate, From, ToType,
- CandidateSet);
+ AddTemplateConversionCandidate(ConvTemplate, ActingContext,
+ From, ToType, CandidateSet);
else
- AddConversionCandidate(Conv, From, ToType, CandidateSet);
+ AddConversionCandidate(Conv, ActingContext, From, ToType,
+ CandidateSet);
}
}
}
@@ -2076,8 +2082,10 @@
/// parameter of the given member function (@c Method) from the
/// expression @p From.
ImplicitConversionSequence
-Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) {
- QualType ClassType = Context.getTypeDeclType(Method->getParent());
+Sema::TryObjectArgumentInitialization(QualType FromType,
+ CXXMethodDecl *Method,
+ CXXRecordDecl *ActingContext) {
+ QualType ClassType = Context.getTypeDeclType(ActingContext);
// [class.dtor]p2: A destructor can be invoked for a const, volatile or
// const volatile object.
unsigned Quals = isa<CXXDestructorDecl>(Method) ?
@@ -2091,7 +2099,6 @@
ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
// We need to have an object of class type.
- QualType FromType = From->getType();
if (const PointerType *PT = FromType->getAs<PointerType>())
FromType = PT->getPointeeType();
@@ -2151,8 +2158,11 @@
DestType = ImplicitParamRecordType;
}
+ // Note that we always use the true parent context when performing
+ // the actual argument initialization.
ImplicitConversionSequence ICS
- = TryObjectArgumentInitialization(From, Method);
+ = TryObjectArgumentInitialization(From->getType(), Method,
+ Method->getParent());
if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion)
return Diag(From->getSourceRange().getBegin(),
diag::err_implicit_object_parameter_init)
@@ -2227,9 +2237,11 @@
// that is named without a member access expression (e.g.,
// "this->f") that was either written explicitly or created
// implicitly. This can happen with a qualified call to a member
- // function, e.g., X::f(). We use a NULL object as the implied
- // object argument (C++ [over.call.func]p3).
- AddMethodCandidate(Method, 0, Args, NumArgs, CandidateSet,
+ // function, e.g., X::f(). We use an empty type for the implied
+ // object argument (C++ [over.call.func]p3), and the acting context
+ // is irrelevant.
+ AddMethodCandidate(Method, Method->getParent(),
+ QualType(), Args, NumArgs, CandidateSet,
SuppressUserConversions, ForceRValue);
return;
}
@@ -2341,10 +2353,12 @@
for (FunctionSet::const_iterator F = Functions.begin(),
FEnd = Functions.end();
F != FEnd; ++F) {
+ // FIXME: using declarations
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F)) {
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
AddMethodCandidate(cast<CXXMethodDecl>(FD),
- Args[0], Args + 1, NumArgs - 1,
+ cast<CXXMethodDecl>(FD)->getParent(),
+ Args[0]->getType(), Args + 1, NumArgs - 1,
CandidateSet, SuppressUserConversions);
else
AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
@@ -2354,8 +2368,9 @@
if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
!cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
AddMethodTemplateCandidate(FunTmpl,
+ cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
/*FIXME: explicit args */ 0,
- Args[0], Args + 1, NumArgs - 1,
+ Args[0]->getType(), Args + 1, NumArgs - 1,
CandidateSet,
SuppressUserConversions);
else
@@ -2369,13 +2384,14 @@
/// AddMethodCandidate - Adds a named decl (which is some kind of
/// method) as a method candidate to the given overload set.
-void Sema::AddMethodCandidate(NamedDecl *Decl, Expr *Object,
+void Sema::AddMethodCandidate(NamedDecl *Decl,
+ QualType ObjectType,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions, bool ForceRValue) {
// FIXME: use this
- //DeclContext *ActingContext = Decl->getDeclContext();
+ CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(Decl->getDeclContext());
if (isa<UsingShadowDecl>(Decl))
Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl();
@@ -2383,13 +2399,14 @@
if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
"Expected a member function template");
- AddMethodTemplateCandidate(TD, /*ExplicitArgs*/ 0,
- Object, Args, NumArgs,
+ AddMethodTemplateCandidate(TD, ActingContext, /*ExplicitArgs*/ 0,
+ ObjectType, Args, NumArgs,
CandidateSet,
SuppressUserConversions,
ForceRValue);
} else {
- AddMethodCandidate(cast<CXXMethodDecl>(Decl), Object, Args, NumArgs,
+ AddMethodCandidate(cast<CXXMethodDecl>(Decl), ActingContext,
+ ObjectType, Args, NumArgs,
CandidateSet, SuppressUserConversions, ForceRValue);
}
}
@@ -2404,8 +2421,8 @@
/// a slightly hacky way to implement the overloading rules for elidable copy
/// initialization in C++0x (C++0x 12.8p15).
void
-Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object,
- Expr **Args, unsigned NumArgs,
+Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext,
+ QualType ObjectType, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions, bool ForceRValue) {
const FunctionProtoType* Proto
@@ -2454,13 +2471,14 @@
Candidate.Viable = true;
Candidate.Conversions.resize(NumArgs + 1);
- if (Method->isStatic() || !Object)
+ if (Method->isStatic() || ObjectType.isNull())
// The implicit object argument is ignored.
Candidate.IgnoreObjectArgument = true;
else {
// Determine the implicit conversion sequence for the object
// parameter.
- Candidate.Conversions[0] = TryObjectArgumentInitialization(Object, Method);
+ Candidate.Conversions[0]
+ = TryObjectArgumentInitialization(ObjectType, Method, ActingContext);
if (Candidate.Conversions[0].ConversionKind
== ImplicitConversionSequence::BadConversion) {
Candidate.Viable = false;
@@ -2501,8 +2519,10 @@
/// function template specialization.
void
Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+ CXXRecordDecl *ActingContext,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
- Expr *Object, Expr **Args, unsigned NumArgs,
+ QualType ObjectType,
+ Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions,
bool ForceRValue) {
@@ -2534,7 +2554,8 @@
assert(Specialization && "Missing member function template specialization?");
assert(isa<CXXMethodDecl>(Specialization) &&
"Specialization is not a member function?");
- AddMethodCandidate(cast<CXXMethodDecl>(Specialization), Object, Args, NumArgs,
+ AddMethodCandidate(cast<CXXMethodDecl>(Specialization), ActingContext,
+ ObjectType, Args, NumArgs,
CandidateSet, SuppressUserConversions, ForceRValue);
}
@@ -2586,6 +2607,7 @@
/// conversion function produces).
void
Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
+ CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet) {
assert(!Conversion->getDescribedFunctionTemplate() &&
@@ -2612,7 +2634,9 @@
// object parameter.
Candidate.Viable = true;
Candidate.Conversions.resize(1);
- Candidate.Conversions[0] = TryObjectArgumentInitialization(From, Conversion);
+ Candidate.Conversions[0]
+ = TryObjectArgumentInitialization(From->getType(), Conversion,
+ ActingContext);
// Conversion functions to a different type in the base class is visible in
// the derived class. So, a derived to base conversion should not participate
// in overload resolution.
@@ -2684,6 +2708,7 @@
/// [temp.deduct.conv]).
void
Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ CXXRecordDecl *ActingDC,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet) {
assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
@@ -2706,7 +2731,7 @@
// Add the conversion function template specialization produced by
// template argument deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
- AddConversionCandidate(Specialization, From, ToType, CandidateSet);
+ AddConversionCandidate(Specialization, ActingDC, From, ToType, CandidateSet);
}
/// AddSurrogateCandidate - Adds a "surrogate" candidate function that
@@ -2715,8 +2740,10 @@
/// with the given arguments (C++ [over.call.object]p2-4). Proto is
/// the type of function that we'll eventually be calling.
void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
+ CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
- Expr *Object, Expr **Args, unsigned NumArgs,
+ QualType ObjectType,
+ Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet) {
if (!CandidateSet.isNewCandidate(Conversion))
return;
@@ -2736,7 +2763,7 @@
// Determine the implicit conversion sequence for the implicit
// object parameter.
ImplicitConversionSequence ObjectInit
- = TryObjectArgumentInitialization(Object, Conversion);
+ = TryObjectArgumentInitialization(ObjectType, Conversion, ActingContext);
if (ObjectInit.ConversionKind == ImplicitConversionSequence::BadConversion) {
Candidate.Viable = false;
return;
@@ -2871,7 +2898,8 @@
OperEnd = Operators.end();
Oper != OperEnd;
++Oper)
- AddMethodCandidate(*Oper, Args[0], Args + 1, NumArgs - 1, CandidateSet,
+ AddMethodCandidate(*Oper, Args[0]->getType(),
+ Args + 1, NumArgs - 1, CandidateSet,
/* SuppressUserConversions = */ false);
}
}
@@ -5140,16 +5168,7 @@
} else {
UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
- // Mock up an object argument.
- Expr *ObjectArg;
- if (UnresExpr->isImplicitAccess()) {
- // It would be nice to avoid creating this, but the overload APIs are written
- // to work on expressions.
- ObjectArg = new(Context) CXXThisExpr(SourceLocation(),
- UnresExpr->getBaseType());
- } else {
- ObjectArg = UnresExpr->getBase();
- }
+ QualType ObjectType = UnresExpr->getBaseType();
// Add overload candidates
OverloadCandidateSet CandidateSet;
@@ -5164,21 +5183,23 @@
for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(),
E = UnresExpr->decls_end(); I != E; ++I) {
- // TODO: note if we found something through a using declaration
- NamedDecl *Func = (*I)->getUnderlyingDecl();
-
+ NamedDecl *Func = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(Func->getDeclContext());
+ if (isa<UsingShadowDecl>(Func))
+ Func = cast<UsingShadowDecl>(Func)->getTargetDecl();
+
if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
// If explicit template arguments were provided, we can't call a
// non-template member function.
if (TemplateArgs)
continue;
- AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet,
- /*SuppressUserConversions=*/false);
+ AddMethodCandidate(Method, ActingDC, ObjectType, Args, NumArgs,
+ CandidateSet, /*SuppressUserConversions=*/false);
} else {
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
- TemplateArgs,
- ObjectArg, Args, NumArgs,
+ ActingDC, TemplateArgs,
+ ObjectType, Args, NumArgs,
CandidateSet,
/*SuppressUsedConversions=*/false);
}
@@ -5218,11 +5239,6 @@
MemExprE = FixOverloadedFunctionReference(MemExprE, Method);
- // Clean up the 'this' expression we created above; FixOFR doesn't
- // actually use it.
- if (UnresExpr->isImplicitAccess())
- Owned(ObjectArg);
-
// If overload resolution picked a static member, build a
// non-member call based on that function.
if (Method->isStatic()) {
@@ -5298,7 +5314,7 @@
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
- AddMethodCandidate(*Oper, Object, Args, NumArgs, CandidateSet,
+ AddMethodCandidate(*Oper, Object->getType(), Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/ false);
}
@@ -5324,12 +5340,17 @@
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
for (UnresolvedSet::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
// Skip over templated conversion functions; they aren't
// surrogates.
- if (isa<FunctionTemplateDecl>(*I))
+ if (isa<FunctionTemplateDecl>(D))
continue;
- CXXConversionDecl *Conv = cast<CXXConversionDecl>(*I);
+ CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
// Strip the reference type (if any) and then the pointer type (if
// any) to get down to what might be a function type.
@@ -5338,7 +5359,9 @@
ConvType = ConvPtrType->getPointeeType();
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
- AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
+ AddSurrogateCandidate(Conv, ActingContext, Proto,
+ Object->getType(), Args, NumArgs,
+ CandidateSet);
}
// Perform overload resolution.
@@ -5525,9 +5548,16 @@
R.suppressDiagnostics();
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
- Oper != OperEnd; ++Oper)
- AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Base, 0, 0, CandidateSet,
+ Oper != OperEnd; ++Oper) {
+ NamedDecl *D = *Oper;
+ CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ AddMethodCandidate(cast<CXXMethodDecl>(D), ActingContext,
+ Base->getType(), 0, 0, CandidateSet,
/*SuppressUserConversions=*/false);
+ }
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
Added: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp?rev=90410&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp Wed Dec 2 22:06:58 2009
@@ -0,0 +1,63 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// C++03 [namespace.udecl]p3:
+// For the purpose of overload resolution, the functions which are
+// introduced by a using-declaration into a derived class will be
+// treated as though they were members of the derived class. In
+// particular, the implicit this parameter shall be treated as if it
+// were a pointer to the derived class rather than to the base
+// class. This has no effect on the type of the function, and in all
+// other respects the function remains a member of the base class.
+
+namespace test0 {
+ struct Opaque0 {};
+ struct Opaque1 {};
+
+ struct Base {
+ Opaque0 test0(int*);
+ Opaque0 test1(const int*);
+ Opaque0 test2(int*);
+ Opaque0 test3(int*) const;
+ };
+
+ struct Derived : Base {
+ using Base::test0;
+ Opaque1 test0(const int*);
+
+ using Base::test1;
+ Opaque1 test1(int*);
+
+ using Base::test2;
+ Opaque1 test2(int*) const;
+
+ using Base::test3;
+ Opaque1 test3(int*);
+ };
+
+ void test0() {
+ Opaque0 a = Derived().test0((int*) 0);
+ Opaque1 b = Derived().test0((const int*) 0);
+ }
+
+ void test1() {
+ Opaque1 a = Derived().test1((int*) 0);
+ Opaque0 b = Derived().test1((const int*) 0);
+ }
+
+ void test2() {
+ Opaque0 a = ((Derived*) 0)->test2((int*) 0);
+ Opaque1 b = ((const Derived*) 0)->test2((int*) 0);
+ }
+
+ void test3() {
+ Opaque1 a = ((Derived*) 0)->test3((int*) 0);
+ Opaque0 b = ((const Derived*) 0)->test3((int*) 0);
+ }
+}
+
+// Things to test:
+// member operators
+// conversion operators
+// call operators
+// call-surrogate conversion operators
+// everything, but in dependent contexts
Modified: cfe/trunk/test/Parser/cxx-using-declaration.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-using-declaration.cpp?rev=90410&r1=90409&r2=90410&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-using-declaration.cpp (original)
+++ cfe/trunk/test/Parser/cxx-using-declaration.cpp Wed Dec 2 22:06:58 2009
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL: *
namespace A {
int VA;
More information about the cfe-commits
mailing list