Index: clang/include/clang/AST/APValue.h =================================================================== --- clang/include/clang/AST/APValue.h +++ clang/include/clang/AST/APValue.h @@ -179,6 +179,10 @@ struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + + friend class ASTReader; + friend class ASTWriter; + private: ValueKind Kind; @@ -313,8 +317,8 @@ void dump() const; void dump(raw_ostream &OS) const; - void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const; - std::string getAsString(ASTContext &Ctx, QualType Ty) const; + void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const; + std::string getAsString(const ASTContext &Ctx, QualType Ty) const; APSInt &getInt() { assert(isInt() && "Invalid accessor"); Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -271,6 +271,9 @@ llvm::DenseMap MaterializedTemporaryValues; + /// Used to cleanups APValues stored in the AST. + mutable llvm::SmallVector APValueCleanups; + /// A cache mapping a string value to a StringLiteral object with the same /// value. /// @@ -2815,6 +2818,10 @@ APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, bool MayCreate); + /// Adds an APValue that will be destructed during the destruction of the + /// ASTContext. + void AddAPValueCleanup(APValue *Ptr) const { APValueCleanups.push_back(Ptr); } + /// Return a string representing the human readable name for the specified /// function declaration or file name. Used by SourceLocExpr and /// PredefinedExpr to cache evaluated results. Index: clang/include/clang/AST/Expr.h =================================================================== --- clang/include/clang/AST/Expr.h +++ clang/include/clang/AST/Expr.h @@ -933,21 +933,57 @@ } }; -/// ConstantExpr - An expression that occurs in a constant context. -class ConstantExpr : public FullExpr { - ConstantExpr(Expr *subexpr) - : FullExpr(ConstantExprClass, subexpr) {} +/// ConstantExpr - An expression that occurs in a constant context and +/// optionally the result of evaluating the expression. +class ConstantExpr final + : public FullExpr, + private llvm::TrailingObjects { public: - static ConstantExpr *Create(const ASTContext &Context, Expr *E) { - assert(!isa(E)); - return new (Context) ConstantExpr(E); + /// Describes the kind of result that can be trail-allocated. + enum ResultStorageKind { RSK_None, RSK_APSInt, RSK_APValue }; + +private: + size_t numTrailingObjects(OverloadToken) const { + return ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue; + } + size_t numTrailingObjects(OverloadToken) const { + return ConstantExprBits.ResultKind == ConstantExpr::RSK_APSInt; + } + + llvm::APSInt &IntResult() { + assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_APSInt && + "invalid accessor"); + return *getTrailingObjects(); + } + const llvm::APSInt &IntResult() const { + return const_cast(this)->IntResult(); + } + APValue &APValueResult() { + assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue && + "invalid accessor"); + return *getTrailingObjects(); + } + const APValue &APValueResult() const { + return const_cast(this)->APValueResult(); } - /// Build an empty constant expression wrapper. - explicit ConstantExpr(EmptyShell Empty) - : FullExpr(ConstantExprClass, Empty) {} + ConstantExpr(Expr *subexpr, ResultStorageKind StorageKind); + ConstantExpr(ResultStorageKind StorageKind, EmptyShell Empty); +public: + friend TrailingObjects; + friend class ASTStmtReader; + friend class ASTStmtWriter; + static ConstantExpr *Create(const ASTContext &Context, Expr *E, + const APValue &Result); + static ConstantExpr *Create(const ASTContext &Context, Expr *E, + ResultStorageKind Storage = RSK_None); + static ConstantExpr *CreateEmpty(const ASTContext &Context, + ResultStorageKind StorageKind, + EmptyShell Empty); + + static ResultStorageKind getStorageKind(APValue::ValueKind Kind); SourceLocation getBeginLoc() const LLVM_READONLY { return SubExpr->getBeginLoc(); } @@ -959,6 +995,25 @@ return T->getStmtClass() == ConstantExprClass; } + void SetResult(APValue Value) { MoveIntoResult(Value); } + void MoveIntoResult(APValue &Value); + + APValue::ValueKind getResultAPValueKind() const { + switch (ConstantExprBits.ResultKind) { + case ConstantExpr::RSK_APValue: + return APValueResult().getKind(); + case ConstantExpr::RSK_APSInt: + return APValue::Int; + case ConstantExpr::RSK_None: + return APValue::Uninitialized; + } + llvm_unreachable("invalid ResultKind"); + } + ResultStorageKind getResultStorageKind() const { + return static_cast(ConstantExprBits.ResultKind); + } + APValue getAPValueResult() const; + // Iterators child_range children() { return child_range(&SubExpr, &SubExpr+1); } const_child_range children() const { @@ -1499,21 +1554,28 @@ /// Get a raw enumeration value representing the floating-point semantics of /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. - APFloatSemantics getRawSemantics() const { - return static_cast(FloatingLiteralBits.Semantics); + llvm::APFloatBase::Semantics getRawSemantics() const { + return static_cast( + FloatingLiteralBits.Semantics); } /// Set the raw enumeration value representing the floating-point semantics of /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. - void setRawSemantics(APFloatSemantics Sem) { + void setRawSemantics(llvm::APFloatBase::Semantics Sem) { FloatingLiteralBits.Semantics = Sem; } /// Return the APFloat semantics this literal uses. - const llvm::fltSemantics &getSemantics() const; + const llvm::fltSemantics &getSemantics() const { + return llvm::APFloatBase::EnumToSemantics( + static_cast( + FloatingLiteralBits.Semantics)); + } /// Set the APFloat semantics this literal uses. - void setSemantics(const llvm::fltSemantics &Sem); + void setSemantics(const llvm::fltSemantics &Sem) { + FloatingLiteralBits.Semantics = llvm::APFloatBase::SemanticsToEnum(Sem); + } bool isExact() const { return FloatingLiteralBits.IsExact; } void setExact(bool E) { FloatingLiteralBits.IsExact = E; } Index: clang/include/clang/AST/Stmt.h =================================================================== --- clang/include/clang/AST/Stmt.h +++ clang/include/clang/AST/Stmt.h @@ -321,6 +321,17 @@ }; enum { NumExprBits = NumStmtBits + 9 }; + class ConstantExprBitfields { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend class ConstantExpr; + + unsigned : NumExprBits; + + /// The kind of result that is trail-allocated. + unsigned ResultKind : 2; + }; + class PredefinedExprBitfields { friend class ASTStmtReader; friend class PredefinedExpr; @@ -355,14 +366,6 @@ SourceLocation Loc; }; - enum APFloatSemantics { - IEEEhalf, - IEEEsingle, - IEEEdouble, - x87DoubleExtended, - IEEEquad, - PPCDoubleDouble - }; class FloatingLiteralBitfields { friend class FloatingLiteral; @@ -930,6 +933,7 @@ // Expressions ExprBitfields ExprBits; + ConstantExprBitfields ConstantExprBits; PredefinedExprBitfields PredefinedExprBits; DeclRefExprBitfields DeclRefExprBits; FloatingLiteralBitfields FloatingLiteralBits; Index: clang/include/clang/AST/TextNodeDumper.h =================================================================== --- clang/include/clang/AST/TextNodeDumper.h +++ clang/include/clang/AST/TextNodeDumper.h @@ -146,6 +146,8 @@ const comments::CommandTraits *Traits; + const ASTContext *Context; + const char *getCommandName(unsigned CommandID); public: @@ -228,6 +230,7 @@ void VisitLabelStmt(const LabelStmt *Node); void VisitGotoStmt(const GotoStmt *Node); void VisitCaseStmt(const CaseStmt *Node); + void VisitConstantExpr(const ConstantExpr *Node); void VisitCallExpr(const CallExpr *Node); void VisitCastExpr(const CastExpr *Node); void VisitImplicitCastExpr(const ImplicitCastExpr *Node); Index: clang/include/clang/Serialization/ASTReader.h =================================================================== --- clang/include/clang/Serialization/ASTReader.h +++ clang/include/clang/Serialization/ASTReader.h @@ -2220,6 +2220,9 @@ llvm::APFloat ReadAPFloat(const RecordData &Record, const llvm::fltSemantics &Sem, unsigned &Idx); + /// Read an APValue + APValue ReadAPValue(const RecordData &Record, unsigned &Idx); + // Read a string static std::string ReadString(const RecordData &Record, unsigned &Idx); @@ -2612,6 +2615,8 @@ return Reader->ReadSourceRange(*F, Record, Idx); } + APValue readAPValue() { return Reader->ReadAPValue(Record, Idx); } + /// Read an integral value, advancing Idx. llvm::APInt readAPInt() { return Reader->ReadAPInt(Record, Idx); Index: clang/include/clang/Serialization/ASTWriter.h =================================================================== --- clang/include/clang/Serialization/ASTWriter.h +++ clang/include/clang/Serialization/ASTWriter.h @@ -863,6 +863,9 @@ /// Emit a floating-point value. void AddAPFloat(const llvm::APFloat &Value); + /// Emit an integral value. + void AddAPValue(const APValue &Value); + /// Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II) { return Writer->AddIdentifierRef(II, *Record); Index: clang/lib/AST/APValue.cpp =================================================================== --- clang/lib/AST/APValue.cpp +++ clang/lib/AST/APValue.cpp @@ -450,7 +450,8 @@ llvm_unreachable("Unknown APValue kind!"); } -void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ +void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, + QualType Ty) const { switch (getKind()) { case APValue::Uninitialized: Out << ""; @@ -666,7 +667,7 @@ llvm_unreachable("Unknown APValue kind!"); } -std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { +std::string APValue::getAsString(const ASTContext &Ctx, QualType Ty) const { std::string Result; llvm::raw_string_ostream Out(Result); printPretty(Out, Ctx, Ty); Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -827,6 +827,9 @@ for (const auto &Value : ModuleInitializers) Value.second->~PerModuleInitializers(); + + for (APValue *Value : APValueCleanups) + Value->~APValue(); } class ASTContext::ParentMap { Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -6365,6 +6365,13 @@ Expr *ToSubExpr; std::tie(ToSubExpr) = *Imp; + // TODO : Handle APValue::ValueKind that require importing. + APValue::ValueKind Kind = E->getResultAPValueKind(); + if (Kind == APValue::Int || Kind == APValue::Float || + Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat || + Kind == APValue::ComplexInt) + return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, + E->getAPValueResult()); return ConstantExpr::Create(Importer.getToContext(), ToSubExpr); } Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -229,6 +229,116 @@ // Primary Expressions. //===----------------------------------------------------------------------===// +static void AssertResultStorageKind(ConstantExpr::ResultStorageKind Kind) { + assert((Kind == ConstantExpr::RSK_APValue || + Kind == ConstantExpr::RSK_APSInt || Kind == ConstantExpr::RSK_None) && + "Invalid StorageKind Value"); +} + +ConstantExpr::ResultStorageKind +ConstantExpr::getStorageKind(APValue::ValueKind Kind) { + switch (Kind) { + case APValue::Uninitialized: + return ConstantExpr::RSK_None; + case APValue::Int: + return ConstantExpr::RSK_APSInt; + default: + return ConstantExpr::RSK_APValue; + } +} + +ConstantExpr::ConstantExpr(Expr *subexpr, ResultStorageKind StorageKind) + : FullExpr(ConstantExprClass, subexpr) { + ConstantExprBits.ResultKind = StorageKind; + switch (StorageKind) { + case RSK_None: + break; + case RSK_APSInt: + ::new (getTrailingObjects()) llvm::APSInt(); + break; + case RSK_APValue: + ::new (getTrailingObjects()) APValue(); + } +} + +ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E, + ResultStorageKind StorageKind) { + assert(!isa(E)); + AssertResultStorageKind(StorageKind); + unsigned Size = totalSizeToAlloc( + StorageKind == ConstantExpr::RSK_APValue, + StorageKind == ConstantExpr::RSK_APSInt); + void *Mem = Context.Allocate(Size, alignof(ConstantExpr)); + ConstantExpr *Self = new (Mem) ConstantExpr(E, StorageKind); + if (StorageKind == ConstantExpr::RSK_APValue) + Context.AddAPValueCleanup(&Self->APValueResult()); + return Self; +} + +ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E, + const APValue &Result) { + ResultStorageKind StorageKind = getStorageKind(Result.getKind()); + ConstantExpr *Self = Create(Context, E, StorageKind); + Self->SetResult(Result); + return Self; +} + +ConstantExpr::ConstantExpr(ResultStorageKind StorageKind, EmptyShell Empty) + : FullExpr(ConstantExprClass, Empty) { + ConstantExprBits.ResultKind = StorageKind; + switch (StorageKind) { + case ConstantExpr::RSK_None: + break; + case ConstantExpr::RSK_APSInt: + ::new (getTrailingObjects()) llvm::APSInt(); + break; + case ConstantExpr::RSK_APValue: + ::new (getTrailingObjects()) APValue(); + } +} + +ConstantExpr *ConstantExpr::CreateEmpty(const ASTContext &Context, + ResultStorageKind StorageKind, + EmptyShell Empty) { + AssertResultStorageKind(StorageKind); + unsigned Size = totalSizeToAlloc( + StorageKind == ConstantExpr::RSK_APValue, + StorageKind == ConstantExpr::RSK_APSInt); + void *Mem = Context.Allocate(Size, alignof(ConstantExpr)); + ConstantExpr *Node = new (Mem) ConstantExpr(StorageKind, Empty); + if (StorageKind == ConstantExpr::RSK_APValue) + Context.AddAPValueCleanup(&Node->APValueResult()); + return Node; +} + +void ConstantExpr::MoveIntoResult(APValue &Value) { + assert(getStorageKind(Value.getKind()) == ConstantExprBits.ResultKind && + "Invalid storage for this value kind"); + switch (ConstantExprBits.ResultKind) { + case RSK_None: + return; + case RSK_APSInt: + IntResult() = std::move(Value.getInt()); + return; + case RSK_APValue: + APValueResult() = std::move(Value); + return; + } + llvm_unreachable("Invalid ResultKind Bits"); +} + +APValue ConstantExpr::getAPValueResult() const { + switch (ConstantExprBits.ResultKind) { + case ConstantExpr::RSK_APValue: + return APValueResult(); + case ConstantExpr::RSK_APSInt: + return APValue(IntResult()); + case ConstantExpr::RSK_None: + return APValue(); + } + llvm_unreachable("invalid ResultKind"); +} + /// Compute the type-, value-, and instantiation-dependence of a /// declaration reference /// based on the declaration being referenced. @@ -840,7 +950,7 @@ FloatingLiteral::FloatingLiteral(const ASTContext &C, EmptyShell Empty) : Expr(FloatingLiteralClass, Empty) { - setRawSemantics(IEEEhalf); + setRawSemantics(llvm::APFloatBase::S_IEEEhalf); FloatingLiteralBits.IsExact = false; } @@ -855,41 +965,6 @@ return new (C) FloatingLiteral(C, Empty); } -const llvm::fltSemantics &FloatingLiteral::getSemantics() const { - switch(FloatingLiteralBits.Semantics) { - case IEEEhalf: - return llvm::APFloat::IEEEhalf(); - case IEEEsingle: - return llvm::APFloat::IEEEsingle(); - case IEEEdouble: - return llvm::APFloat::IEEEdouble(); - case x87DoubleExtended: - return llvm::APFloat::x87DoubleExtended(); - case IEEEquad: - return llvm::APFloat::IEEEquad(); - case PPCDoubleDouble: - return llvm::APFloat::PPCDoubleDouble(); - } - llvm_unreachable("Unrecognised floating semantics"); -} - -void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) { - if (&Sem == &llvm::APFloat::IEEEhalf()) - FloatingLiteralBits.Semantics = IEEEhalf; - else if (&Sem == &llvm::APFloat::IEEEsingle()) - FloatingLiteralBits.Semantics = IEEEsingle; - else if (&Sem == &llvm::APFloat::IEEEdouble()) - FloatingLiteralBits.Semantics = IEEEdouble; - else if (&Sem == &llvm::APFloat::x87DoubleExtended()) - FloatingLiteralBits.Semantics = x87DoubleExtended; - else if (&Sem == &llvm::APFloat::IEEEquad()) - FloatingLiteralBits.Semantics = IEEEquad; - else if (&Sem == &llvm::APFloat::PPCDoubleDouble()) - FloatingLiteralBits.Semantics = PPCDoubleDouble; - else - llvm_unreachable("Unknown floating semantics"); -} - /// getValueAsApproximateDouble - This returns the value as an inaccurate /// double. Note that this may cause loss of precision, but is useful for /// debugging dumps, etc. Index: clang/lib/AST/TextNodeDumper.cpp =================================================================== --- clang/lib/AST/TextNodeDumper.cpp +++ clang/lib/AST/TextNodeDumper.cpp @@ -223,6 +223,7 @@ return; } + Context = &D->getASTContext(); { ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << D->getDeclKindName() << "Decl"; @@ -686,6 +687,14 @@ OS << " gnu_range"; } +void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) { + if (Node->getResultAPValueKind() != APValue::Uninitialized) { + ColorScope Color(OS, ShowColors, ValueColor); + OS << " "; + Node->getAPValueResult().printPretty(OS, *Context, Node->getType()); + } +} + void TextNodeDumper::VisitCallExpr(const CallExpr *Node) { if (Node->usesADL()) OS << " adl"; Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -5514,7 +5514,7 @@ if (Notes.empty()) { // It's a constant expression. - return ConstantExpr::Create(S.Context, Result.get()); + return ConstantExpr::Create(S.Context, Result.get(), Value); } } Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -9102,6 +9102,61 @@ return SourceRange(beg, end); } +static FixedPointSemantics +ReadFixedPointSemantics(const SmallVectorImpl &Record, + unsigned &Idx) { + uint64_t Tmp = Record[Idx++]; + unsigned Width = Tmp & 0xffffffff; + unsigned Scale = Tmp >> static_cast(32); + Tmp = Record[Idx++]; + bool IsSigned = Tmp & 0x1; + bool IsSaturated = Tmp & 0x2; + bool HasUnsignedPadding = Tmp & 0x4; + return FixedPointSemantics(Width, Scale, IsSigned, IsSaturated, + HasUnsignedPadding); +} + +APValue ASTReader::ReadAPValue(const RecordData &Record, unsigned &Idx) { + unsigned Kind = Record[Idx++]; + switch (Kind) { + case APValue::Uninitialized: + return APValue(); + case APValue::Int: + return APValue(ReadAPSInt(Record, Idx)); + case APValue::Float: { + const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics( + static_cast(Record[Idx++])); + return APValue(ReadAPFloat(Record, FloatSema, Idx)); + } + case APValue::FixedPoint: { + FixedPointSemantics FPSema = ReadFixedPointSemantics(Record, Idx); + return APValue(APFixedPoint(ReadAPInt(Record, Idx), FPSema)); + } + case APValue::ComplexInt: { + llvm::APSInt First = ReadAPSInt(Record, Idx); + return APValue(std::move(First), ReadAPSInt(Record, Idx)); + } + case APValue::ComplexFloat: { + const llvm::fltSemantics &FloatSema1 = llvm::APFloatBase::EnumToSemantics( + static_cast(Record[Idx++])); + llvm::APFloat First = ReadAPFloat(Record, FloatSema1, Idx); + const llvm::fltSemantics &FloatSema2 = llvm::APFloatBase::EnumToSemantics( + static_cast(Record[Idx++])); + return APValue(std::move(First), ReadAPFloat(Record, FloatSema2, Idx)); + } + case APValue::LValue: + case APValue::Vector: + case APValue::Array: + case APValue::Struct: + case APValue::Union: + case APValue::MemberPointer: + case APValue::AddrLabelDiff: + // TODO : Handle all these APValue::ValueKind. + return APValue(); + } + llvm_unreachable("Invalid APValue::ValueKind"); +} + /// Read an integral value llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) { unsigned BitWidth = Record[Idx++]; Index: clang/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- clang/lib/Serialization/ASTReaderStmt.cpp +++ clang/lib/Serialization/ASTReaderStmt.cpp @@ -526,6 +526,14 @@ void ASTStmtReader::VisitConstantExpr(ConstantExpr *E) { VisitExpr(E); + E->ConstantExprBits.ResultKind = Record.readInt(); + switch (E->ConstantExprBits.ResultKind) { + case ConstantExpr::RSK_APSInt: + E->IntResult() = Record.readAPSInt(); + break; + case ConstantExpr::RSK_APValue: + E->APValueResult() = Record.readAPValue(); + } E->setSubExpr(Record.readSubExpr()); } @@ -582,7 +590,8 @@ void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) { VisitExpr(E); - E->setRawSemantics(static_cast(Record.readInt())); + E->setRawSemantics( + static_cast(Record.readInt())); E->setExact(Record.readInt()); E->setValue(Record.getContext(), Record.readAPFloat(E->getSemantics())); E->setLocation(ReadSourceLocation()); @@ -2464,7 +2473,11 @@ break; case EXPR_CONSTANT: - S = new (Context) ConstantExpr(Empty); + S = ConstantExpr::CreateEmpty( + Context, + static_cast( + Record[ASTStmtReader::NumExprFields]), + Empty); break; case EXPR_PREDEFINED: Index: clang/lib/Serialization/ASTWriter.cpp =================================================================== --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -5399,6 +5399,61 @@ AddAPInt(Value.bitcastToAPInt()); } +static void WriteFixedPointSemantics(ASTRecordWriter &Record, + FixedPointSemantics FPSema) { + Record.push_back(static_cast(FPSema.getWidth()) | + static_cast(FPSema.getScale()) + << static_cast(32)); + Record.push_back(FPSema.isSigned() | FPSema.isSaturated() << 1 | + FPSema.hasUnsignedPadding() << 2); +} + +void ASTRecordWriter::AddAPValue(const APValue &Value) { + APValue::ValueKind Kind = Value.getKind(); + push_back(static_cast(Kind)); + switch (Kind) { + case APValue::Uninitialized: + return; + case APValue::Int: + AddAPSInt(Value.getInt()); + return; + case APValue::Float: + push_back(static_cast( + llvm::APFloatBase::SemanticsToEnum(Value.getFloat().getSemantics()))); + AddAPFloat(Value.getFloat()); + return; + case APValue::FixedPoint: { + WriteFixedPointSemantics(*this, Value.getFixedPoint().getSemantics()); + AddAPSInt(Value.getFixedPoint().getValue()); + return; + } + case APValue::ComplexInt: { + AddAPSInt(Value.getComplexIntReal()); + AddAPSInt(Value.getComplexIntImag()); + return; + } + case APValue::ComplexFloat: { + push_back(static_cast(llvm::APFloatBase::SemanticsToEnum( + Value.getComplexFloatReal().getSemantics()))); + AddAPFloat(Value.getComplexFloatReal()); + push_back(static_cast(llvm::APFloatBase::SemanticsToEnum( + Value.getComplexFloatImag().getSemantics()))); + AddAPFloat(Value.getComplexFloatImag()); + return; + } + case APValue::LValue: + case APValue::Vector: + case APValue::Array: + case APValue::Struct: + case APValue::Union: + case APValue::MemberPointer: + case APValue::AddrLabelDiff: + // TODO : Handle all these APValue::ValueKind. + return; + } + llvm_unreachable("Invalid APValue::ValueKind"); +} + void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) { Record.push_back(getIdentifierRef(II)); } Index: clang/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- clang/lib/Serialization/ASTWriterStmt.cpp +++ clang/lib/Serialization/ASTWriterStmt.cpp @@ -428,6 +428,14 @@ void ASTStmtWriter::VisitConstantExpr(ConstantExpr *E) { VisitExpr(E); + Record.push_back(static_cast(E->ConstantExprBits.ResultKind)); + switch (E->ConstantExprBits.ResultKind) { + case ConstantExpr::RSK_APSInt: + Record.AddAPSInt(E->IntResult()); + break; + case ConstantExpr::RSK_APValue: + Record.AddAPValue(E->APValueResult()); + } Record.AddStmt(E->getSubExpr()); Code = serialization::EXPR_CONSTANT; } Index: clang/test/AST/ast-dump-color.cpp =================================================================== --- clang/test/AST/ast-dump-color.cpp +++ clang/test/AST/ast-dump-color.cpp @@ -49,13 +49,13 @@ //CHECK: {{^}}[[Blue]]| | |-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:10:11[[RESET]]> [[Green]]'int'[[RESET]][[Cyan:.\[0;36m]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}} //CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:14[[RESET]], [[Yellow]]line:15:3[[RESET]]>{{$}} //CHECK: {{^}}[[Blue]]| | |-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:3[[RESET]], [[Yellow]]line:12:27[[RESET]]>{{$}} -//CHECK: {{^}}[[Blue]]| | | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]]{{$}} +//CHECK: {{^}}[[Blue]]| | | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}} //CHECK: {{^}}[[Blue]]| | | | `-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}} //CHECK: {{^}}[[Blue]]| | | `-[[RESET]][[MAGENTA]]AttributedStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:12:5[[RESET]], [[Yellow]]col:27[[RESET]]>{{$}} //CHECK: {{^}}[[Blue]]| | | |-[[RESET]][[BLUE]]FallThroughAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:7[[RESET]], [[Yellow]]col:14[[RESET]]>{{$}} //CHECK: {{^}}[[Blue]]| | | `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:27[[RESET]]>{{$}} //CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:3[[RESET]], [[Yellow]]line:14:5[[RESET]]>{{$}} -//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]]{{$}} +//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 2[[RESET]]{{$}} //CHECK: {{^}}[[Blue]]| | | `-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 2[[RESET]]{{$}} //CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:14:5[[RESET]]>{{$}} //CHECK: {{^}}[[Blue]]| `-[[RESET]][[Blue]]FullComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:8:4[[RESET]], [[Yellow]]col:11[[RESET]]>{{$}} Index: llvm/include/llvm/ADT/APFloat.h =================================================================== --- llvm/include/llvm/ADT/APFloat.h +++ llvm/include/llvm/ADT/APFloat.h @@ -147,6 +147,17 @@ /// \name Floating Point Semantics. /// @{ + enum Semantics { + S_IEEEhalf, + S_IEEEsingle, + S_IEEEdouble, + S_x87DoubleExtended, + S_IEEEquad, + S_PPCDoubleDouble + }; + + static const llvm::fltSemantics &EnumToSemantics(Semantics S); + static Semantics SemanticsToEnum(const llvm::fltSemantics &Sem); static const fltSemantics &IEEEhalf() LLVM_READNONE; static const fltSemantics &IEEEsingle() LLVM_READNONE; Index: llvm/lib/Support/APFloat.cpp =================================================================== --- llvm/lib/Support/APFloat.cpp +++ llvm/lib/Support/APFloat.cpp @@ -113,6 +113,42 @@ static const fltSemantics semPPCDoubleDoubleLegacy = {1023, -1022 + 53, 53 + 53, 128}; + const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) { + switch (S) { + case S_IEEEhalf: + return IEEEhalf(); + case S_IEEEsingle: + return IEEEsingle(); + case S_IEEEdouble: + return IEEEdouble(); + case S_x87DoubleExtended: + return x87DoubleExtended(); + case S_IEEEquad: + return IEEEquad(); + case S_PPCDoubleDouble: + return PPCDoubleDouble(); + } + llvm_unreachable("Unrecognised floating semantics"); + } + + APFloatBase::Semantics + APFloatBase::SemanticsToEnum(const llvm::fltSemantics &Sem) { + if (&Sem == &llvm::APFloat::IEEEhalf()) + return S_IEEEhalf; + else if (&Sem == &llvm::APFloat::IEEEsingle()) + return S_IEEEsingle; + else if (&Sem == &llvm::APFloat::IEEEdouble()) + return S_IEEEdouble; + else if (&Sem == &llvm::APFloat::x87DoubleExtended()) + return S_x87DoubleExtended; + else if (&Sem == &llvm::APFloat::IEEEquad()) + return S_IEEEquad; + else if (&Sem == &llvm::APFloat::PPCDoubleDouble()) + return S_PPCDoubleDouble; + else + llvm_unreachable("Unknown floating semantics"); + } + const fltSemantics &APFloatBase::IEEEhalf() { return semIEEEhalf; }