From: Steve Naroff Date: Tue, 15 Jan 2008 01:41:59 +0000 (+0000) Subject: Rework commit r45976, which was incorrect. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4cdec1c3ca80124024a787ce32833fd5b20cbb15;p=clang Rework commit r45976, which was incorrect. - 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 --- diff --git a/AST/Type.cpp b/AST/Type.cpp index 949b6f8d2a..bb3fd9d44b 100644 --- a/AST/Type.cpp +++ b/AST/Type.cpp @@ -77,6 +77,29 @@ bool Type::isComplexType() const { return isa(CanonicalType); } +bool Type::isComplexIntegerType() const { + // Check for GCC complex integer extension. + if (const ComplexType *CT = dyn_cast(CanonicalType)) + return CT->getElementType()->isIntegerType(); + return false; +} + +const ComplexType *Type::getAsComplexIntegerType() const { + // Are we directly a complex type? + if (const ComplexType *CTy = dyn_cast(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(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(CanonicalType)) if (TT->getDecl()->getKind() == Decl::Enum) return true; - // Check for GCC complex integer extension. - if (const ComplexType *CT = dyn_cast(CanonicalType)) - return CT->getElementType()->isIntegerType(); if (const VectorType *VT = dyn_cast(CanonicalType)) return VT->getElementType()->isIntegerType(); return false; diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 9f5e8e68b8..436510f763 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -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; } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 24440f76aa..13a000a87c 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -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 diff --git a/test/Sema/complex-int.c b/test/Sema/complex-int.c index b2555f5937..90d1e3dc12 100644 --- a/test/Sema/complex-int.c +++ b/test/Sema/complex-int.c @@ -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}} +} }