[cfe-commits] r79412 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaType.cpp test/Sema/promote-int-16bit.c

Eli Friedman eli.friedman at gmail.com
Wed Aug 19 00:44:53 PDT 2009


Author: efriedma
Date: Wed Aug 19 02:44:53 2009
New Revision: 79412

URL: http://llvm.org/viewvc/llvm-project?rev=79412&view=rev
Log:
Make integer promotions work correctly on PIC16 and other platforms 
where sizeof(short) == sizeof(int).  Move UsualArithmeticConversionsType 
out of Sema, since it was only there as a historical artifact.  Patch by 
Enea Zaffanella.


Added:
    cfe/trunk/test/Sema/promote-int-16bit.c
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=79412&r1=79411&r2=79412&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed Aug 19 02:44:53 2009
@@ -813,6 +813,11 @@
   /// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
   QualType getArrayDecayedType(QualType T);
   
+  /// getPromotedIntegerType - Returns the type that Promotable will
+  /// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable
+  /// integer type.
+  QualType getPromotedIntegerType(QualType PromotableType);
+
   /// getIntegerTypeOrder - Returns the highest ranked integer type: 
   /// C99 6.3.1.8p1.  If LHS > RHS, return 1.  If LHS == RHS, return 0. If
   /// LHS < RHS, return -1. 
@@ -869,6 +874,11 @@
   QualType mergeTypes(QualType, QualType);
   QualType mergeFunctionTypes(QualType, QualType);
 
+  /// UsualArithmeticConversionsType - handles the various conversions
+  /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
+  /// and returns the result type of that conversion.
+  QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
+
   //===--------------------------------------------------------------------===//
   //                    Integer Predicates
   //===--------------------------------------------------------------------===//

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=79412&r1=79411&r2=79412&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Aug 19 02:44:53 2009
@@ -2487,6 +2487,20 @@
   }
 }
 
+/// getPromotedIntegerType - Returns the type that Promotable will
+/// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable
+/// integer type.
+QualType ASTContext::getPromotedIntegerType(QualType Promotable) {
+  assert(!Promotable.isNull());
+  assert(Promotable->isPromotableIntegerType());
+  if (Promotable->isSignedIntegerType())
+    return IntTy;
+  uint64_t PromotableSize = getTypeSize(Promotable);
+  uint64_t IntSize = getTypeSize(IntTy);
+  assert(Promotable->isUnsignedIntegerType() && PromotableSize <= IntSize);
+  return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy;
+}
+
 /// getIntegerTypeOrder - Returns the highest ranked integer type: 
 /// C99 6.3.1.8p1.  If LHS > RHS, return 1.  If LHS == RHS, return 0. If
 /// LHS < RHS, return -1. 
@@ -4157,3 +4171,143 @@
   return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(),
                          TypeStr[0] == '.', 0);
 }
+
+QualType
+ASTContext::UsualArithmeticConversionsType(QualType lhs, QualType rhs) {
+  // Perform the usual unary conversions. We do this early so that
+  // integral promotions to "int" can allow us to exit early, in the
+  // lhs == rhs check. Also, for conversion purposes, we ignore any
+  // qualifiers.  For example, "const float" and "float" are
+  // equivalent.
+  if (lhs->isPromotableIntegerType())
+    lhs = getPromotedIntegerType(lhs);
+  else
+    lhs = lhs.getUnqualifiedType();
+  if (rhs->isPromotableIntegerType())
+    rhs = getPromotedIntegerType(rhs);
+  else
+    rhs = rhs.getUnqualifiedType();
+
+  // If both types are identical, no conversion is needed.
+  if (lhs == rhs)
+    return lhs;
+  
+  // If either side is a non-arithmetic type (e.g. a pointer), we are done.
+  // The caller can deal with this (e.g. pointer + int).
+  if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
+    return lhs;
+    
+  // At this point, we have two different arithmetic types. 
+  
+  // Handle complex types first (C99 6.3.1.8p1).
+  if (lhs->isComplexType() || rhs->isComplexType()) {
+    // if we have an integer operand, the result is the complex type.
+    if (rhs->isIntegerType() || rhs->isComplexIntegerType()) { 
+      // convert the rhs to the lhs complex type.
+      return lhs;
+    }
+    if (lhs->isIntegerType() || lhs->isComplexIntegerType()) { 
+      // convert the lhs to the rhs complex type.
+      return rhs;
+    }
+    // This handles complex/complex, complex/float, or float/complex.
+    // When both operands are complex, the shorter operand is converted to the 
+    // type of the longer, and that is the type of the result. This corresponds 
+    // to what is done when combining two real floating-point operands. 
+    // The fun begins when size promotion occur across type domains. 
+    // From H&S 6.3.4: When one operand is complex and the other is a real
+    // floating-point type, the less precise type is converted, within it's 
+    // real or complex domain, to the precision of the other type. For example,
+    // when combining a "long double" with a "double _Complex", the 
+    // "double _Complex" is promoted to "long double _Complex".
+    int result = getFloatingTypeOrder(lhs, rhs);
+    
+    if (result > 0) { // The left side is bigger, convert rhs. 
+      rhs = getFloatingTypeOfSizeWithinDomain(lhs, rhs);
+    } else if (result < 0) { // The right side is bigger, convert lhs. 
+      lhs = getFloatingTypeOfSizeWithinDomain(rhs, lhs);
+    } 
+    // At this point, lhs and rhs have the same rank/size. Now, make sure the
+    // domains match. This is a requirement for our implementation, C99
+    // does not require this promotion.
+    if (lhs != rhs) { // Domains don't match, we have complex/float mix.
+      if (lhs->isRealFloatingType()) { // handle "double, _Complex double".
+        return rhs;
+      } else { // handle "_Complex double, double".
+        return lhs;
+      }
+    }
+    return lhs; // The domain/size match exactly.
+  }
+  // Now handle "real" floating types (i.e. float, double, long double).
+  if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
+    // if we have an integer operand, the result is the real floating type.
+    if (rhs->isIntegerType()) {
+      // convert rhs to the lhs floating point type.
+      return lhs;
+    }
+    if (rhs->isComplexIntegerType()) {
+      // convert rhs to the complex floating point type.
+      return getComplexType(lhs);
+    }
+    if (lhs->isIntegerType()) {
+      // convert lhs to the rhs floating point type.
+      return rhs;
+    }
+    if (lhs->isComplexIntegerType()) { 
+      // convert lhs to the complex floating point type.
+      return getComplexType(rhs);
+    }
+    // We have two real floating types, float/complex combos were handled above.
+    // Convert the smaller operand to the bigger result.
+    int result = getFloatingTypeOrder(lhs, rhs);
+    if (result > 0) // convert the rhs
+      return lhs;
+    assert(result < 0 && "illegal float comparison");
+    return rhs;   // convert the lhs
+  }
+  if (lhs->isComplexIntegerType() || rhs->isComplexIntegerType()) {
+    // Handle GCC complex int extension.
+    const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
+    const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();
+
+    if (lhsComplexInt && rhsComplexInt) {
+      if (getIntegerTypeOrder(lhsComplexInt->getElementType(), 
+                              rhsComplexInt->getElementType()) >= 0)
+        return lhs; // convert the rhs
+      return rhs;
+    } else if (lhsComplexInt && rhs->isIntegerType()) {
+      // convert the rhs to the lhs complex type.
+      return lhs;
+    } else if (rhsComplexInt && lhs->isIntegerType()) {
+      // convert the lhs to the rhs complex type.
+      return rhs;
+    }
+  }
+  // Finally, we have two differing integer types.
+  // The rules for this case are in C99 6.3.1.8
+  int compare = getIntegerTypeOrder(lhs, rhs);
+  bool lhsSigned = lhs->isSignedIntegerType(),
+       rhsSigned = rhs->isSignedIntegerType();
+  QualType destType;
+  if (lhsSigned == rhsSigned) {
+    // Same signedness; use the higher-ranked type
+    destType = compare >= 0 ? lhs : rhs;
+  } else if (compare != (lhsSigned ? 1 : -1)) {
+    // The unsigned type has greater than or equal rank to the
+    // signed type, so use the unsigned type
+    destType = lhsSigned ? rhs : lhs;
+  } else if (getIntWidth(lhs) != getIntWidth(rhs)) {
+    // The two types are different widths; if we are here, that
+    // means the signed type is larger than the unsigned type, so
+    // use the signed type.
+    destType = lhsSigned ? lhs : rhs;
+  } else {
+    // The signed type is higher-ranked than the unsigned type,
+    // but isn't actually any bigger (like unsigned int and long
+    // on most 32-bit systems).  Use the unsigned type corresponding
+    // to the signed type.
+    destType = getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
+  }
+  return destType;
+}

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=79412&r1=79411&r2=79412&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Aug 19 02:44:53 2009
@@ -3115,12 +3115,6 @@
   QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr,
                                       bool isCompAssign = false);
   
-  /// UsualArithmeticConversionsType - handles the various conversions
-  /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
-  /// and returns the result type of that conversion.
-  QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
-                                          
-
   /// AssignConvertType - All of the 'assignment' semantic checks return this
   /// enum to indicate whether the assignment was allowed.  These checks are
   /// done for simple assignments, as well as initialization, return from

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Aug 19 02:44:53 2009
@@ -273,7 +273,8 @@
   //   unsigned int. These are called the integer promotions. All
   //   other types are unchanged by the integer promotions.
   if (Ty->isPromotableIntegerType()) {
-    ImpCastExprToType(Expr, Context.IntTy);
+    QualType PT = Context.getPromotedIntegerType(Ty);
+    ImpCastExprToType(Expr, PT);
     return Expr;
   } else {
     QualType T = isPromotableBitField(Expr, Context);
@@ -361,152 +362,13 @@
   if (!RHSBitfieldPromoteTy.isNull())
     rhs = RHSBitfieldPromoteTy;
 
-  QualType destType = UsualArithmeticConversionsType(lhs, rhs);
+  QualType destType = Context.UsualArithmeticConversionsType(lhs, rhs);
   if (!isCompAssign)
     ImpCastExprToType(lhsExpr, destType);
   ImpCastExprToType(rhsExpr, destType);
   return destType;
 }
 
-QualType Sema::UsualArithmeticConversionsType(QualType lhs, QualType rhs) {
-  // Perform the usual unary conversions. We do this early so that
-  // integral promotions to "int" can allow us to exit early, in the
-  // lhs == rhs check. Also, for conversion purposes, we ignore any
-  // qualifiers.  For example, "const float" and "float" are
-  // equivalent.
-  if (lhs->isPromotableIntegerType())
-    lhs = Context.IntTy;
-  else
-    lhs = lhs.getUnqualifiedType();
-  if (rhs->isPromotableIntegerType())
-    rhs = Context.IntTy;
-  else
-    rhs = rhs.getUnqualifiedType();
-
-  // If both types are identical, no conversion is needed.
-  if (lhs == rhs)
-    return lhs;
-  
-  // If either side is a non-arithmetic type (e.g. a pointer), we are done.
-  // The caller can deal with this (e.g. pointer + int).
-  if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
-    return lhs;
-    
-  // At this point, we have two different arithmetic types. 
-  
-  // Handle complex types first (C99 6.3.1.8p1).
-  if (lhs->isComplexType() || rhs->isComplexType()) {
-    // if we have an integer operand, the result is the complex type.
-    if (rhs->isIntegerType() || rhs->isComplexIntegerType()) { 
-      // convert the rhs to the lhs complex type.
-      return lhs;
-    }
-    if (lhs->isIntegerType() || lhs->isComplexIntegerType()) { 
-      // convert the lhs to the rhs complex type.
-      return rhs;
-    }
-    // This handles complex/complex, complex/float, or float/complex.
-    // When both operands are complex, the shorter operand is converted to the 
-    // type of the longer, and that is the type of the result. This corresponds 
-    // to what is done when combining two real floating-point operands. 
-    // The fun begins when size promotion occur across type domains. 
-    // From H&S 6.3.4: When one operand is complex and the other is a real
-    // floating-point type, the less precise type is converted, within it's 
-    // real or complex domain, to the precision of the other type. For example,
-    // when combining a "long double" with a "double _Complex", the 
-    // "double _Complex" is promoted to "long double _Complex".
-    int result = Context.getFloatingTypeOrder(lhs, rhs);
-    
-    if (result > 0) { // The left side is bigger, convert rhs. 
-      rhs = Context.getFloatingTypeOfSizeWithinDomain(lhs, rhs);
-    } else if (result < 0) { // The right side is bigger, convert lhs. 
-      lhs = Context.getFloatingTypeOfSizeWithinDomain(rhs, lhs);
-    } 
-    // At this point, lhs and rhs have the same rank/size. Now, make sure the
-    // domains match. This is a requirement for our implementation, C99
-    // does not require this promotion.
-    if (lhs != rhs) { // Domains don't match, we have complex/float mix.
-      if (lhs->isRealFloatingType()) { // handle "double, _Complex double".
-        return rhs;
-      } else { // handle "_Complex double, double".
-        return lhs;
-      }
-    }
-    return lhs; // The domain/size match exactly.
-  }
-  // Now handle "real" floating types (i.e. float, double, long double).
-  if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
-    // if we have an integer operand, the result is the real floating type.
-    if (rhs->isIntegerType()) {
-      // convert rhs to the lhs floating point type.
-      return lhs;
-    }
-    if (rhs->isComplexIntegerType()) {
-      // convert rhs to the complex floating point type.
-      return Context.getComplexType(lhs);
-    }
-    if (lhs->isIntegerType()) {
-      // convert lhs to the rhs floating point type.
-      return rhs;
-    }
-    if (lhs->isComplexIntegerType()) { 
-      // convert lhs to the complex floating point type.
-      return Context.getComplexType(rhs);
-    }
-    // We have two real floating types, float/complex combos were handled above.
-    // Convert the smaller operand to the bigger result.
-    int result = Context.getFloatingTypeOrder(lhs, rhs);
-    if (result > 0) // convert the rhs
-      return lhs;
-    assert(result < 0 && "illegal float comparison");
-    return rhs;   // convert the lhs
-  }
-  if (lhs->isComplexIntegerType() || rhs->isComplexIntegerType()) {
-    // Handle GCC complex int extension.
-    const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
-    const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();
-
-    if (lhsComplexInt && rhsComplexInt) {
-      if (Context.getIntegerTypeOrder(lhsComplexInt->getElementType(), 
-                                      rhsComplexInt->getElementType()) >= 0)
-        return lhs; // convert the rhs
-      return rhs;
-    } else if (lhsComplexInt && rhs->isIntegerType()) {
-      // convert the rhs to the lhs complex type.
-      return lhs;
-    } else if (rhsComplexInt && lhs->isIntegerType()) {
-      // convert the lhs to the rhs complex type.
-      return rhs;
-    }
-  }
-  // Finally, we have two differing integer types.
-  // The rules for this case are in C99 6.3.1.8
-  int compare = Context.getIntegerTypeOrder(lhs, rhs);
-  bool lhsSigned = lhs->isSignedIntegerType(),
-       rhsSigned = rhs->isSignedIntegerType();
-  QualType destType;
-  if (lhsSigned == rhsSigned) {
-    // Same signedness; use the higher-ranked type
-    destType = compare >= 0 ? lhs : rhs;
-  } else if (compare != (lhsSigned ? 1 : -1)) {
-    // The unsigned type has greater than or equal rank to the
-    // signed type, so use the unsigned type
-    destType = lhsSigned ? rhs : lhs;
-  } else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) {
-    // The two types are different widths; if we are here, that
-    // means the signed type is larger than the unsigned type, so
-    // use the signed type.
-    destType = lhsSigned ? lhs : rhs;
-  } else {
-    // The signed type is higher-ranked than the unsigned type,
-    // but isn't actually any bigger (like unsigned int and long
-    // on most 32-bit systems).  Use the unsigned type corresponding
-    // to the signed type.
-    destType = Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
-  }
-  return destType;
-}
-
 //===----------------------------------------------------------------------===//
 //  Semantic Analysis for various Expression Types
 //===----------------------------------------------------------------------===//
@@ -4088,7 +3950,7 @@
       if (CompLHSTy) {
         QualType LHSTy = lex->getType();
         if (LHSTy->isPromotableIntegerType())
-          LHSTy = Context.IntTy;
+          LHSTy = Context.getPromotedIntegerType(LHSTy);
         else {
           QualType T = isPromotableBitField(lex, Context);
           if (!T.isNull())
@@ -4256,13 +4118,13 @@
 
   // Shifts don't perform usual arithmetic conversions, they just do integer
   // promotions on each operand. C99 6.5.7p3
-  QualType LHSTy;
-  if (lex->getType()->isPromotableIntegerType())
-    LHSTy = Context.IntTy;
+  QualType LHSTy = lex->getType();
+  if (LHSTy->isPromotableIntegerType())
+    LHSTy = Context.getPromotedIntegerType(LHSTy);
   else {
-    LHSTy = isPromotableBitField(lex, Context);
-    if (LHSTy.isNull())
-      LHSTy = lex->getType();
+    QualType T = isPromotableBitField(lex, Context);
+    if (!T.isNull())
+      LHSTy = T;
   }
   if (!isCompAssign)
     ImpCastExprToType(lex, LHSTy);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Aug 19 02:44:53 2009
@@ -3101,9 +3101,10 @@
       for (unsigned Right = FirstPromotedArithmeticType; 
            Right < LastPromotedArithmeticType; ++Right) {
         QualType LandR[2] = { ArithmeticTypes[Left], ArithmeticTypes[Right] };
-        QualType Result 
-          = isComparison? Context.BoolTy 
-                        : UsualArithmeticConversionsType(LandR[0], LandR[1]);
+        QualType Result
+          = isComparison
+          ? Context.BoolTy
+          : Context.UsualArithmeticConversionsType(LandR[0], LandR[1]);
         AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
       }
     }
@@ -3136,7 +3137,7 @@
         QualType LandR[2] = { ArithmeticTypes[Left], ArithmeticTypes[Right] };
         QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater)
             ? LandR[0]
-            : UsualArithmeticConversionsType(LandR[0], LandR[1]);
+            : Context.UsualArithmeticConversionsType(LandR[0], LandR[1]);
         AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
       }
     }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Aug 19 02:44:53 2009
@@ -1127,7 +1127,7 @@
             }
           } else if (!FTI.hasPrototype) {
             if (ArgTy->isPromotableIntegerType()) {
-              ArgTy = Context.IntTy;
+              ArgTy = Context.getPromotedIntegerType(ArgTy);
             } else if (const BuiltinType* BTy = ArgTy->getAsBuiltinType()) {
               if (BTy->getKind() == BuiltinType::Float)
                 ArgTy = Context.DoubleTy;

Added: cfe/trunk/test/Sema/promote-int-16bit.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/promote-int-16bit.c?rev=79412&view=auto

==============================================================================
--- cfe/trunk/test/Sema/promote-int-16bit.c (added)
+++ cfe/trunk/test/Sema/promote-int-16bit.c Wed Aug 19 02:44:53 2009
@@ -0,0 +1,6 @@
+// RUN: clang-cc -fsyntax-only -verify %s -triple pic16-unknown-unknown
+
+// Check that unsigned short promotes to unsigned int on targets where
+// sizeof(unsigned short) == sizeof(unsigned int)
+__typeof(1+(unsigned short)1) x;
+unsigned x;





More information about the cfe-commits mailing list