summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarphaman <arphaman@gmail.com>2013-09-19 13:52:26 +0100
committerarphaman <arphaman@gmail.com>2013-09-19 13:52:26 +0100
commit2d9553a89153be4ed76408c439e749b88a16b8d2 (patch)
treece9b825434c5a469137795999c78278efe999bcd
parent77938070560e981eb408990f2380f2e2370488bd (diff)
downloadflang-2d9553a89153be4ed76408c439e749b88a16b8d2.tar.gz
added character type; removed char builtin type and length spec in extquals
-rw-r--r--include/flang/AST/ASTContext.h9
-rw-r--r--include/flang/AST/Type.h63
-rw-r--r--include/flang/AST/TypeNodes.def3
-rw-r--r--include/flang/Sema/Sema.h2
-rw-r--r--lib/AST/ASTContext.cpp45
-rw-r--r--lib/AST/ASTDumper.cpp21
-rw-r--r--lib/AST/Expr.cpp7
-rw-r--r--lib/AST/ExprConstant.cpp7
-rw-r--r--lib/CodeGen/CGCall.cpp7
-rw-r--r--lib/CodeGen/CGExprCharacter.cpp20
-rw-r--r--lib/CodeGen/CGIOLibflang.cpp14
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp32
-rw-r--r--lib/CodeGen/CodeGenTypes.h5
-rw-r--r--lib/Sema/Sema.cpp11
-rw-r--r--lib/Sema/SemaChecking.cpp56
-rw-r--r--lib/Sema/SemaDataStmt.cpp7
-rw-r--r--lib/Sema/SemaDecl.cpp19
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;