diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-09-19 23:17:44 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-09-19 23:17:44 +0000 |
commit | 0c706c29f20b6fa36759fa41333b9c3ec0bd2969 (patch) | |
tree | cff749b4d8a9d6e5b4fbae39c4f4e710307366c0 /lib | |
parent | 40ccaccd21a4377cd76d6adda2b192dcf9514ef6 (diff) |
Add list initialization for complex numbers in C. Essentially, this allows "_Complex float x = {1.0f, 2.0f};". See changes to docs/LanguageExtensions.html for a longer description.
<rdar://problem/9397672>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140090 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/CGExprComplex.cpp | 9 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 72 |
3 files changed, 91 insertions, 6 deletions
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index 5a752a1830..a92a7ad33e 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -738,10 +738,17 @@ ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) { Ignore = TestAndClearIgnoreImag(); (void)Ignore; assert (Ignore == false && "init list ignored"); - if (E->getNumInits()) + + if (E->getNumInits() == 2) { + llvm::Value *Real = CGF.EmitScalarExpr(E->getInit(0)); + llvm::Value *Imag = CGF.EmitScalarExpr(E->getInit(1)); + return ComplexPairTy(Real, Imag); + } else if (E->getNumInits() == 1) { return Visit(E->getInit(0)); + } // Empty init list intializes to null + assert(E->getNumInits() == 0 && "Unexpected number of inits"); QualType Ty = E->getType()->getAs<ComplexType>()->getElementType(); llvm::Type* LTy = CGF.ConvertType(Ty); llvm::Value* zeroConstant = llvm::Constant::getNullValue(LTy); diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index c0b7045a52..d7dfa253ad 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -742,6 +742,22 @@ public: } llvm::Constant *VisitInitListExpr(InitListExpr *ILE) { + if (ILE->getType()->isAnyComplexType() && ILE->getNumInits() == 2) { + // Complex type with element initializers + Expr *Real = ILE->getInit(0); + Expr *Imag = ILE->getInit(1); + llvm::Constant *Complex[2]; + Complex[0] = CGM.EmitConstantExpr(Real, Real->getType(), CGF); + if (!Complex[0]) + return 0; + Complex[1] = CGM.EmitConstantExpr(Imag, Imag->getType(), CGF); + if (!Complex[1]) + return 0; + llvm::StructType *STy = + cast<llvm::StructType>(ConvertType(ILE->getType())); + return llvm::ConstantStruct::get(STy, Complex); + } + if (ILE->getType()->isScalarType()) { // We have a scalar in braces. Just use the first element. if (ILE->getNumInits() > 0) { diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 5fa8486a7f..43477b266d 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -195,6 +195,11 @@ class InitListChecker { unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); + void CheckComplexType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); void CheckScalarType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, @@ -610,7 +615,7 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, } } - if (T->isScalarType() && !TopLevelObject) + if (T->isScalarType() && IList->getNumInits() == 1 && !TopLevelObject) SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init) << IList->getSourceRange() << FixItHint::CreateRemoval(IList->getLocStart()) @@ -625,7 +630,12 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject) { - if (DeclType->isScalarType()) { + if (DeclType->isAnyComplexType() && SubobjectIsDesignatorContext) { + // Explicitly braced initializer for complex type can be real+imaginary + // parts. + CheckComplexType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); + } else if (DeclType->isScalarType()) { CheckScalarType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isVectorType()) { @@ -797,6 +807,43 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, } } +void InitListChecker::CheckComplexType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + assert(Index == 0 && "Index in explicit init list must be zero"); + + // As an extension, clang supports complex initializers, which initialize + // a complex number component-wise. When an explicit initializer list for + // a complex number contains two two initializers, this extension kicks in: + // it exepcts the initializer list to contain two elements convertible to + // the element type of the complex type. The first element initializes + // the real part, and the second element intitializes the imaginary part. + + if (IList->getNumInits() != 2) + return CheckScalarType(Entity, IList, DeclType, Index, StructuredList, + StructuredIndex); + + // This is an extension in C. (The builtin _Complex type does not exist + // in the C++ standard.) + if (!SemaRef.getLangOptions().CPlusPlus) + SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init) + << IList->getSourceRange(); + + // Initialize the complex number. + QualType elementType = DeclType->getAs<ComplexType>()->getElementType(); + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + + for (unsigned i = 0; i < 2; ++i) { + ElementEntity.setElementIndex(Index); + CheckSubElementType(ElementEntity, IList, elementType, Index, + StructuredList, StructuredIndex); + } +} + + void InitListChecker::CheckScalarType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, @@ -2060,9 +2107,14 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) { Kind = EK_ArrayElement; Type = AT->getElementType(); - } else { + } else if (const VectorType *VT = Parent.getType()->getAs<VectorType>()) { Kind = EK_VectorElement; - Type = Parent.getType()->getAs<VectorType>()->getElementType(); + Type = VT->getElementType(); + } else { + const ComplexType *CT = Parent.getType()->getAs<ComplexType>(); + assert(CT && "Unexpected type"); + Kind = EK_ComplexElement; + Type = CT->getElementType(); } } @@ -2099,6 +2151,7 @@ DeclarationName InitializedEntity::getName() const { case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: + case EK_ComplexElement: case EK_BlockElement: return DeclarationName(); } @@ -2124,6 +2177,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const { case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: + case EK_ComplexElement: case EK_BlockElement: return 0; } @@ -2147,6 +2201,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: + case EK_ComplexElement: case EK_BlockElement: break; } @@ -2599,7 +2654,10 @@ static void TryListInitialization(Sema &S, // is equivalent to // // T x = a; - if (DestType->isScalarType()) { + if (DestType->isAnyComplexType()) { + // We allow more than 1 init for complex types in some cases, even though + // they are scalar. + } else if (DestType->isScalarType()) { if (InitList->getNumInits() > 1 && S.getLangOptions().CPlusPlus) { Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar); return; @@ -3812,6 +3870,7 @@ getAssignmentAction(const InitializedEntity &Entity) { case InitializedEntity::EK_Member: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: return Sema::AA_Initializing; } @@ -3831,6 +3890,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_BlockElement: return false; @@ -3853,6 +3913,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: return false; @@ -3938,6 +3999,7 @@ static ExprResult CopyObject(Sema &S, case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: Loc = CurInitExpr->getLocStart(); break; |