diff options
author | arphaman <arphaman@gmail.com> | 2013-09-19 13:52:26 +0100 |
---|---|---|
committer | arphaman <arphaman@gmail.com> | 2013-09-19 13:52:26 +0100 |
commit | 2d9553a89153be4ed76408c439e749b88a16b8d2 (patch) | |
tree | ce9b825434c5a469137795999c78278efe999bcd | |
parent | 77938070560e981eb408990f2380f2e2370488bd (diff) | |
download | flang-2d9553a89153be4ed76408c439e749b88a16b8d2.tar.gz |
added character type; removed char builtin type and length spec in extquals
-rw-r--r-- | include/flang/AST/ASTContext.h | 9 | ||||
-rw-r--r-- | include/flang/AST/Type.h | 63 | ||||
-rw-r--r-- | include/flang/AST/TypeNodes.def | 3 | ||||
-rw-r--r-- | include/flang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 45 | ||||
-rw-r--r-- | lib/AST/ASTDumper.cpp | 21 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 7 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCharacter.cpp | 20 | ||||
-rw-r--r-- | lib/CodeGen/CGIOLibflang.cpp | 14 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 32 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTypes.h | 5 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 56 | ||||
-rw-r--r-- | lib/Sema/SemaDataStmt.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 19 |
17 files changed, 170 insertions, 158 deletions
diff --git a/include/flang/AST/ASTContext.h b/include/flang/AST/ASTContext.h index ebd17605c1..0708c96b7a 100644 --- a/include/flang/AST/ASTContext.h +++ b/include/flang/AST/ASTContext.h @@ -43,6 +43,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { mutable std::vector<Type*> Types; mutable llvm::FoldingSet<ExtQuals> ExtQualNodes; + mutable llvm::FoldingSet<CharacterType> CharTypes; mutable llvm::FoldingSet<PointerType> PointerTypes; mutable llvm::FoldingSet<ArrayType> ArrayTypes; mutable llvm::FoldingSet<RecordType> RecordTypes; @@ -68,9 +69,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { public: /// getExtQualType - Return a type with extended qualifiers. QualType getExtQualType(const Type *Base, Qualifiers Quals, - unsigned KindSel = BuiltinType::NoKind, bool IsDoublePrecisionKind = false, - bool IsStarLength = false, - unsigned LenSel = 0) const; + unsigned KindSel = BuiltinType::NoKind, bool IsDoublePrecisionKind = false) const; QualType getQualTypeOtherKind(QualType Type, QualType KindType); QualType getComplexTypeElementType(QualType Type); QualType getComplexType(QualType ElementType); @@ -190,10 +189,14 @@ public: QualType LogicalTy; QualType ComplexTy; QualType DoubleComplexTy; + QualType NoLengthCharacterTy; /// getBuiltinQualType - Return the QualType for the specified builtin type. QualType getBuiltinQualType(BuiltinType::TypeSpec TS) const; + /// getCharacterType - Return the QualType for the specified character type. + CharacterType *getCharacterType(uint64_t Length) const; + /// getPointerType - Return the uniqued reference to the type for a pointer to /// the specified type. PointerType *getPointerType(const Type *Ty, unsigned NumDims); diff --git a/include/flang/AST/Type.h b/include/flang/AST/Type.h index 4bbb4ded5d..9f93e512a2 100644 --- a/include/flang/AST/Type.h +++ b/include/flang/AST/Type.h @@ -33,9 +33,11 @@ namespace flang { TypeAlignmentInBits = 4, TypeAlignment = 1 << TypeAlignmentInBits }; + class Type; class ExtQuals; class QualType; + class CharacterType; class FunctionType; class RecordType; } @@ -525,6 +527,7 @@ public: bool isIntegerType() const; bool isRealType() const; bool isCharacterType() const; + const CharacterType *asCharacterType() const; bool isComplexType() const; bool isLogicalType() const; @@ -612,6 +615,34 @@ public: static bool classof(const BuiltinType *) { return true; } }; +/// CharacterType - Character types. +class CharacterType : public Type, public llvm::FoldingSetNode { + uint64_t Length; + + friend class ASTContext; + CharacterType(uint64_t Len) + : Type(Character, QualType()), Length(Len) {} +public: + + bool hasLength() const { + return Length != 0; + } + uint64_t getLength() const { + return Length; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Length); + } + static void Profile(llvm::FoldingSetNodeID &ID, + uint64_t Length) { + ID.AddInteger(Length); + } + + static bool classof(const Type *T) { return T->getTypeClass() == Character; } + static bool classof(const CharacterType *) { return true; } +}; + /// PointerType - Allocatable types. class PointerType : public Type, public llvm::FoldingSetNode { const Type *BaseType; //< The type of the object pointed to. @@ -780,24 +811,14 @@ class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode { /// DOUBLE PRECISION/DOUBLE COMPLEX statement. unsigned IsDoublePrecisionKind : 1; - /// LEN = * - unsigned IsStarLengthSelector : 1; - - /// LengthSelector - the length of a character variable - /// The value of 0 means that the length selector wasn't - /// specified. - unsigned LenSelector; - ExtQuals *this_() { return this; } public: ExtQuals(const Type *BaseTy, QualType Canon, Qualifiers Quals, - unsigned KS = BuiltinType::NoKind, bool DBL = false, - bool StarLS = false, unsigned LS = 0) + unsigned KS = BuiltinType::NoKind, bool DBL = false) : ExtQualsTypeCommonBase(BaseTy, Canon.isNull() ? QualType(this_(), 0) : Canon), - Quals(Quals), KindSelector(KS), IsDoublePrecisionKind(DBL?1:0), - IsStarLengthSelector(StarLS?1:0), LenSelector(LS) + Quals(Quals), KindSelector(KS), IsDoublePrecisionKind(DBL?1:0) {} Qualifiers getQualifiers() const { return Quals; } @@ -819,22 +840,15 @@ public: } bool isDoublePrecisionKind() const { return IsDoublePrecisionKind != 0; } - bool hasLengthSelector() const { return LenSelector != 0 || IsStarLengthSelector != 0; } - bool isStarLengthSelector() const { return IsStarLengthSelector != 0; } - unsigned getLengthSelector() const { return LenSelector; } - void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, getBaseType(), Quals, KindSelector, IsDoublePrecisionKind != 0, - IsStarLengthSelector != 0, LenSelector); + Profile(ID, getBaseType(), Quals, KindSelector, IsDoublePrecisionKind != 0); } static void Profile(llvm::FoldingSetNodeID &ID, const Type *BaseType, Qualifiers Quals, - unsigned KS, bool IsDBL, bool StarLS, unsigned LS) { + unsigned KS, bool IsDBL) { ID.AddPointer(BaseType); ID.AddInteger(KS); ID.AddBoolean(IsDBL); - ID.AddBoolean(StarLS); - ID.AddInteger(LS); Quals.Profile(ID); } }; @@ -916,9 +930,10 @@ inline bool Type::isRealType() const { return false; } inline bool Type::isCharacterType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getTypeSpec() == BuiltinType::Character; - return false; + return isa<CharacterType>(CanonicalType); +} +inline const CharacterType *Type::asCharacterType() const { + return dyn_cast<CharacterType>(CanonicalType); } inline bool Type::isLogicalType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) diff --git a/include/flang/AST/TypeNodes.def b/include/flang/AST/TypeNodes.def index 1856db4457..94ee22140b 100644 --- a/include/flang/AST/TypeNodes.def +++ b/include/flang/AST/TypeNodes.def @@ -20,9 +20,8 @@ TYPE(Builtin, Type) BUILTIN_TYPE(Integer) BUILTIN_TYPE(Real) BUILTIN_TYPE(Complex) -BUILTIN_TYPE(Character) BUILTIN_TYPE(Logical) -//TYPE(Character, Type) +TYPE(Character, Type) TYPE(Record, Type) TYPE(Pointer, Type) TYPE(Array, Type) diff --git a/include/flang/Sema/Sema.h b/include/flang/Sema/Sema.h index 0eed11c5c4..be5fd96d37 100644 --- a/include/flang/Sema/Sema.h +++ b/include/flang/Sema/Sema.h @@ -693,7 +693,7 @@ public: /// Returns evaluated length specification /// fot the character type. - unsigned EvalAndCheckCharacterLength(const Expr *E); + uint64_t EvalAndCheckCharacterLength(const Expr *E); /// Returns true if an expression is constant(i.e. evaluatable) bool CheckConstantExpression(const Expr *E); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e99da59a2b..98450defc8 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -43,12 +43,15 @@ void ASTContext::InitBuiltinTypes() { InitBuiltinType(IntegerTy, BuiltinType::Integer); InitBuiltinType(RealTy, BuiltinType::Real); DoublePrecisionTy = getExtQualType(RealTy.getTypePtr(), Qualifiers(), - BuiltinType::Real8, true, false, 0); + BuiltinType::Real8, true); InitBuiltinType(ComplexTy, BuiltinType::Complex); DoubleComplexTy = getExtQualType(ComplexTy.getTypePtr(), Qualifiers(), - BuiltinType::Real8, true, false, 0); - InitBuiltinType(CharacterTy, BuiltinType::Character); + BuiltinType::Real8, true); + InitBuiltinType(LogicalTy, BuiltinType::Logical); + + CharacterTy = QualType(getCharacterType(1), 0); + NoLengthCharacterTy = QualType(getCharacterType(0), 0); } QualType ASTContext::getBuiltinQualType(BuiltinType::TypeSpec TS) const { @@ -56,7 +59,6 @@ QualType ASTContext::getBuiltinQualType(BuiltinType::TypeSpec TS) const { case BuiltinType::Invalid: assert(false && "Invalid type spec!"); break; case BuiltinType::Integer: return IntegerTy; case BuiltinType::Real: return RealTy; - case BuiltinType::Character: return CharacterTy; case BuiltinType::Logical: return LogicalTy; case BuiltinType::Complex: return ComplexTy; } @@ -104,12 +106,10 @@ BuiltinType::TypeKind ASTContext::getSelectedIntKind(int64_t Range) const { //===----------------------------------------------------------------------===// QualType ASTContext::getExtQualType(const Type *BaseType, Qualifiers Quals, - unsigned KindSel, bool IsDoublePrecisionKind, - bool IsStarLength, - unsigned LenSel) const { + unsigned KindSel, bool IsDoublePrecisionKind) const { // Check if we've already instantiated this type. llvm::FoldingSetNodeID ID; - ExtQuals::Profile(ID, BaseType, Quals, KindSel, IsDoublePrecisionKind, IsStarLength, LenSel); + ExtQuals::Profile(ID, BaseType, Quals, KindSel, IsDoublePrecisionKind); void *InsertPos = 0; if (ExtQuals *EQ = ExtQualNodes.FindNodeOrInsertPos(ID, InsertPos)) { assert(EQ->getQualifiers() == Quals); @@ -122,15 +122,14 @@ QualType ASTContext::getExtQualType(const Type *BaseType, Qualifiers Quals, SplitQualType CanonSplit = BaseType->getCanonicalTypeInternal().split(); CanonSplit.second.addConsistentQualifiers(Quals); Canon = getExtQualType(CanonSplit.first, CanonSplit.second, KindSel, - IsDoublePrecisionKind, IsStarLength, LenSel); + IsDoublePrecisionKind); // Re-find the insert position. (void) ExtQualNodes.FindNodeOrInsertPos(ID, InsertPos); } ExtQuals *EQ = new (*this, TypeAlignment) ExtQuals(BaseType, Canon, Quals, - KindSel, IsDoublePrecisionKind, - IsStarLength, LenSel); + KindSel, IsDoublePrecisionKind); ExtQualNodes.InsertNode(EQ, InsertPos); return QualType(EQ, 0); } @@ -143,9 +142,7 @@ QualType ASTContext::getQualTypeOtherKind(QualType Type, QualType KindType) { return getExtQualType(Type.getTypePtr(), ExtQuals? ExtQuals->getQualifiers() : Qualifiers(), DesiredExtQuals->getKindSelector(), - DesiredExtQuals->isDoublePrecisionKind(), - ExtQuals? ExtQuals->isStarLengthSelector() : false, - ExtQuals? ExtQuals->getLengthSelector() : 0); + DesiredExtQuals->isDoublePrecisionKind()); } // NB: this assumes that real and complex have have the same default kind. @@ -169,12 +166,24 @@ QualType ASTContext::getTypeWithQualifers(QualType Type, Qualifiers Quals) { return ExtQuals? getExtQualType(Type.getTypePtr(), Quals, ExtQuals->getKindSelector(), - ExtQuals->isDoublePrecisionKind(), - ExtQuals->isStarLengthSelector(), - ExtQuals->getLengthSelector()) : + ExtQuals->isDoublePrecisionKind()) : getExtQualType(Type.getTypePtr(), Quals); } +CharacterType *ASTContext::getCharacterType(uint64_t Length) const { + llvm::FoldingSetNodeID ID; + CharacterType::Profile(ID, Length); + + void *InsertPos = 0; + if (auto CT = CharTypes.FindNodeOrInsertPos(ID, InsertPos)) + return CT; + + auto CT = new (*this, TypeAlignment) CharacterType(Length); + Types.push_back(CT); + CharTypes.InsertNode(CT, InsertPos); + return CT; +} + /// getPointerType - Return the uniqued reference to the type for a pointer to /// the specified type. PointerType *ASTContext::getPointerType(const Type *Ty, unsigned NumDims) { @@ -187,7 +196,7 @@ PointerType *ASTContext::getPointerType(const Type *Ty, unsigned NumDims) { if (PointerType *PT = PointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return PT; - PointerType *New = new (*this) PointerType(Ty, NumDims); + PointerType *New = new (*this, TypeAlignment) PointerType(Ty, NumDims); Types.push_back(New); PointerTypes.InsertNode(New, InsertPos); return New; diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index df2b9e17a3..546db1fdd1 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -51,6 +51,7 @@ public: // types void dumpType(QualType T); void VisitBuiltinType(const BuiltinType *T, const ExtQuals *E); + void VisitCharacterType(const CharacterType *T, const ExtQuals *E); void VisitArrayType(const ArrayType *T, const ExtQuals *E); void VisitFunctionType(const FunctionType *T, const ExtQuals *E); void VisitRecordType(const RecordType *T, const ExtQuals *E); @@ -291,9 +292,6 @@ void ASTDumper::VisitBuiltinType(const BuiltinType *T, const ExtQuals *E) { case BuiltinType::Real: OS << "real"; break; - case BuiltinType::Character: - OS << "character"; - break; case BuiltinType::Complex: OS << "complex"; break; @@ -306,21 +304,16 @@ void ASTDumper::VisitBuiltinType(const BuiltinType *T, const ExtQuals *E) { if (!E) return; if (!E->isDoublePrecisionKind() && E->hasKindSelector()) { OS << " (Kind=" << BuiltinType::getTypeKindString(E->getKindSelector()); - if (E->hasLengthSelector()) { - if(E->isStarLengthSelector()) OS << ", Len=*"; - else { - OS << ", Len=" << E->getLengthSelector(); - } - } OS << ")"; - } else if (E->hasLengthSelector()) { - if(E->isStarLengthSelector()) OS << "(Len=*)"; - else { - OS << " (Len=" << E->getLengthSelector() << ")"; - } } } +void ASTDumper::VisitCharacterType(const CharacterType *T, const ExtQuals *E) { + OS << "character"; + if(T->hasLength() && T->getLength() > 1) + OS << " (Len=" << T->getLength() << ")"; +} + void ASTDumper::VisitArrayType(const ArrayType *T, const ExtQuals *E) { dumpType(T->getElementType()); OS << " array"; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 56362f1f97..19c79ccd56 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -102,11 +102,8 @@ CharacterConstantExpr *CharacterConstantExpr::Create(ASTContext &C, SourceRange CharacterConstantExpr *CharacterConstantExpr:: CreateCopyWithCompatibleLength(ASTContext &C, QualType T) { - uint64_t Len = 1; - if(auto Ext = T.getExtQualsPtrOrNull()) { - if(Ext->hasLengthSelector()) - Len = Ext->getLengthSelector(); - } + auto CTy = T->asCharacterType(); + uint64_t Len = CTy->hasLength()? CTy->getLength() : 1; StringRef Str(Data); if(Str.size() == Len) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index bad33c5e71..ac34850581 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -287,12 +287,15 @@ bool IntExprEvaluator::VisitIntrinsicCallExpr(const IntrinsicCallExpr *E) { return false; case intrinsic::KIND: { auto T = Args[0]->getType().getSelfOrArrayElementType(); + if(T->isCharacterType()) { + Result.Assign(llvm::APInt(64, 1, true)); + return true; + } if(!T->isBuiltinType()) { Result.Assign(llvm::APInt(64, 4, true)); return true; } - auto Kind = T->isCharacterType()? BuiltinType::Int1 : - Context.getArithmeticOrLogicalTypeKind(T.getExtQualsPtrOrNull(), T); + auto Kind = Context.getArithmeticOrLogicalTypeKind(T.getExtQualsPtrOrNull(), T); Result.Assign(llvm::APInt(64, Context.getTypeKindBitWidth(Kind)/8, true)); return true; } diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 3f1dd6635a..a80fedf681 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -369,10 +369,9 @@ CharacterValueTy CodeGenFunction::GetCharacterArg(const VarDecl *Arg) { } } - auto T = Arg->getType().getExtQualsPtrOrNull(); - if(!(T && T->isStarLengthSelector())) - Val.Len = llvm::ConstantInt::get(CGM.SizeTy, T && T->hasLengthSelector()? - T->getLengthSelector() : 1); + auto CharTy = Arg->getType()->asCharacterType(); + if(CharTy->hasLength()) + Val.Len = llvm::ConstantInt::get(CGM.SizeTy, CharTy->getLength()); CharacterArgs.insert(std::make_pair(Arg, Val)); return Val; } diff --git a/lib/CodeGen/CGExprCharacter.cpp b/lib/CodeGen/CGExprCharacter.cpp index 54e5590df4..d388b1d168 100644 --- a/lib/CodeGen/CGExprCharacter.cpp +++ b/lib/CodeGen/CGExprCharacter.cpp @@ -96,16 +96,12 @@ CharacterValueTy CharacterExprEmitter::VisitBinaryExprConcat(const BinaryExpr *E Dest = takeDestination(); } else { // FIXME temp size overflow checking. - auto ExtLHS = E->getLHS()->getType().getExtQualsPtrOrNull(); - auto ExtRHS = E->getRHS()->getType().getExtQualsPtrOrNull(); - auto Size = (ExtLHS && ExtLHS->hasLengthSelector()? ExtLHS->getLengthSelector() : 1) + - (ExtRHS && ExtRHS->hasLengthSelector()? ExtRHS->getLengthSelector() : 1); - auto TempType = CGF.getContext().getExtQualType(CGF.getContext().CharacterTy.getTypePtr(), - Qualifiers(), - 0, false, false, Size); - Dest = CGF.GetCharacterValueFromPtr( - CGF.CreateTempAlloca(CGF.ConvertTypeForMem(TempType), "characters"), - TempType); + auto CharTyLHS = E->getLHS()->getType()->asCharacterType(); + auto CharTyRHS = E->getRHS()->getType()->asCharacterType(); + auto Size = CharTyLHS->getLength() + CharTyRHS->getLength(); + auto Storage = CGF.CreateTempAlloca(llvm::ArrayType::get(CGF.getModule().Int8Ty, Size), "concat-result"); + Dest = CharacterValueTy(Builder.CreateConstInBoundsGEP2_32(Storage, 0, 0), + llvm::ConstantInt::get(CGF.getModule().SizeTy, Size)); } // a = b // c @@ -184,8 +180,8 @@ void CodeGenFunction::EmitCharacterAssignment(CharacterValueTy LHS, CharacterVal } llvm::Value *CodeGenFunction::GetCharacterTypeLength(QualType T) { - llvm::ConstantInt::get(CGM.SizeTy, - getTypes().GetCharacterTypeLength(T)); + return llvm::ConstantInt::get(CGM.SizeTy, + T->asCharacterType()->getLength()); } CharacterValueTy CodeGenFunction::GetCharacterValueFromPtr(llvm::Value *Ptr, diff --git a/lib/CodeGen/CGIOLibflang.cpp b/lib/CodeGen/CGIOLibflang.cpp index a05e5baf5a..cadcb4df61 100644 --- a/lib/CodeGen/CGIOLibflang.cpp +++ b/lib/CodeGen/CGIOLibflang.cpp @@ -74,6 +74,7 @@ public: void EmitWriteUnformattedBuiltin(const BuiltinType *BTy, const ExtQuals *ExtTy, const Expr *E); + void EmitWriteUnformattedChar(const Expr *E); }; void CGLibflangWriteEmitter::EmitStart() { @@ -89,6 +90,8 @@ void CGLibflangWriteEmitter::EmitEnd() { void CGLibflangWriteEmitter::EmitWriteUnformattedList(ArrayRef<Expr*> Values) { for(auto E : Values) { auto EType = E->getType(); + if(EType->isCharacterType()) + EmitWriteUnformattedChar(E); if(auto BTy = dyn_cast<BuiltinType>(EType.getTypePtr())) EmitWriteUnformattedBuiltin(BTy, EType.getExtQualsPtrOrNull(), E); @@ -112,11 +115,6 @@ void CGLibflangWriteEmitter::EmitWriteUnformattedBuiltin(const BuiltinType *BTy, Func = CGM.GetRuntimeFunction2("write_complex", ControllerPtr->getType(), E->getType(), CGType(), getTransferABI()); break; - case BuiltinType::Character: - Func = CGM.GetRuntimeFunction2("write_character", ControllerPtr->getType(), - E->getType()); - CGF.EmitCall2(Func, ControllerPtr, CGF.EmitCharacterExpr(E)); - return; case BuiltinType::Logical: Func = CGM.GetRuntimeFunction2("write_logical", ControllerPtr->getType(), E->getType(), CGType(), getTransferABI()); @@ -128,6 +126,12 @@ void CGLibflangWriteEmitter::EmitWriteUnformattedBuiltin(const BuiltinType *BTy, CGF.EmitCall(Func.getFunction(), Func.getInfo(), ArgList, ArrayRef<Expr*>(), true); } +void CGLibflangWriteEmitter::EmitWriteUnformattedChar(const Expr *E) { + auto Func = CGM.GetRuntimeFunction2("write_character", ControllerPtr->getType(), + E->getType()); + CGF.EmitCall2(Func, ControllerPtr, CGF.EmitCharacterExpr(E)); +} + void CGLibflangIORuntime::EmitWriteStmt(CodeGenFunction &CGF, const WriteStmt *S) { // FIXME auto ControllerPtr = CGF.CreateTempAlloca(GetWriteControllerType(), "write"); diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 8b9a355767..89af3d678d 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -29,17 +29,13 @@ CodeGenTypes::CodeGenTypes(CodeGenModule &cgm) CodeGenTypes::~CodeGenTypes() { } -uint64_t CodeGenTypes::GetCharacterTypeLength(QualType T) { - auto Ext = T.getExtQualsPtrOrNull(); - return Ext && Ext->hasLengthSelector()? - Ext->getLengthSelector() : 1; -} - llvm::Type *CodeGenTypes::ConvertType(QualType T) { auto Ext = T.getExtQualsPtrOrNull(); auto TPtr = T.getTypePtr(); if(const BuiltinType *BTy = dyn_cast<BuiltinType>(TPtr)) return ConvertBuiltInType(BTy, Ext); + else if(const CharacterType *CTy = dyn_cast<CharacterType>(TPtr)) + return ConvertCharType(CTy); else if(const ArrayType *ATy = dyn_cast<ArrayType>(TPtr)) return ConvertArrayType(ATy); else if(const FunctionType *FTy = dyn_cast<FunctionType>(TPtr)) @@ -52,10 +48,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { llvm::Type *CodeGenTypes::ConvertBuiltInTypeForMem(const BuiltinType *T, const ExtQuals *Ext) { - if(T->getTypeSpec() != BuiltinType::Character) - return ConvertBuiltInType(T, Ext); - return llvm::ArrayType::get(CGM.Int8Ty, Ext && Ext->hasLengthSelector()? - Ext->getLengthSelector() : 1); + return ConvertBuiltInType(T, Ext); } llvm::Type *CodeGenTypes::ConvertBuiltInType(const BuiltinType *T, @@ -74,11 +67,6 @@ llvm::Type *CodeGenTypes::ConvertBuiltInType(const BuiltinType *T, case BuiltinType::Logical: Kind = CGM.getContext().getLogicalTypeKind(Ext); break; - - case BuiltinType::Character: - llvm::Type *Pair[2] = { CGM.Int8PtrTy, CGM.SizeTy }; - return llvm::StructType::get(CGM.getLLVMContext(), - ArrayRef<llvm::Type*>(Pair,2)); } return ConvertBuiltInType(T->getTypeSpec(), Kind); @@ -116,6 +104,18 @@ llvm::Type *CodeGenTypes::ConvertBuiltInType(BuiltinType::TypeSpec Spec, return Type; } + +llvm::Type *CodeGenTypes::ConvertCharType(const CharacterType *T) { + llvm::Type *Pair[2] = { CGM.Int8PtrTy, CGM.SizeTy }; + return llvm::StructType::get(CGM.getLLVMContext(), + ArrayRef<llvm::Type*>(Pair,2)); +} + +llvm::Type *CodeGenTypes::ConvertCharTypeForMem(const CharacterType *T) { + assert(T->hasLength()); + return llvm::ArrayType::get(CGM.Int8Ty, T->getLength()); +} + llvm::Type *CodeGenTypes::GetComplexType(llvm::Type *ElementType) { llvm::Type *Pair[2] = { ElementType, ElementType }; return llvm::StructType::get(CGM.getLLVMContext(), @@ -145,6 +145,8 @@ llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) { auto TPtr = T.getTypePtr(); if(const BuiltinType *BTy = dyn_cast<BuiltinType>(TPtr)) return ConvertBuiltInTypeForMem(BTy, Ext); + else if(const CharacterType *CTy = dyn_cast<CharacterType>(TPtr)) + return ConvertCharTypeForMem(CTy); else if(const ArrayType *ATy = dyn_cast<ArrayType>(TPtr)) return ConvertArrayTypeForMem(ATy); else if(const RecordType *RTy = dyn_cast<RecordType>(TPtr)) diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h index 6efeebe31a..8fcddd7694 100644 --- a/lib/CodeGen/CodeGenTypes.h +++ b/lib/CodeGen/CodeGenTypes.h @@ -95,6 +95,9 @@ public: llvm::Type *ConvertBuiltInType(BuiltinType::TypeSpec Spec, BuiltinType::TypeKind Kind); + llvm::Type *ConvertCharType(const CharacterType *T); + llvm::Type *ConvertCharTypeForMem(const CharacterType *T); + llvm::ArrayType *ConvertArrayTypeForMem(const ArrayType *T); llvm::Type *ConvertArrayType(const ArrayType *T); @@ -120,8 +123,6 @@ public: QualType T, const CGFunctionInfo::RetInfo &ReturnInfo); - uint64_t GetCharacterTypeLength(QualType T); - }; } // end namespace CodeGen diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index b9f3c32849..a8a8ab589d 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1027,13 +1027,10 @@ bool Sema::CheckArrayTypeDeclarationCompability(const ArrayType *T, VarDecl *VD) } bool Sema::CheckCharacterLengthDeclarationCompability(QualType T, VarDecl *VD) { - auto Ext = T.getExtQualsPtrOrNull(); - if(Ext) { - if(Ext->isStarLengthSelector() && !VD->isArgument()) { - Diags.Report(VD->getLocation(), diag::err_char_star_length_incompatible) - << (VD->isParameter()? 1 : 0) << VD->getIdentifier() - << VD->getSourceRange(); - } + if(!T->asCharacterType()->hasLength() && !VD->isArgument()) { + Diags.Report(VD->getLocation(), diag::err_char_star_length_incompatible) + << (VD->isParameter()? 1 : 0) << VD->getIdentifier() + << VD->getSourceRange(); } return true; } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 48441595f1..2de3edc60a 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -81,17 +81,6 @@ QualType Sema::ApplyTypeKind(QualType T, const Expr *E) { Context.getExtQualType(T.getTypePtr(), Qualifiers(), Kind) : T; } -unsigned Sema::EvalAndCheckCharacterLength(const Expr *E) { - auto Result = CheckIntGT0(E, EvalAndCheckIntExpr(E, 1)); - if(Result > int64_t(std::numeric_limits<unsigned>::max())) { - //FIXME overflow diag - Diags.Report(E->getLocation(), diag::err_expected_integer_constant_expr) - << E->getSourceRange(); - return 1; - } - return Result; -} - bool Sema::CheckConstantExpression(const Expr *E) { if(!E->isEvaluatable(Context)) { Diags.Report(E->getLocation(), @@ -293,6 +282,8 @@ bool Sema::CheckCharacterExpression(const Expr *E) { } bool Sema::AreTypesOfSameKind(QualType A, QualType B) const { + if(A->isCharacterType()) + return B->isCharacterType(); if(auto ABTy = dyn_cast<BuiltinType>(A.getTypePtr())) { auto BBTy = dyn_cast<BuiltinType>(B.getTypePtr()); if(!BBTy) return false; @@ -307,8 +298,6 @@ bool Sema::AreTypesOfSameKind(QualType A, QualType B) const { case BuiltinType::Real: return Context.getRealTypeKind(AExt) == Context.getRealTypeKind(BExt); - case BuiltinType::Character: - return true; case BuiltinType::Complex: return Context.getComplexTypeKind(AExt) == Context.getComplexTypeKind(BExt); @@ -330,7 +319,7 @@ bool Sema::CheckTypesOfSameKind(QualType A, QualType B, } bool Sema::CheckTypeScalarOrCharacter(const Expr *E, QualType T, bool IsConstant) { - if(isa<BuiltinType>(T.getTypePtr())) return true; + if(T->isBuiltinType() || T->isCharacterType()) return true; Diags.Report(E->getLocation(), IsConstant? diag::err_expected_scalar_or_character_constant_expr : diag::err_expected_scalar_or_character_expr) @@ -364,7 +353,7 @@ Expr *Sema::TypecheckExprIntegerOrLogicalOrSameCharacter(Expr *E, } bool Sema::IsDefaultBuiltinOrDoublePrecisionType(QualType T) { - if(!T->isBuiltinType()) + if(!(T->isBuiltinType() || T->isCharacterType())) return false; auto Ext = T.getExtQualsPtrOrNull(); if(!Ext) return true; @@ -462,21 +451,27 @@ bool Sema::CheckArgumentsTypeCompability(const Expr *E1, const Expr *E2, StringRef ArgName1, StringRef ArgName2, bool AllowArrays) { // assume builtin type - auto Type1 = getBuiltinType(E1, AllowArrays); - auto Type2 = getBuiltinType(E2, AllowArrays); - auto T1 = AllowArrays? E1->getType().getSelfOrArrayElementType() : E1->getType(); - auto T2 = AllowArrays? E2->getType().getSelfOrArrayElementType() : E2->getType(); - auto Ext1 = T1.getExtQualsPtrOrNull(); - auto Ext2 = T2.getExtQualsPtrOrNull(); - if(!Type2 || Type1->getTypeSpec() != Type2->getTypeSpec() || - Context.getArithmeticOrLogicalTypeKind(Ext1,T1) != Context.getArithmeticOrLogicalTypeKind(Ext2, T2)) { - Diags.Report(E2->getLocation(), diag::err_typecheck_arg_conflict_type) - << ArgName1 << ArgName2 - << T1 << T2 - << E1->getSourceRange() << E2->getSourceRange(); - return true; + auto T1 = ScalarizeType(E1->getType(), AllowArrays); + auto T2 = ScalarizeType(E2->getType(), AllowArrays); + + if(T1->isCharacterType()) { + if(T2->isCharacterType()) + return false; + } else { + auto Type1 = getBuiltinType(E1, AllowArrays); + auto Type2 = getBuiltinType(E2, AllowArrays); + auto Ext1 = T1.getExtQualsPtrOrNull(); + auto Ext2 = T2.getExtQualsPtrOrNull(); + if(!(!Type2 || Type1->getTypeSpec() != Type2->getTypeSpec() || + Context.getArithmeticOrLogicalTypeKind(Ext1,T1) != Context.getArithmeticOrLogicalTypeKind(Ext2, T2))) + return false; } - return false; + + Diags.Report(E2->getLocation(), diag::err_typecheck_arg_conflict_type) + << ArgName1 << ArgName2 + << T1 << T2 + << E1->getSourceRange() << E2->getSourceRange(); + return true; } bool Sema::CheckBuiltinTypeArgument(const Expr *E, bool AllowArrays) { @@ -535,8 +530,7 @@ bool Sema::CheckDoubleComplexArgument(const Expr *E, bool AllowArrays) { } bool Sema::CheckCharacterArgument(const Expr *E) { - auto Type = getBuiltinType(E); - if(!Type || !Type->isCharacterType()) + if(!E->getType()->isCharacterType()) return DiagnoseIncompatiblePassing(E, Context.CharacterTy, false); return false; } diff --git a/lib/Sema/SemaDataStmt.cpp b/lib/Sema/SemaDataStmt.cpp index 66ee448eba..36ba3e3828 100644 --- a/lib/Sema/SemaDataStmt.cpp +++ b/lib/Sema/SemaDataStmt.cpp @@ -283,11 +283,8 @@ void DataStmtEngine::VisitArrayElementExpr(ArrayElementExpr *E) { ExprResult DataStmtEngine::CreateSubstringExprInitializer(SubstringExpr *E, QualType CharTy) { - uint64_t Len = 1; - if(auto Ext = CharTy.getExtQualsPtrOrNull()) { - if(Ext->hasLengthSelector()) - Len = Ext->getLengthSelector(); - } + auto CTy = CharTy.getSelfOrArrayElementType()->asCharacterType(); + uint64_t Len = CTy->hasLength()? CTy->getLength() : 1; uint64_t Begin, End; if(!E->EvaluateRange(Context, Len, Begin, End, &ImpliedDoEvaluator)) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f1a7a9bda1..224379d939 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -108,6 +108,10 @@ bool Sema::CheckDeclaration(const IdentifierInfo *IDInfo, SourceLocation IDLoc) // Type construction // +uint64_t Sema::EvalAndCheckCharacterLength(const Expr *E) { + return CheckIntGT0(E, EvalAndCheckIntExpr(E, 1)); +} + /// \brief Convert the specified DeclSpec to the appropriate type object. QualType Sema::ActOnTypeName(ASTContext &C, DeclSpec &DS) { QualType Result; @@ -120,7 +124,12 @@ QualType Sema::ActOnTypeName(ASTContext &C, DeclSpec &DS) { Result = C.RealTy; break; case DeclSpec::TST_character: - Result = C.CharacterTy; + if(DS.isStarLengthSelector()) + Result = C.NoLengthCharacterTy; + else if(DS.hasLengthSelector()) + Result = QualType(C.getCharacterType( + EvalAndCheckCharacterLength(DS.getLengthSelector())), 0); + else Result = C.CharacterTy; break; case DeclSpec::TST_logical: Result = C.LogicalTy; @@ -151,14 +160,8 @@ QualType Sema::ActOnTypeName(ASTContext &C, DeclSpec &DS) { } else if(DS.hasKindSelector()) Kind = EvalAndCheckTypeKind(Result, DS.getKindSelector()); - unsigned LengthSelector = 0; - if(DS.hasLengthSelector() && !DS.isStarLengthSelector()) - LengthSelector = EvalAndCheckCharacterLength(DS.getLengthSelector()); - Result = C.getExtQualType(TypeNode, Quals, Kind, - DS.isDoublePrecision(), - DS.isStarLengthSelector(), - LengthSelector); + DS.isDoublePrecision()); if (!Quals.hasAttributeSpec(Qualifiers::AS_dimension)) return Result; |