[cfe-commits] r84187 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/SemaCXX/ambiguous-builtin-unary-operator.cpp test/SemaCXX/builtin-ptrtomember-ambig.cpp test/SemaCXX/builtin-ptrtomember-overload.cpp

Fariborz Jahanian fjahanian at apple.com
Thu Oct 15 10:14:06 PDT 2009


Author: fjahanian
Date: Thu Oct 15 12:14:05 2009
New Revision: 84187

URL: http://llvm.org/viewvc/llvm-project?rev=84187&view=rev
Log:
Apply heuristics to cut back on number of candidate
sets of builtin operators. Currently, it is applied 
to '++' and '->*' operators. I need to apply it to others
as well. Also, heuristics need be applied to 
BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants.
This is WIP.


Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/ambiguous-builtin-unary-operator.cpp
    cfe/trunk/test/SemaCXX/builtin-ptrtomember-ambig.cpp
    cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload.cpp

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=84187&r1=84186&r2=84187&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Oct 15 12:14:05 2009
@@ -2884,7 +2884,8 @@
     : SemaRef(SemaRef), Context(SemaRef.Context) { }
 
   void AddTypesConvertedFrom(QualType Ty, bool AllowUserConversions,
-                             bool AllowExplicitConversions);
+                             bool AllowExplicitConversions,
+                             const Qualifiers &VisibleTypeConversionsQuals);
 
   /// pointer_begin - First pointer type found;
   iterator pointer_begin() { return PointerTypes.begin(); }
@@ -2984,7 +2985,8 @@
 void
 BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
                                                bool AllowUserConversions,
-                                               bool AllowExplicitConversions) {
+                                               bool AllowExplicitConversions,
+                                               const Qualifiers &VisibleQuals) {
   // Only deal with canonical types.
   Ty = Context.getCanonicalType(Ty);
 
@@ -3022,10 +3024,10 @@
         QualType BaseTy = Context.getCanonicalType(Base->getType());
         BaseTy = Context.getCVRQualifiedType(BaseTy.getUnqualifiedType(),
                                           PointeeTy.getCVRQualifiers());
-
         // Add the pointer type, recursively, so that we get all of
         // the indirect base classes, too.
-        AddTypesConvertedFrom(Context.getPointerType(BaseTy), false, false);
+        AddTypesConvertedFrom(Context.getPointerType(BaseTy), false, false,
+                              VisibleQuals);
       }
     }
   } else if (Ty->isMemberPointerType()) {
@@ -3056,8 +3058,10 @@
         if (ConvTemplate)
           continue;
 
-        if (AllowExplicitConversions || !Conv->isExplicit())
-          AddTypesConvertedFrom(Conv->getConversionType(), false, false);
+        if (AllowExplicitConversions || !Conv->isExplicit()) {
+          AddTypesConvertedFrom(Conv->getConversionType(), false, false, 
+                                VisibleQuals);
+        }
       }
     }
   }
@@ -3089,6 +3093,58 @@
   }
 }
 
+/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers
+/// , if any, found in visible type conversion functions found in ArgExpr's
+/// type.
+static  Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
+    Qualifiers VRQuals;
+    const RecordType *TyRec;
+    if (const MemberPointerType *RHSMPType =
+        ArgExpr->getType()->getAs<MemberPointerType>())
+      TyRec = cast<RecordType>(RHSMPType->getClass());
+    else
+      TyRec = ArgExpr->getType()->getAs<RecordType>();
+    if (!TyRec) {
+      // Just to be safe, asssume the worst case.
+      VRQuals.addVolatile();
+      VRQuals.addRestrict();
+      return VRQuals;
+    }
+    
+    CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+    OverloadedFunctionDecl *Conversions =
+    ClassDecl->getVisibleConversionFunctions();
+    
+    for (OverloadedFunctionDecl::function_iterator Func
+         = Conversions->function_begin();
+         Func != Conversions->function_end(); ++Func) {
+      if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(*Func)) {
+        QualType CanTy = Context.getCanonicalType(Conv->getConversionType());
+        if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>())
+          CanTy = ResTypeRef->getPointeeType();
+        // Need to go down the pointer/mempointer chain and add qualifiers
+        // as see them.
+        bool done = false;
+        while (!done) {
+          if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>())
+            CanTy = ResTypePtr->getPointeeType();
+          else if (const MemberPointerType *ResTypeMPtr = 
+                CanTy->getAs<MemberPointerType>())
+            CanTy = ResTypeMPtr->getPointeeType();
+          else
+            done = true;
+          if (CanTy.isVolatileQualified())
+            VRQuals.addVolatile();
+          if (CanTy.isRestrictQualified())
+            VRQuals.addRestrict();
+          if (VRQuals.hasRestrict() && VRQuals.hasVolatile())
+            return VRQuals;
+        }
+      }
+    }
+    return VRQuals;
+}
+  
 /// AddBuiltinOperatorCandidates - Add the appropriate built-in
 /// operator overloads to the candidate set (C++ [over.built]), based
 /// on the operator @p Op and the arguments given. For example, if the
@@ -3123,6 +3179,8 @@
   // Find all of the types that the arguments can convert to, but only
   // if the operator we're looking at has built-in operator candidates
   // that make use of these types.
+  Qualifiers VisibleTypeConversionsQuals;
+  VisibleTypeConversionsQuals.addConst();
   BuiltinCandidateTypeSet CandidateTypes(*this);
   if (Op == OO_Less || Op == OO_Greater || Op == OO_LessEqual ||
       Op == OO_GreaterEqual || Op == OO_EqualEqual || Op == OO_ExclaimEqual ||
@@ -3131,11 +3189,15 @@
       Op == OO_ArrowStar || Op == OO_PlusPlus || Op == OO_MinusMinus ||
       (Op == OO_Star && NumArgs == 1) || Op == OO_Conditional) {
     for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+      VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
+      
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
       CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(),
                                            true,
                                            (Op == OO_Exclaim ||
                                             Op == OO_AmpAmp ||
-                                            Op == OO_PipePipe));
+                                            Op == OO_PipePipe),
+                                           VisibleTypeConversionsQuals);
   }
 
   bool isComparison = false;
@@ -3202,14 +3264,17 @@
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
       else
         AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
-
-      // Volatile version
-      ParamTypes[0]
-        = Context.getLValueReferenceType(Context.getVolatileType(ArithTy));
-      if (NumArgs == 1)
-        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
-      else
-        AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
+      // heuristic to reduce number of builtin candidates in the set.
+      // Add volatile version only if there are conversions to a volatile type.
+      if (VisibleTypeConversionsQuals.hasVolatile()) {
+        // Volatile version
+        ParamTypes[0]
+          = Context.getLValueReferenceType(Context.getVolatileType(ArithTy));
+        if (NumArgs == 1)
+          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+        else
+          AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
+      }
     }
 
     // C++ [over.built]p5:
@@ -3238,7 +3303,8 @@
       else
         AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
 
-      if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
+      if (!Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+          VisibleTypeConversionsQuals.hasVolatile()) {
         // With volatile
         ParamTypes[0]
           = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
@@ -3708,6 +3774,13 @@
           C1 = QualType(Q1.strip(PointerTy->getPointeeType()), 0);
           if (!isa<RecordType>(C1))
             continue;
+          // heuristic to reduce number of builtin candidates in the set.
+          // Add volatile/restrict version only if there are conversions to a
+          // volatile/restrict type.
+          if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
+            continue;
+          if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
+            continue;
         }
         for (BuiltinCandidateTypeSet::iterator
              MemPtr = CandidateTypes.member_pointer_begin(),
@@ -3721,6 +3794,12 @@
           QualType ParamTypes[2] = { *Ptr, *MemPtr };
           // build CV12 T&
           QualType T = mptr->getPointeeType();
+          if (!VisibleTypeConversionsQuals.hasVolatile() && 
+              T.isVolatileQualified())
+            continue;
+          if (!VisibleTypeConversionsQuals.hasRestrict() && 
+              T.isRestrictQualified())
+            continue;
           T = Q1.apply(T);
           QualType ResultTy = Context.getLValueReferenceType(T);
           AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);

Modified: cfe/trunk/test/SemaCXX/ambiguous-builtin-unary-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ambiguous-builtin-unary-operator.cpp?rev=84187&r1=84186&r2=84187&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/ambiguous-builtin-unary-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/ambiguous-builtin-unary-operator.cpp Thu Oct 15 12:14:05 2009
@@ -2,17 +2,33 @@
 
 struct A {
   operator int&();
+  operator long*& ();
 };
 
 struct B {
   operator long&();
+  operator int*& ();
 };
 
 struct C : B, A { };
 
 void test(C c) {
   ++c; // expected-error {{use of overloaded operator '++' is ambiguous}}\
-       // expected-note 4 {{built-in candidate operator ++ (}}
+       // expected-note {{built-in candidate operator ++ ('int &')}} \
+       // expected-note {{built-in candidate operator ++ ('long &')}} \
+       // expected-note {{built-in candidate operator ++ ('long *&')}} \
+       // expected-note {{built-in candidate operator ++ ('int *&')}}
 }
 
+struct A1 { operator volatile int&(); };
+
+struct B1 { operator volatile long&(); };
+
+struct C1 : B1, A1 { };
+
+void test(C1 c) {
+  ++c;	// expected-error {{use of overloaded operator '++' is ambiguous}} \
+	// expected-note {{built-in candidate operator ++ ('int volatile &')}} \
+	// expected-note {{built-in candidate operator ++ ('long volatile &')}}
+}
 

Modified: cfe/trunk/test/SemaCXX/builtin-ptrtomember-ambig.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/builtin-ptrtomember-ambig.cpp?rev=84187&r1=84186&r2=84187&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/builtin-ptrtomember-ambig.cpp (original)
+++ cfe/trunk/test/SemaCXX/builtin-ptrtomember-ambig.cpp Thu Oct 15 12:14:05 2009
@@ -19,6 +19,9 @@
 void foo(C c, int A::* pmf) {
        				// FIXME. Why so many built-in candidates?
 	int i = c->*pmf; 	// expected-error {{use of overloaded operator '->*' is ambiguous}} \
-				// expected-note 40 {{built-in candidate operator ->* ('struct A}}
+				// expected-note {{built-in candidate operator ->* ('struct A const *', 'int const struct A::*')}} \
+				// expected-note {{built-in candidate operator ->* ('struct A const *', 'int struct A::*')}} \
+				// expected-note {{built-in candidate operator ->* ('struct A *', 'int const struct A::*')}} \
+				// expected-note {{built-in candidate operator ->* ('struct A *', 'int struct A::*')}}
 }
 

Modified: cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload.cpp?rev=84187&r1=84186&r2=84187&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload.cpp (original)
+++ cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload.cpp Thu Oct 15 12:14:05 2009
@@ -16,3 +16,15 @@
 	int i = b->*pmf;
 }
 
+struct D {
+ operator const D *();
+};
+
+struct DPtr {
+ operator volatile int D::*();
+};
+
+int test(D d, DPtr dptr) {
+ return d->*dptr;
+}
+





More information about the cfe-commits mailing list