]> granicus.if.org Git - clang/commitdiff
Clean up the helpers used to compute the usual arithmetic conversions' result
authorChandler Carruth <chandlerc@gmail.com>
Sun, 12 Dec 2010 09:59:53 +0000 (09:59 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sun, 12 Dec 2010 09:59:53 +0000 (09:59 +0000)
type. Localize all of the logic within a single function rather than spreading
it throughout the class.

Also fixes a buglet where we failed to check for a RHS arithmetic type wider
than the LHS and return its canonical type. I've yet to produce a test case
that breaks because of this, but it was spotted by inspection by folks on the
IRC channel and is obviously correct now.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121633 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOverload.cpp

index 99b483ff6e08b3f4325b42522f331089a71f6e44..f89107e08b072a15d0776bfa2f8e350981b8a864 100644 (file)
@@ -4571,45 +4571,6 @@ class BuiltinOperatorOverloadBuilder {
 
   static CanQualType ASTContext::* const ArithmeticTypes[NumArithmeticTypes];
 
-  // Accelerator table for performing the usual arithmetic conversions.
-  // The rules are basically:
-  //   - if either is floating-point, use the wider floating-point
-  //   - if same signedness, use the higher rank
-  //   - if same size, use unsigned of the higher rank
-  //   - use the larger type
-  // These rules, together with the axiom that higher ranks are
-  // never smaller, are sufficient to precompute all of these results
-  // *except* when dealing with signed types of higher rank.
-  // (we could precompute SLL x UI for all known platforms, but it's
-  // better not to make any assumptions).
-  enum PromT {  Flt,  Dbl, LDbl,   SI,   SL,  SLL,   UI,   UL,  ULL, Dep=-1 };
-  static PromT UsualArithmeticConversionsTypes
-    [LastPromotedArithmeticType][LastPromotedArithmeticType];
-  struct UsualArithmeticConversionsType {
-    static CanQualType find(ASTContext &C, unsigned L, unsigned R) {
-      assert(L < LastPromotedArithmeticType);
-      assert(R < LastPromotedArithmeticType);
-      signed char Idx = UsualArithmeticConversionsTypes[L][R];
-
-      // Fast path: the table gives us a concrete answer.
-      if (Idx != Dep) return C.*ArithmeticTypes[Idx];
-
-      // Slow path: we need to compare widths.
-      // An invariant is that the signed type has higher rank.
-      CanQualType LT = C.*ArithmeticTypes[L], RT = C.*ArithmeticTypes[R];
-      unsigned LW = C.getIntWidth(LT), RW = C.getIntWidth(RT);
-
-      // If they're different widths, use the signed type.
-      if (LW > RW) return LT;
-      else if (LW > RW) return RT;
-
-      // Otherwise, use the unsigned type of the signed type's rank.
-      if (L == SL || R == SL) return C.UnsignedLongTy;
-      assert(L == SLL || R == SLL);
-      return C.UnsignedLongLongTy;
-    }
-  };
-
   // Common instance state available to all overload candidate addition methods.
   Sema &S;
   Expr **Args;
@@ -4618,6 +4579,60 @@ class BuiltinOperatorOverloadBuilder {
   llvm::SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
   OverloadCandidateSet &CandidateSet;
 
+  /// \brief Gets the canonical type resulting from the usual arithemetic
+  /// converions for the given arithmetic types.
+  CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) {
+    // Accelerator table for performing the usual arithmetic conversions.
+    // The rules are basically:
+    //   - if either is floating-point, use the wider floating-point
+    //   - if same signedness, use the higher rank
+    //   - if same size, use unsigned of the higher rank
+    //   - use the larger type
+    // These rules, together with the axiom that higher ranks are
+    // never smaller, are sufficient to precompute all of these results
+    // *except* when dealing with signed types of higher rank.
+    // (we could precompute SLL x UI for all known platforms, but it's
+    // better not to make any assumptions).
+    enum PromotedType {
+                  Flt,  Dbl, LDbl,   SI,   SL,  SLL,   UI,   UL,  ULL, Dep=-1
+    };
+    static PromotedType ConversionsTable[LastPromotedArithmeticType]
+                                        [LastPromotedArithmeticType] = {
+      /* Flt*/ {  Flt,  Dbl, LDbl,  Flt,  Flt,  Flt,  Flt,  Flt,  Flt },
+      /* Dbl*/ {  Dbl,  Dbl, LDbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl },
+      /*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl },
+      /*  SI*/ {  Flt,  Dbl, LDbl,   SI,   SL,  SLL,   UI,   UL,  ULL },
+      /*  SL*/ {  Flt,  Dbl, LDbl,   SL,   SL,  SLL,  Dep,   UL,  ULL },
+      /* SLL*/ {  Flt,  Dbl, LDbl,  SLL,  SLL,  SLL,  Dep,  Dep,  ULL },
+      /*  UI*/ {  Flt,  Dbl, LDbl,   UI,  Dep,  Dep,   UI,   UL,  ULL },
+      /*  UL*/ {  Flt,  Dbl, LDbl,   UL,   UL,  Dep,   UL,   UL,  ULL },
+      /* ULL*/ {  Flt,  Dbl, LDbl,  ULL,  ULL,  ULL,  ULL,  ULL,  ULL },
+    };
+
+    assert(L < LastPromotedArithmeticType);
+    assert(R < LastPromotedArithmeticType);
+    int Idx = ConversionsTable[L][R];
+
+    // Fast path: the table gives us a concrete answer.
+    if (Idx != Dep) return S.Context.*ArithmeticTypes[Idx];
+
+    // Slow path: we need to compare widths.
+    // An invariant is that the signed type has higher rank.
+    CanQualType LT = S.Context.*ArithmeticTypes[L],
+                RT = S.Context.*ArithmeticTypes[R];
+    unsigned LW = S.Context.getIntWidth(LT),
+             RW = S.Context.getIntWidth(RT);
+
+    // If they're different widths, use the signed type.
+    if (LW > RW) return LT;
+    else if (LW < RW) return RT;
+
+    // Otherwise, use the unsigned type of the signed type's rank.
+    if (L == SL || R == SL) return S.Context.UnsignedLongTy;
+    assert(L == SLL || R == SLL);
+    return S.Context.UnsignedLongLongTy;
+  }
+
   /// \brief Helper method to factor out the common pattern of adding overloads
   /// for '++' and '--' builtin operators.
   void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
@@ -5009,8 +5024,7 @@ public:
                               S.Context.*ArithmeticTypes[Right] };
         QualType Result =
           isComparison ? S.Context.BoolTy
-                       : UsualArithmeticConversionsType::find(S.Context, Left,
-                                                              Right);
+                       : getUsualArithmeticConversions(Left, Right);
         S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
       }
     }
@@ -5062,7 +5076,7 @@ public:
                               S.Context.*ArithmeticTypes[Right] };
         QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater)
             ? LandR[0]
-            : UsualArithmeticConversionsType::find(S.Context, Left, Right);
+            : getUsualArithmeticConversions(Left, Right);
         S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
       }
     }
@@ -5473,31 +5487,6 @@ BuiltinOperatorOverloadBuilder::ArithmeticTypes[NumArithmeticTypes] = {
   // FIXME: What about complex?
 };
 
-// Accelerator table for performing the usual arithmetic conversions.
-// The rules are basically:
-//   - if either is floating-point, use the wider floating-point
-//   - if same signedness, use the higher rank
-//   - if same size, use unsigned of the higher rank
-//   - use the larger type
-// These rules, together with the axiom that higher ranks are
-// never smaller, are sufficient to precompute all of these results
-// *except* when dealing with signed types of higher rank.
-// (we could precompute SLL x UI for all known platforms, but it's
-// better not to make any assumptions).
-BuiltinOperatorOverloadBuilder::PromT
-BuiltinOperatorOverloadBuilder::UsualArithmeticConversionsTypes
-[LastPromotedArithmeticType][LastPromotedArithmeticType] = {
-  /* Flt*/ {  Flt,  Dbl, LDbl,  Flt,  Flt,  Flt,  Flt,  Flt,  Flt },
-  /* Dbl*/ {  Dbl,  Dbl, LDbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl },
-  /*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl },
-  /*  SI*/ {  Flt,  Dbl, LDbl,   SI,   SL,  SLL,   UI,   UL,  ULL },
-  /*  SL*/ {  Flt,  Dbl, LDbl,   SL,   SL,  SLL,  Dep,   UL,  ULL },
-  /* SLL*/ {  Flt,  Dbl, LDbl,  SLL,  SLL,  SLL,  Dep,  Dep,  ULL },
-  /*  UI*/ {  Flt,  Dbl, LDbl,   UI,  Dep,  Dep,   UI,   UL,  ULL },
-  /*  UL*/ {  Flt,  Dbl, LDbl,   UL,   UL,  Dep,   UL,   UL,  ULL },
-  /* ULL*/ {  Flt,  Dbl, LDbl,  ULL,  ULL,  ULL,  ULL,  ULL,  ULL }
-};
-
 } // end anonymous namespace
 
 /// AddBuiltinOperatorCandidates - Add the appropriate built-in