diff options
author | John McCall <rjmccall@apple.com> | 2009-12-03 04:06:58 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-12-03 04:06:58 +0000 |
commit | 701c89e02cde6e0fb9673cbe7c97eadc74b50358 (patch) | |
tree | dc0e4e30cebf6b4274abead5ae74575616c4cedf | |
parent | 919d5e51fd0a1b6e52028c8aa42edf44ee036954 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90410 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 18 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 142 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp | 63 | ||||
-rw-r--r-- | test/Parser/cxx-using-declaration.cpp | 1 |
5 files changed, 171 insertions, 68 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index bd41072d3a..5d6dc96638 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -896,7 +896,8 @@ public: 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 @@ public: 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 @@ public: 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, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 37681719aa..20cc290b18 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3906,23 +3906,28 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, = 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); } } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index fdeda40ea2..769adb51cf 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1447,6 +1447,11 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( = 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 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( 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 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType, /// 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 @@ Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) { 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 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) { 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 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // 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 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions, 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 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions, 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 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions, /// 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 @@ void Sema::AddMethodCandidate(NamedDecl *Decl, Expr *Object, 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 @@ void Sema::AddMethodCandidate(NamedDecl *Decl, Expr *Object, /// 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 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object, 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 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object, /// 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 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, 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 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, /// conversion function produces). void Sema::AddConversionCandidate(CXXConversionDecl *Conversion, + CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet& CandidateSet) { assert(!Conversion->getDescribedFunctionTemplate() && @@ -2612,7 +2634,9 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // 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 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, /// [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 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, // 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 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, /// 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 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, // 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 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, 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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } 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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, 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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, 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 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, 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 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, = 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 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, 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 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { 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; diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp new file mode 100644 index 0000000000..1a05aae3af --- /dev/null +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp @@ -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 diff --git a/test/Parser/cxx-using-declaration.cpp b/test/Parser/cxx-using-declaration.cpp index 461b9e597d..20c9fb391a 100644 --- a/test/Parser/cxx-using-declaration.cpp +++ b/test/Parser/cxx-using-declaration.cpp @@ -1,5 +1,4 @@ // RUN: clang-cc -fsyntax-only -verify %s -// XFAIL: * namespace A { int VA; |