[cfe-commits] r124311 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/Sema/Overload.h include/clang/Sema/Sema.h lib/Sema/SemaOverload.cpp test/CXX/over/over.match/over.match.funcs/p4-0x.cpp

Douglas Gregor dgregor at apple.com
Wed Jan 26 11:30:29 PST 2011


Author: dgregor
Date: Wed Jan 26 13:30:28 2011
New Revision: 124311

URL: http://llvm.org/viewvc/llvm-project?rev=124311&view=rev
Log:
Rvalue references for *this: implement the implicit conversion rules
for the implicit object argument to a non-static member function with
a ref-qualifier (C++0x [over.match.funcs]p4).

Added:
    cfe/trunk/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/Sema/Overload.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaOverload.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=124311&r1=124310&r2=124311&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed Jan 26 13:30:28 2011
@@ -268,6 +268,12 @@
     bool isPRValue() const { return Kind >= CL_Function; }
     bool isRValue() const { return Kind >= CL_XValue; }
     bool isModifiable() const { return getModifiable() == CM_Modifiable; }
+    
+    /// \brief Create a simple, modifiably lvalue
+    static Classification makeSimpleLValue() {
+      return Classification(CL_LValue, CM_Modifiable);
+    }
+    
   };
   /// \brief Classify - Classify this expression according to the C++0x
   ///        expression taxonomy.

Modified: cfe/trunk/include/clang/Sema/Overload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Overload.h?rev=124311&r1=124310&r2=124311&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Overload.h (original)
+++ cfe/trunk/include/clang/Sema/Overload.h Wed Jan 26 13:30:28 2011
@@ -294,7 +294,9 @@
       no_conversion,
       unrelated_class,
       suppressed_user,
-      bad_qualifiers
+      bad_qualifiers,
+      lvalue_ref_to_rvalue,
+      rvalue_ref_to_lvalue
     };
 
     // This can be null, e.g. for implicit object arguments.

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=124311&r1=124310&r2=124311&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Jan 26 13:30:28 2011
@@ -20,7 +20,7 @@
 #include "clang/Sema/IdentifierResolver.h"
 #include "clang/Sema/ObjCMethodList.h"
 #include "clang/Sema/DeclSpec.h"
-#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/ExternalASTSource.h"
 #include "clang/AST/TypeLoc.h"
@@ -1080,12 +1080,14 @@
                              bool SuppressUserConversions = false);
   void AddMethodCandidate(DeclAccessPair FoundDecl,
                           QualType ObjectType,
+                          Expr::Classification ObjectClassification,
                           Expr **Args, unsigned NumArgs,
                           OverloadCandidateSet& CandidateSet,
                           bool SuppressUserConversion = false);
   void AddMethodCandidate(CXXMethodDecl *Method,
                           DeclAccessPair FoundDecl,
                           CXXRecordDecl *ActingContext, QualType ObjectType,
+                          Expr::Classification ObjectClassification,
                           Expr **Args, unsigned NumArgs,
                           OverloadCandidateSet& CandidateSet,
                           bool SuppressUserConversions = false);
@@ -1094,6 +1096,7 @@
                                   CXXRecordDecl *ActingContext,
                          const TemplateArgumentListInfo *ExplicitTemplateArgs,
                                   QualType ObjectType,
+                                  Expr::Classification ObjectClassification,
                                   Expr **Args, unsigned NumArgs,
                                   OverloadCandidateSet& CandidateSet,
                                   bool SuppressUserConversions = false);
@@ -1117,7 +1120,7 @@
                              DeclAccessPair FoundDecl,
                              CXXRecordDecl *ActingContext,
                              const FunctionProtoType *Proto,
-                             QualType ObjectTy, Expr **Args, unsigned NumArgs,
+                             Expr *Object, Expr **Args, unsigned NumArgs,
                              OverloadCandidateSet& CandidateSet);
   void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
                                    SourceLocation OpLoc,

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=124311&r1=124310&r2=124311&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Jan 26 13:30:28 2011
@@ -2345,9 +2345,10 @@
   // and std::reference_wrapper when dealing with references to functions.
   // Proposed wording changes submitted to CWG for consideration.
   //
-  // FIXME: Rvalue references. We don't know if we're dealing with the 
-  // implicit object parameter, or if the member function in this case has a 
-  // ref qualifier. (Of course, we don't have ref qualifiers yet.)
+  // Note: neither of these conditions will evalute true for the implicit 
+  // object parameter, because we don't set either BindsToRvalue or
+  // BindsToFunctionLvalue when computing the conversion sequence for the
+  // implicit object parameter.
   return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue &&
           SCS2.IsLvalueReference) ||
          (SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue &&
@@ -3182,6 +3183,7 @@
 /// expression @p From.
 static ImplicitConversionSequence
 TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
+                                Expr::Classification FromClassification,
                                 CXXMethodDecl *Method,
                                 CXXRecordDecl *ActingContext) {
   QualType ClassType = S.Context.getTypeDeclType(ActingContext);
@@ -3197,22 +3199,35 @@
 
   // We need to have an object of class type.
   QualType FromType = OrigFromType;
-  if (const PointerType *PT = FromType->getAs<PointerType>())
+  if (const PointerType *PT = FromType->getAs<PointerType>()) {
     FromType = PT->getPointeeType();
 
+    // When we had a pointer, it's implicitly dereferenced, so we
+    // better have an lvalue.
+    assert(FromClassification.isLValue());
+  }
+
   assert(FromType->isRecordType());
 
-  // The implicit object parameter is has the type "reference to cv X",
-  // where X is the class of which the function is a member
-  // (C++ [over.match.funcs]p4). However, when finding an implicit
-  // conversion sequence for the argument, we are not allowed to
-  // create temporaries or perform user-defined conversions
+  // C++0x [over.match.funcs]p4:
+  //   For non-static member functions, the type of the implicit object 
+  //   parameter is
+  //
+  //     — "lvalue reference to cv X" for functions declared without a 
+  //       ref-qualifier or with the & ref-qualifier
+  //     — "rvalue reference to cv X" for functions declared with the && 
+  //        ref-qualifier
+  //
+  // where X is the class of which the function is a member and cv is the 
+  // cv-qualification on the member function declaration.
+  //
+  // However, when finding an implicit conversion sequence for the argument, we 
+  // are not allowed to create temporaries or perform user-defined conversions
   // (C++ [over.match.funcs]p5). We perform a simplified version of
   // reference binding here, that allows class rvalues to bind to
   // non-constant references.
 
-  // First check the qualifiers. We don't care about lvalue-vs-rvalue
-  // with the implicit object parameter (C++ [over.match.funcs]p5).
+  // First check the qualifiers.
   QualType FromTypeCanon = S.Context.getCanonicalType(FromType);
   if (ImplicitParamType.getCVRQualifiers() 
                                     != FromTypeCanon.getLocalCVRQualifiers() &&
@@ -3236,6 +3251,31 @@
     return ICS;
   }
 
+  // Check the ref-qualifier.
+  switch (Method->getRefQualifier()) {
+  case RQ_None:
+    // Do nothing; we don't care about lvalueness or rvalueness.
+    break;
+      
+  case RQ_LValue:
+    if (!FromClassification.isLValue() && Quals != Qualifiers::Const) {
+      // non-const lvalue reference cannot bind to an rvalue
+      ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType, 
+                 ImplicitParamType);
+      return ICS;
+    }
+    break;
+
+  case RQ_RValue:
+    if (!FromClassification.isRValue()) {
+      // rvalue reference cannot bind to an lvalue
+      ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, FromType, 
+                 ImplicitParamType);
+      return ICS;
+    }
+    break;
+  }
+  
   // Success. Mark this as a reference binding.
   ICS.setStandard();
   ICS.Standard.setAsIdentityConversion();
@@ -3244,10 +3284,10 @@
   ICS.Standard.setAllToTypes(ImplicitParamType);
   ICS.Standard.ReferenceBinding = true;
   ICS.Standard.DirectBinding = true;
-  
-  // FIXME: Rvalue references.
-  ICS.Standard.IsLvalueReference = true; 
+  ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue; 
   ICS.Standard.BindsToFunctionLvalue = false;
+  
+  // Note: we intentionally don't set this; see isBetterReferenceBindingKind().
   ICS.Standard.BindsToRvalue = false;
   return ICS;
 }
@@ -3264,19 +3304,22 @@
   QualType ImplicitParamRecordType  =
     Method->getThisType(Context)->getAs<PointerType>()->getPointeeType();
 
+  Expr::Classification FromClassification;
   if (const PointerType *PT = From->getType()->getAs<PointerType>()) {
     FromRecordType = PT->getPointeeType();
     DestType = Method->getThisType(Context);
+    FromClassification = Expr::Classification::makeSimpleLValue();
   } else {
     FromRecordType = From->getType();
     DestType = ImplicitParamRecordType;
+    FromClassification = From->Classify(Context);
   }
 
   // Note that we always use the true parent context when performing
   // the actual argument initialization.
   ImplicitConversionSequence ICS
-    = TryObjectArgumentInitialization(*this, From->getType(), Method,
-                                      Method->getParent());
+    = TryObjectArgumentInitialization(*this, From->getType(), FromClassification,
+                                      Method, Method->getParent());
   if (ICS.isBad()) {
     if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
       Qualifiers FromQs = FromRecordType.getQualifiers();
@@ -3549,7 +3592,7 @@
     = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
   assert(Proto && "Functions without a prototype cannot be overloaded");
   assert(!Function->getDescribedFunctionTemplate() &&
-         "Use AddTemplateOverloadCandidate for function templates");
+         "Use AddTemp∫lateOverloadCandidate for function templates");
 
   if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
     if (!isa<CXXConstructorDecl>(Method)) {
@@ -3561,7 +3604,8 @@
       // object argument (C++ [over.call.func]p3), and the acting context
       // is irrelevant.
       AddMethodCandidate(Method, FoundDecl, Method->getParent(),
-                         QualType(), Args, NumArgs, CandidateSet,
+                         QualType(), Expr::Classification::makeSimpleLValue(), 
+                         Args, NumArgs, CandidateSet,
                          SuppressUserConversions);
       return;
     }
@@ -3662,7 +3706,8 @@
       if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
         AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
                            cast<CXXMethodDecl>(FD)->getParent(),
-                           Args[0]->getType(), Args + 1, NumArgs - 1, 
+                           Args[0]->getType(), Args[0]->Classify(Context),
+                           Args + 1, NumArgs - 1, 
                            CandidateSet, SuppressUserConversions);
       else
         AddOverloadCandidate(FD, F.getPair(), Args, NumArgs, CandidateSet,
@@ -3674,7 +3719,9 @@
         AddMethodTemplateCandidate(FunTmpl, F.getPair(),
                               cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
                                    /*FIXME: explicit args */ 0,
-                                   Args[0]->getType(), Args + 1, NumArgs - 1,
+                                   Args[0]->getType(), 
+                                   Args[0]->Classify(Context),
+                                   Args + 1, NumArgs - 1,
                                    CandidateSet,
                                    SuppressUserConversions);
       else
@@ -3690,6 +3737,7 @@
 /// method) as a method candidate to the given overload set.
 void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
                               QualType ObjectType,
+                              Expr::Classification ObjectClassification,
                               Expr **Args, unsigned NumArgs,
                               OverloadCandidateSet& CandidateSet,
                               bool SuppressUserConversions) {
@@ -3704,12 +3752,12 @@
            "Expected a member function template");
     AddMethodTemplateCandidate(TD, FoundDecl, ActingContext,
                                /*ExplicitArgs*/ 0,
-                               ObjectType, Args, NumArgs,
+                               ObjectType, ObjectClassification, Args, NumArgs,
                                CandidateSet,
                                SuppressUserConversions);
   } else {
     AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext,
-                       ObjectType, Args, NumArgs,
+                       ObjectType, ObjectClassification, Args, NumArgs,
                        CandidateSet, SuppressUserConversions);
   }
 }
@@ -3724,6 +3772,7 @@
 void
 Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
                          CXXRecordDecl *ActingContext, QualType ObjectType,
+                         Expr::Classification ObjectClassification,
                          Expr **Args, unsigned NumArgs,
                          OverloadCandidateSet& CandidateSet,
                          bool SuppressUserConversions) {
@@ -3782,8 +3831,8 @@
     // Determine the implicit conversion sequence for the object
     // parameter.
     Candidate.Conversions[0]
-      = TryObjectArgumentInitialization(*this, ObjectType, Method,
-                                        ActingContext);
+      = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification,
+                                        Method, ActingContext);
     if (Candidate.Conversions[0].isBad()) {
       Candidate.Viable = false;
       Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -3827,6 +3876,7 @@
                                  CXXRecordDecl *ActingContext,
                         const TemplateArgumentListInfo *ExplicitTemplateArgs,
                                  QualType ObjectType,
+                                 Expr::Classification ObjectClassification,
                                  Expr **Args, unsigned NumArgs,
                                  OverloadCandidateSet& CandidateSet,
                                  bool SuppressUserConversions) {
@@ -3867,8 +3917,8 @@
   assert(isa<CXXMethodDecl>(Specialization) &&
          "Specialization is not a member function?");
   AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
-                     ActingContext, ObjectType, Args, NumArgs,
-                     CandidateSet, SuppressUserConversions);
+                     ActingContext, ObjectType, ObjectClassification,
+                     Args, NumArgs, CandidateSet, SuppressUserConversions);
 }
 
 /// \brief Add a C++ function template specialization as a candidate
@@ -3968,8 +4018,9 @@
     = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
   
   Candidate.Conversions[0]
-    = TryObjectArgumentInitialization(*this, From->getType(), Conversion,
-                                      ConversionContext);
+    = TryObjectArgumentInitialization(*this, From->getType(), 
+                                      From->Classify(Context), 
+                                      Conversion, ConversionContext);
   
   if (Candidate.Conversions[0].isBad()) {
     Candidate.Viable = false;
@@ -4113,7 +4164,7 @@
                                  DeclAccessPair FoundDecl,
                                  CXXRecordDecl *ActingContext,
                                  const FunctionProtoType *Proto,
-                                 QualType ObjectType,
+                                 Expr *Object,
                                  Expr **Args, unsigned NumArgs,
                                  OverloadCandidateSet& CandidateSet) {
   if (!CandidateSet.isNewCandidate(Conversion))
@@ -4136,8 +4187,9 @@
   // Determine the implicit conversion sequence for the implicit
   // object parameter.
   ImplicitConversionSequence ObjectInit
-    = TryObjectArgumentInitialization(*this, ObjectType, Conversion,
-                                      ActingContext);
+    = TryObjectArgumentInitialization(*this, Object->getType(), 
+                                      Object->Classify(Context),
+                                      Conversion, ActingContext);
   if (ObjectInit.isBad()) {
     Candidate.Viable = false;
     Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -4249,7 +4301,8 @@
          Oper != OperEnd;
          ++Oper)
       AddMethodCandidate(Oper.getPair(), Args[0]->getType(),
-                         Args + 1, NumArgs - 1, CandidateSet,
+                         Args[0]->Classify(Context), Args + 1, NumArgs - 1, 
+                         CandidateSet,
                          /* SuppressUserConversions = */ false);
   }
 }
@@ -4901,8 +4954,8 @@
   //       T&         operator*(T*);
   //
   // C++ [over.built]p7:
-  //   For every function type T, there exist candidate operator
-  //   functions of the form
+  //   For every function type T that does not have cv-qualifiers or a 
+  //   ref-qualifier, there exist candidate operator functions of the form
   //       T&         operator*(T*);
   void addUnaryStarPointerOverloads() {
     for (BuiltinCandidateTypeSet::iterator
@@ -4914,6 +4967,10 @@
       if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType())
         continue;
       
+      if (const FunctionProtoType *Proto =PointeeTy->getAs<FunctionProtoType>())
+        if (Proto->getTypeQuals() || Proto->getRefQualifier())
+          continue;
+      
       S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy),
                             &ParamTy, Args, 1, CandidateSet);
     }
@@ -7950,6 +8007,9 @@
     Qualifier = UnresExpr->getQualifier();
     
     QualType ObjectType = UnresExpr->getBaseType();
+    Expr::Classification ObjectClassification
+      = UnresExpr->isArrow()? Expr::Classification::makeSimpleLValue()
+                            : UnresExpr->getBase()->Classify(Context);
 
     // Add overload candidates
     OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc());
@@ -7969,6 +8029,7 @@
       if (isa<UsingShadowDecl>(Func))
         Func = cast<UsingShadowDecl>(Func)->getTargetDecl();
 
+
       // Microsoft supports direct constructor calls.
       if (getLangOptions().Microsoft && isa<CXXConstructorDecl>(Func)) {
         AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, NumArgs,
@@ -7980,13 +8041,14 @@
           continue;
         
         AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType,
-                           Args, NumArgs,
-                           CandidateSet, /*SuppressUserConversions=*/false);
+                           ObjectClassification, 
+                           Args, NumArgs, CandidateSet, 
+                           /*SuppressUserConversions=*/false);
       } else {
         AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
                                    I.getPair(), ActingDC, TemplateArgs,
-                                   ObjectType, Args, NumArgs,
-                                   CandidateSet,
+                                   ObjectType,  ObjectClassification, 
+                                   Args, NumArgs, CandidateSet,
                                    /*SuppressUsedConversions=*/false);
       }
     }
@@ -8113,7 +8175,7 @@
   for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
        Oper != OperEnd; ++Oper) {
     AddMethodCandidate(Oper.getPair(), Object->getType(),
-                       Args, NumArgs, CandidateSet,
+                       Object->Classify(Context), Args, NumArgs, CandidateSet,
                        /*SuppressUserConversions=*/ false);
   }
   
@@ -8158,8 +8220,7 @@
 
     if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
       AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
-                            Object->getType(), Args, NumArgs,
-                            CandidateSet);
+                            Object, Args, NumArgs, CandidateSet);
   }
 
   // Perform overload resolution.
@@ -8369,8 +8430,8 @@
 
   for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
        Oper != OperEnd; ++Oper) {
-    AddMethodCandidate(Oper.getPair(), Base->getType(), 0, 0, CandidateSet,
-                       /*SuppressUserConversions=*/false);
+    AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context),
+                       0, 0, CandidateSet, /*SuppressUserConversions=*/false);
   }
 
   // Perform overload resolution.

Added: cfe/trunk/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp?rev=124311&view=auto
==============================================================================
--- cfe/trunk/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp (added)
+++ cfe/trunk/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp Wed Jan 26 13:30:28 2011
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename T> T &lvalue();
+template<typename T> T &&xvalue();
+template<typename T> T prvalue();
+
+struct X0 {
+  int &f() &;
+  float &f() &&;
+
+  template<typename T> int &ft(T) &;
+  template<typename T> float &ft(T) &&;
+
+  typedef int &(*func_int_ref)();
+  typedef float &(*func_float_ref)();
+
+  operator func_int_ref() &;
+  operator func_float_ref() &&;
+
+  void g();
+
+  int &operator+(const X0&) &;
+  float &operator+(const X0&) &&;
+
+  template<typename T> int &operator+(const T&) &;
+  template<typename T> float &operator+(const T&) &&;
+
+  int &h() const&;
+  float &h() &&;
+};
+
+void X0::g() {
+  int &ir1 = f();
+  int &ir2 = X0::f();
+}
+
+void test_ref_qualifier_binding() {
+  int &ir1 = lvalue<X0>().f();
+  float &fr1 = xvalue<X0>().f();
+  float &fr2 = prvalue<X0>().f();
+  int &ir2 = lvalue<X0>().ft(1);
+  float &fr3 = xvalue<X0>().ft(2);
+  float &fr4 = prvalue<X0>().ft(3);
+}
+
+void test_ref_qualifier_binding_with_surrogates() {
+  int &ir1 = lvalue<X0>()();
+  float &fr1 = xvalue<X0>()();
+  float &fr2 = prvalue<X0>()();
+}
+
+void test_ref_qualifier_binding_operators() {
+  int &ir1 = lvalue<X0>() + prvalue<X0>();
+  float &fr1 = xvalue<X0>() + prvalue<X0>();
+  float &fr2 = prvalue<X0>() + prvalue<X0>();
+  int &ir2 = lvalue<X0>() + 1;
+  float &fr3 = xvalue<X0>() + 2;
+  float &fr4 = prvalue<X0>() + 3;
+}
+
+void test_ref_qualifier_overloading() {
+  int &ir1 = lvalue<X0>().h();
+  float &fr1 = xvalue<X0>().h();
+  float &fr2 = prvalue<X0>().h();
+}

Propchange: cfe/trunk/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list