]> granicus.if.org Git - clang/commitdiff
Rework commit r45976, which was incorrect.
authorSteve Naroff <snaroff@apple.com>
Tue, 15 Jan 2008 01:41:59 +0000 (01:41 +0000)
committerSteve Naroff <snaroff@apple.com>
Tue, 15 Jan 2008 01:41:59 +0000 (01:41 +0000)
- Add Type::isComplexIntegerType(), Type::getAsComplexIntegerType().
- Don't inlude complex types with Type::isIntegerType(), which is too general.
- Use the new predicates in Sema::UsualArithmeticConversions() to recognize/convert the types.

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

AST/Type.cpp
Sema/SemaExpr.cpp
include/clang/AST/Type.h
test/Sema/complex-int.c

index 949b6f8d2a33310d2957ae4cb4f7b4ec4c3ae27d..bb3fd9d44b5a59877eab325ae9392ce1c9945c67 100644 (file)
@@ -77,6 +77,29 @@ bool Type::isComplexType() const {
   return isa<ComplexType>(CanonicalType);
 }
 
+bool Type::isComplexIntegerType() const {
+  // Check for GCC complex integer extension.
+  if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
+    return CT->getElementType()->isIntegerType();
+  return false;
+}
+
+const ComplexType *Type::getAsComplexIntegerType() const {
+  // Are we directly a complex type?
+  if (const ComplexType *CTy = dyn_cast<ComplexType>(this)) {
+    if (CTy->getElementType()->isIntegerType())
+      return CTy;
+  }
+  // If the canonical form of this type isn't the right kind, reject it.
+  const ComplexType *CTy = dyn_cast<ComplexType>(CanonicalType);
+  if (!CTy || !CTy->getElementType()->isIntegerType())
+    return 0;
+
+  // If this is a typedef for a complex type, strip the typedef off without
+  // losing all typedef information.
+  return getDesugaredType()->getAsComplexIntegerType();
+}
+
 /// getDesugaredType - Return the specified type with any "sugar" removed from
 /// type type.  This takes off typedefs, typeof's etc.  If the outer level of
 /// the type is already concrete, it returns it unmodified.  This is similar
@@ -310,9 +333,6 @@ bool Type::isIntegerType() const {
   if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
     if (TT->getDecl()->getKind() == Decl::Enum)
       return true;
-  // Check for GCC complex integer extension.
-  if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
-    return CT->getElementType()->isIntegerType();
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isIntegerType();
   return false;
index 9f5e8e68b89266d5552ec0aaff1d7ad60f4d2b3f..436510f763c06ad6938aac21b8abc6842d17d625 100644 (file)
@@ -951,12 +951,25 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
   
   // 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()) { // convert the rhs to the lhs complex type.
+    // Handle GCC complex int extension first.
+    // FIXME: need to verify these conversion rules are consistent with GCC.
+    const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
+    const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();
+    
+    if (lhsComplexInt && rhsComplexInt) {
+      if (Context.maxIntegerType(lhsComplexInt->getElementType(), 
+                                 rhsComplexInt->getElementType()) == lhs) { 
+        if (!isCompAssign) promoteExprToType(rhsExpr, lhs); // convert the rhs
+        return lhs;
+      }
+      if (!isCompAssign) promoteExprToType(lhsExpr, rhs); // convert the lhs
+      return rhs;
+    } else if (lhsComplexInt && rhs->isIntegerType()) {
+      // convert the rhs to the lhs complex type.
       if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
       return lhs;
-    }
-    if (lhs->isIntegerType()) { // convert the lhs to the rhs complex type.
+    } else if (rhsComplexInt && lhs->isIntegerType()) {
+      // convert the lhs to the rhs complex type.
       if (!isCompAssign) promoteExprToType(lhsExpr, rhs);
       return rhs;
     }
index 24440f76aaa2626d1c0013a01e1e1520f47a27a6..13a000a87cd627ae7ced785bc2440f61d72e951b 100644 (file)
@@ -291,7 +291,8 @@ public:
   bool isArrayType() const;
   bool isRecordType() const;
   bool isStructureType() const;   
-  bool isUnionType() const;  
+  bool isUnionType() const;
+  bool isComplexIntegerType() const; // GCC complex int type.
   bool isVectorType() const; // GCC vector type.
   bool isOCUVectorType() const; // OCU vector type.
   bool isObjCInterfaceType() const; // includes conforming protocol type
@@ -313,6 +314,7 @@ public:
   const RecordType *getAsUnionType() const;
   const VectorType *getAsVectorType() const; // GCC vector type.
   const ComplexType *getAsComplexType() const;
+  const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
   const OCUVectorType *getAsOCUVectorType() const; // OCU vector type.
   
   /// getDesugaredType - Return the specified type with any "sugar" removed from
index b2555f5937181adf6024c63b02b510a939ba8218..90d1e3dc121539724311d3dfeb492bceffd8e8fb 100644 (file)
@@ -5,10 +5,18 @@ __complex__ int arr;
 __complex__ short brr;
 __complex__ unsigned xx;
 __complex__ signed yy;
-
 __complex__ int result;
+int ii;
+
+result = arr*ii;
+result = ii*brr;
 
 result = arr*brr;
 result = xx*yy;
+
+switch (arr) { // expected-error{{statement requires expression of integer type ('_Complex int' invalid)}}
+  case brr: ; // expected-error{{case label does not reduce to an integer constant}}
+  case xx: ; // expected-error{{case label does not reduce to an integer constant}}
+}
 }