[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