Tyker updated this revision to Diff 282682.
Tyker edited the summary of this revision.
Tyker added a comment.
Sorry for the delay
In D63640#2151016 <https://reviews.llvm.org/D63640#2151016>, @rsmith wrote:
> Are we at a point where we can test this now?
Yes we can use consteval to test it. so i removed changes to constexpr AST
modling.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D63640/new/
https://reviews.llvm.org/D63640
Files:
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/ASTImporter.h
clang/lib/AST/APValue.cpp
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/Expr.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/test/ASTMerge/APValue/APValue.cpp
Index: clang/test/ASTMerge/APValue/APValue.cpp
===================================================================
--- /dev/null
+++ clang/test/ASTMerge/APValue/APValue.cpp
@@ -0,0 +1,460 @@
+// RUN: %clang_cc1 -std=gnu++2a -emit-pch %s -o %t.pch
+// RUN: %clang_cc1 -std=gnu++2a %s -DEMIT -ast-merge %t.pch -ast-dump-all | FileCheck %s
+
+#ifndef EMIT
+#define EMIT
+
+namespace Integer {
+
+consteval int fint() {
+ return 6789;
+}
+
+int Unique_Int = fint();
+//CHECK: VarDecl {{.*}} Unique_Int
+//CHECK-NEXT: ConstantExpr {{.*}} 'int'
+//CHECK-NEXT: value: Int 6789
+
+consteval __uint128_t fint128() {
+ return ((__uint128_t)0x75f17d6b3588f843 << 64) | 0xb13dea7c9c324e51;
+}
+
+constexpr __uint128_t Unique_Int128 = fint128();
+//CHECK: VarDecl {{.*}} Unique_Int128
+//CHECK-NEXT: value: Int 156773562844924187900898496343692168785
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: Int 156773562844924187900898496343692168785
+
+} // namespace Integer
+
+namespace FloatingPoint {
+
+consteval double fdouble() {
+ return double(567890.67890);
+}
+
+double Unique_Double = fdouble();
+//CHECK: VarDecl {{.*}} Unique_Double
+//CHECK-NEXT: ConstantExpr {{.*}}
+//CHECK-NEXT: value: Float 5.678907e+05
+
+} // namespace FloatingPoint
+
+// FIXME: Add test for FixedPoint, ComplexInt, ComplexFloat, AddrLabelDiff.
+
+namespace Struct {
+
+struct B {
+ int i;
+ double d;
+};
+
+consteval B fB() {
+ return B{1, 0.7};
+}
+
+constexpr B Basic_Struct = fB();
+//CHECK: VarDecl {{.*}} Basic_Struct
+//CHECK-NEXT: value: Struct
+//CHECK-NEXT: fields: Int 1, Float 7.000000e-01
+//CHECK-NEXT: ImplicitCastExpr
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: Struct
+//CHECK-NEXT: fields: Int 1, Float 7.000000e-01
+
+struct C {
+ int i = 9;
+};
+
+struct A : B {
+ constexpr A(B b, int I, double D, C _c) : B(b), i(I), d(D), c(_c) {}
+ int i;
+ double d;
+ C c;
+};
+
+consteval A fA() {
+ return A(Basic_Struct, 1, 79.789, {});
+}
+
+A Advanced_Struct = fA();
+//CHECK: VarDecl {{.*}} Advanced_Struct
+//CHECK-NEXT: ConstantExpr {{.*}}
+//CHECK-NEXT: value: Struct
+//CHECK-NEXT: base: Struct
+//CHECK-NEXT: fields: Int 1, Float 7.000000e-01
+//CHECK-NEXT: fields: Int 1, Float 7.978900e+01
+//CHECK-NEXT: field: Struct
+//CHECK-NEXT: field: Int 9
+
+} // namespace Struct
+
+namespace Vector {
+
+using v4si = int __attribute__((__vector_size__(16)));
+
+consteval v4si fv4si() {
+ return (v4si){8, 2, 3};
+}
+
+v4si Vector_Int = fv4si();
+//CHECK: VarDecl {{.*}} Vector_Int
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: Vector length=4
+//CHECK-NEXT: elements: Int 8, Int 2, Int 3, Int 0
+
+} // namespace Vector
+
+namespace Array {
+
+struct B {
+ int arr[6];
+};
+
+consteval B fint() {
+ return B{1, 2, 3, 4, 5, 6};
+}
+
+B Array_Int = fint();
+//CHECK: VarDecl {{.*}} Array_Int
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: Struct
+//CHECK-NEXT: field: Array size=6
+//CHECK-NEXT: elements: Int 1, Int 2, Int 3, Int 4
+//CHECK-NEXT: elements: Int 5, Int 6
+
+struct A {
+ int i = 789;
+ double d = 67890.09876;
+};
+
+struct C {
+ A arr[3];
+};
+
+consteval C fA() {
+ return {{A{}, A{-45678, 9.8}, A{9}}};
+}
+
+C Array2_Struct = fA();
+//CHECK: VarDecl {{.*}} Array2_Struct
+//CHECK-NEXT: ConstantExpr {{.*}}
+
+using v4si = int __attribute__((__vector_size__(16)));
+
+struct D {
+ v4si arr[2];
+};
+
+consteval D fv4si() {
+ return {{{1, 2, 3, 4}, {4, 5, 6, 7}}};
+}
+
+D Array_Vector = fv4si();
+//CHECK: VarDecl {{.*}} Array_Vector
+//CHECK-NEXT: ConstantExpr {{.*}}
+//CHECK-NEXT: value: Struct
+//CHECK-NEXT: field: Array size=2
+//CHECK-NEXT: element: Vector length=4
+//CHECK-NEXT: elements: Int 1, Int 2, Int 3, Int 4
+//CHECK-NEXT: element: Vector length=4
+//CHECK-NEXT: elements: Int 4, Int 5, Int 6, Int 7
+
+} // namespace Array
+
+namespace Union {
+
+struct A {
+ int i = 6789;
+ float f = 987.9876;
+};
+
+union U {
+ int i;
+ A a{567890, 9876.5678f};
+};
+
+consteval U fU1() {
+ return U{0};
+}
+
+U Unique_Union1 = fU1();
+//CHECK: VarDecl {{.*}} Unique_Union
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: Union .i Int 0
+
+consteval U fU() {
+ return U{};
+}
+
+U Unique_Union2 = fU();
+//CHECK: VarDecl {{.*}} Unique_Union
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: Union .a
+//CHECK-NEXT: Struct
+//CHECK-NEXT: fields: Int 567890, Float 9.876567e+03
+
+} // namespace Union
+
+namespace MemberPointer {
+
+struct A {
+ struct B {
+ struct C {
+ struct D {
+ struct E {
+ struct F {
+ struct G {
+ int i;
+ };
+ };
+ };
+ };
+ };
+ };
+};
+
+consteval auto fmem_ptr() -> decltype(&A::B::C::D::E::F::G::i) {
+ return &A::B::C::D::E::F::G::i;
+}
+
+auto MemberPointer1 = fmem_ptr();
+//CHECK: VarDecl {{.*}} MemberPointer1
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: MemberPointer &G::i
+
+struct A1 {
+ struct B1 {
+ int f() const {
+ return 0;
+ }
+ };
+};
+
+consteval auto fmem_ptr2() {
+ return &A1::B1::f;
+}
+
+auto MemberPointer2 = fmem_ptr2();
+//CHECK: VarDecl {{.*}} MemberPointer2
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: MemberPointer &B1::f
+
+} // namespace MemberPointer
+
+namespace std {
+struct type_info;
+};
+
+namespace LValue {
+
+constexpr int g = 0;
+
+consteval const int &fg_ref() {
+ return g;
+}
+
+const int &g_ref = fg_ref();
+//CHECK: VarDecl {{.*}} g_ref
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: LValue &g
+
+consteval const int *fint_ptr() {
+ return &g;
+}
+
+const int *g_ptr = fint_ptr();
+//CHECK: VarDecl {{.*}} g_ptr
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: LValue &g
+
+consteval const int *fnull_ptr() {
+ return nullptr;
+}
+
+const int *ptr2 = fnull_ptr();
+//CHECK: VarDecl {{.*}} ptr2
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: LValue nullptr
+
+int fconst();
+
+consteval auto ffunc_ptr() {
+ return &fconst;
+}
+
+int (*func_ptr)() = ffunc_ptr();
+//CHECK: VarDecl {{.*}} func_ptr
+//CHECK-NEXT: ConstantExpr {{.*}}
+//CHECK-NEXT: value: LValue &fconst
+
+struct A {
+ int Arr[6] = {0, 1, 3, 4, 5, 9};
+ int i = 0;
+};
+
+struct D {
+ A arr[6] = {};
+};
+
+consteval D fA() {
+ return {};
+}
+
+constexpr D Arr = fA();
+// CHECK: VarDecl {{.*}} Arr
+// CHECK-NEXT: value: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+// CHECK-NEXT: element: Struct
+// CHECK-NEXT: field: Array size=6
+// CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+// CHECK-NEXT: elements: Int 5, Int 9
+// CHECK-NEXT: field: Int 0
+
+consteval const int &fconstintref() {
+ return Arr.arr[0].i;
+}
+
+const int &ArrayStructRef1 = fconstintref();
+//CHECK: VarDecl {{.*}} ArrayStructRef1
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: LValue &Arr.arr[0].i
+
+consteval const int &fconstintref2() {
+ return Arr.arr[1].Arr[5];
+}
+
+const int &ArrayStructRef2 = fconstintref2();
+//CHECK: VarDecl {{.*}} ArrayStructRef2
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: LValue &Arr.arr[1].Arr[5]
+
+consteval const int *fconststar() {
+ return &ArrayStructRef2;
+}
+
+const int *ArrayStructRef3 = fconststar();
+//CHECK: VarDecl {{.*}} ArrayStructRef3
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: LValue &Arr.arr[1].Arr[5]
+
+struct B : A {
+};
+
+struct C {
+ B b;
+};
+
+consteval C fC() {
+ return {};
+}
+
+C c = fC();
+//CHECK: VarDecl {{.*}} c
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: Struct
+//CHECK-NEXT: field: Struct
+//CHECK-NEXT: base: Struct
+//CHECK-NEXT: field: Array size=6
+//CHECK-NEXT: elements: Int 0, Int 1, Int 3, Int 4
+//CHECK-NEXT: elements: Int 5, Int 9
+//CHECK-NEXT: field: Int 0
+
+consteval const int &f2constintref() {
+ return c.b.i;
+}
+
+const int &StructPathRef = f2constintref();
+//CHECK: VarDecl {{.*}} StructPathRef
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: LValue &c.b.A::i
+
+consteval const std::type_info *ftype_info() {
+ return &typeid(c);
+}
+
+const std::type_info *T1 = ftype_info();
+//CHECK: VarDecl {{.*}} T1
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT:value: LValue &typeid(LValue::C)
+
+consteval const std::type_info *ftype_info2() {
+ return &typeid(Arr.arr[1].Arr[2]);
+}
+
+const std::type_info *T2 = ftype_info2();
+//CHECK: VarDecl {{.*}} T2
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: LValue &typeid(int)
+
+consteval const char *fstring() {
+ return "test";
+}
+
+const char *cptr = fstring();
+//CHECK: VarDecl {{.*}} cptr
+//CHECK-NEXT: ConstantExpr
+//CHECK-NEXT: value: LValue &"test"[0]
+
+} // namespace LValue
+
+#endif
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -5168,14 +5168,90 @@
AddAPFloat(Value.getComplexFloatImag());
return;
}
- case APValue::LValue:
case APValue::Vector:
+ push_back(Value.getVectorLength());
+ for (unsigned Idx = 0; Idx < Value.getVectorLength(); Idx++)
+ AddAPValue(Value.getVectorElt(Idx));
+ return;
case APValue::Array:
+ push_back(Value.getArrayInitializedElts());
+ push_back(Value.getArraySize());
+ for (unsigned Idx = 0; Idx < Value.getArrayInitializedElts(); Idx++)
+ AddAPValue(Value.getArrayInitializedElt(Idx));
+ return;
case APValue::Struct:
+ push_back(Value.getStructNumBases());
+ push_back(Value.getStructNumFields());
+ for (unsigned Idx = 0; Idx < Value.getStructNumBases(); Idx++)
+ AddAPValue(Value.getStructBase(Idx));
+ for (unsigned Idx = 0; Idx < Value.getStructNumFields(); Idx++)
+ AddAPValue(Value.getStructField(Idx));
+ return;
case APValue::Union:
- case APValue::MemberPointer:
+ AddDeclRef(Value.getUnionField());
+ AddAPValue(Value.getUnionValue());
+ return;
case APValue::AddrLabelDiff:
- // TODO : Handle all these APValue::ValueKind.
+ AddStmt(const_cast<AddrLabelExpr *>(Value.getAddrLabelDiffLHS()));
+ AddStmt(const_cast<AddrLabelExpr *>(Value.getAddrLabelDiffRHS()));
+ return;
+ case APValue::MemberPointer: {
+ push_back(Value.isMemberPointerToDerivedMember());
+ AddDeclRef(Value.getMemberPointerDecl());
+ ArrayRef<const CXXRecordDecl *> RecordPath = Value.getMemberPointerPath();
+ push_back(RecordPath.size());
+ for (auto Elem : RecordPath)
+ AddDeclRef(Elem);
+ return;
+ }
+ case APValue::LValue: {
+ push_back(Value.hasLValuePath() | Value.isLValueOnePastTheEnd() << 1 |
+ Value.getLValueBase().is<const Expr *>() << 2 |
+ Value.getLValueBase().is<TypeInfoLValue>() << 3 |
+ Value.isNullPointer() << 4 |
+ static_cast<bool>(Value.getLValueBase()) << 5);
+ QualType ElemTy;
+ if (Value.getLValueBase()) {
+ if (!Value.getLValueBase().is<TypeInfoLValue>()) {
+ push_back(Value.getLValueBase().getCallIndex());
+ push_back(Value.getLValueBase().getVersion());
+ if (const auto *E = Value.getLValueBase().dyn_cast<const Expr *>()) {
+ AddStmt(const_cast<Expr *>(E));
+ ElemTy = E->getType();
+ } else {
+ AddDeclRef(Value.getLValueBase().get<const ValueDecl *>());
+ ElemTy = Value.getLValueBase().get<const ValueDecl *>()->getType();
+ }
+ } else {
+ AddTypeRef(
+ QualType(Value.getLValueBase().get<TypeInfoLValue>().getType(), 0));
+ AddTypeRef(Value.getLValueBase().getTypeInfoType());
+ ElemTy = Value.getLValueBase().getTypeInfoType();
+ }
+ }
+ push_back(Value.getLValueOffset().getQuantity());
+ push_back(Value.getLValuePath().size());
+ if (Value.hasLValuePath()) {
+ ArrayRef<APValue::LValuePathEntry> Path = Value.getLValuePath();
+ for (auto Elem : Path) {
+ if (ElemTy->getAs<RecordType>()) {
+ push_back(Elem.getAsBaseOrMember().getInt());
+ const Decl *BaseOrMember = Elem.getAsBaseOrMember().getPointer();
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
+ AddDeclRef(RD);
+ ElemTy = Writer->Context->getRecordType(RD);
+ } else {
+ const auto *VD = cast<ValueDecl>(BaseOrMember);
+ AddDeclRef(VD);
+ ElemTy = VD->getType();
+ }
+ } else {
+ push_back(Elem.getAsArrayIndex());
+ ElemTy = Writer->Context->getAsArrayType(ElemTy)->getElementType();
+ }
+ }
+ }
+ }
return;
}
llvm_unreachable("Invalid APValue::ValueKind");
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -8940,61 +8940,152 @@
return SourceRange(beg, end);
}
-static FixedPointSemantics
-ReadFixedPointSemantics(const SmallVectorImpl<uint64_t> &Record,
- unsigned &Idx) {
- unsigned Width = Record[Idx++];
- unsigned Scale = Record[Idx++];
- uint64_t Tmp = Record[Idx++];
- bool IsSigned = Tmp & 0x1;
- bool IsSaturated = Tmp & 0x2;
- bool HasUnsignedPadding = Tmp & 0x4;
- return FixedPointSemantics(Width, Scale, IsSigned, IsSaturated,
- HasUnsignedPadding);
-}
-
-static const llvm::fltSemantics &
-readAPFloatSemantics(ASTRecordReader &reader) {
- return llvm::APFloatBase::EnumToSemantics(
- static_cast<llvm::APFloatBase::Semantics>(reader.readInt()));
-}
-
APValue ASTRecordReader::readAPValue() {
- unsigned Kind = readInt();
- switch ((APValue::ValueKind) Kind) {
+ auto Kind = static_cast<APValue::ValueKind>(asImpl().readUInt32());
+ switch (Kind) {
case APValue::None:
return APValue();
case APValue::Indeterminate:
return APValue::IndeterminateValue();
case APValue::Int:
- return APValue(readAPSInt());
+ return APValue(asImpl().readAPSInt());
case APValue::Float: {
- const llvm::fltSemantics &FloatSema = readAPFloatSemantics(*this);
- return APValue(readAPFloat(FloatSema));
+ const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics(
+ static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
+ return APValue(asImpl().readAPFloat(FloatSema));
}
case APValue::FixedPoint: {
- FixedPointSemantics FPSema = ReadFixedPointSemantics(Record, Idx);
- return APValue(APFixedPoint(readAPInt(), FPSema));
+ unsigned Width = asImpl().readUInt32();
+ unsigned Scale = asImpl().readUInt32();
+ unsigned Tmp = asImpl().readUInt32();
+ bool IsSigned = Tmp & 0x1;
+ bool IsSaturated = Tmp & 0x2;
+ bool HasUnsignedPadding = Tmp & 0x4;
+ FixedPointSemantics FPSema = FixedPointSemantics(
+ Width, Scale, IsSigned, IsSaturated, HasUnsignedPadding);
+ return APValue(APFixedPoint(asImpl().readAPInt(), FPSema));
}
case APValue::ComplexInt: {
- llvm::APSInt First = readAPSInt();
- return APValue(std::move(First), readAPSInt());
+ llvm::APSInt First = asImpl().readAPSInt();
+ return APValue(std::move(First), asImpl().readAPSInt());
}
case APValue::ComplexFloat: {
- const llvm::fltSemantics &FloatSema1 = readAPFloatSemantics(*this);
+ const llvm::fltSemantics &FloatSema1 = llvm::APFloatBase::EnumToSemantics(
+ static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
llvm::APFloat First = readAPFloat(FloatSema1);
- const llvm::fltSemantics &FloatSema2 = readAPFloatSemantics(*this);
- return APValue(std::move(First), readAPFloat(FloatSema2));
- }
- 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();
+ const llvm::fltSemantics &FloatSema2 = llvm::APFloatBase::EnumToSemantics(
+ static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
+ return APValue(std::move(First), asImpl().readAPFloat(FloatSema2));
+ }
+ case APValue::Vector: {
+ APValue Result;
+ Result.MakeVector();
+ unsigned Length = asImpl().readUInt32();
+ Result.ReserveVector(Length);
+ for (unsigned LoopIdx = 0; LoopIdx < Length; LoopIdx++)
+ Result.getVectorElt(LoopIdx) = asImpl().readAPValue();
+ return Result;
+ }
+ case APValue::Array: {
+ APValue Result;
+ unsigned InitLength = asImpl().readUInt32();
+ unsigned TotalLength = asImpl().readUInt32();
+ Result.MakeArray(InitLength, TotalLength);
+ for (unsigned LoopIdx = 0; LoopIdx < InitLength; LoopIdx++)
+ Result.getArrayInitializedElt(LoopIdx) = asImpl().readAPValue();
+ return Result;
+ }
+ case APValue::Struct: {
+ APValue Result;
+ unsigned BasesLength = asImpl().readUInt32();
+ unsigned FieldsLength = asImpl().readUInt32();
+ Result.MakeStruct(BasesLength, FieldsLength);
+ for (unsigned LoopIdx = 0; LoopIdx < BasesLength; LoopIdx++)
+ Result.getStructBase(LoopIdx) = asImpl().readAPValue();
+ for (unsigned LoopIdx = 0; LoopIdx < FieldsLength; LoopIdx++)
+ Result.getStructField(LoopIdx) = asImpl().readAPValue();
+ return Result;
+ }
+ case APValue::Union: {
+ auto *FDecl = asImpl().readDeclAs<FieldDecl>();
+ APValue Value = asImpl().readAPValue();
+ return APValue(FDecl, std::move(Value));
+ }
+ case APValue::AddrLabelDiff: {
+ auto *LHS = cast<AddrLabelExpr>(asImpl().readExpr());
+ auto *RHS = cast<AddrLabelExpr>(asImpl().readExpr());
+ return APValue(LHS, RHS);
+ }
+ case APValue::MemberPointer: {
+ APValue Result;
+ bool IsDerived = asImpl().readUInt32();
+ auto *Member = asImpl().readDeclAs<ValueDecl>();
+ unsigned PathSize = asImpl().readUInt32();
+ Result.MakeEmptyMemberPointer(Member, IsDerived, PathSize);
+ const CXXRecordDecl **PathArray = Result.GetInternalMemberPointerPathPtr();
+ for (unsigned LoopIdx = 0; LoopIdx < PathSize; LoopIdx++)
+ PathArray[LoopIdx] = asImpl().readDeclAs<const CXXRecordDecl>();
+ return Result;
+ }
+ case APValue::LValue: {
+ uint64_t Bits = asImpl().readUInt32();
+ bool HasLValuePath = Bits & 0x1;
+ bool IsLValueOnePastTheEnd = Bits & 0x2;
+ bool IsExpr = Bits & 0x4;
+ bool IsTypeInfo = Bits & 0x8;
+ bool IsNullPtr = Bits & 0x10;
+ bool HasBase = Bits & 0x20;
+ APValue::LValueBase Base;
+ QualType ElemTy;
+ assert((!IsExpr || !IsTypeInfo) && "LValueBase cannot be both");
+ if (HasBase) {
+ if (!IsTypeInfo) {
+ unsigned CallIndex = asImpl().readUInt32();
+ unsigned Version = asImpl().readUInt32();
+ if (IsExpr) {
+ Base = APValue::LValueBase(asImpl().readExpr(), CallIndex, Version);
+ ElemTy = Base.get<const Expr *>()->getType();
+ } else {
+ Base = APValue::LValueBase(asImpl().readDeclAs<const ValueDecl>(),
+ CallIndex, Version);
+ ElemTy = Base.get<const ValueDecl *>()->getType();
+ }
+ } else {
+ QualType TypeInfo = asImpl().readType();
+ QualType Type = asImpl().readType();
+ Base = APValue::LValueBase::getTypeInfo(
+ TypeInfoLValue(TypeInfo.getTypePtr()), Type);
+ Base.getTypeInfoType();
+ }
+ }
+ CharUnits Offset = CharUnits::fromQuantity(asImpl().readUInt32());
+ unsigned PathLength = asImpl().readUInt32();
+ APValue Result;
+ Result.MakeLValue();
+ if (HasLValuePath) {
+ Result.SetLValueEmptyPath(Base, Offset, PathLength, IsLValueOnePastTheEnd,
+ IsNullPtr);
+ APValue::LValuePathEntry *Path = Result.GetInternalLValuePathPtr();
+ for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) {
+ if (ElemTy->getAs<RecordType>()) {
+ unsigned Int = asImpl().readUInt32();
+ Decl *D = asImpl().readDeclAs<Decl>();
+ if (auto *RD = dyn_cast<CXXRecordDecl>(D))
+ ElemTy = getASTContext().getRecordType(RD);
+ else
+ ElemTy = cast<ValueDecl>(D)->getType();
+ Path[LoopIdx] =
+ APValue::LValuePathEntry(APValue::BaseOrMemberType(D, Int));
+ } else {
+ ElemTy = getASTContext().getAsArrayType(ElemTy)->getElementType();
+ Path[LoopIdx] =
+ APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32());
+ }
+ }
+ } else
+ Result.setLValue(Base, Offset, APValue::NoLValuePath{}, IsNullPtr);
+ return Result;
+ }
}
llvm_unreachable("Invalid APValue::ValueKind");
}
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -359,7 +359,6 @@
}
APValue ConstantExpr::getAPValueResult() const {
- assert(hasAPValueResult());
switch (ConstantExprBits.ResultKind) {
case ConstantExpr::RSK_APValue:
@@ -369,6 +368,8 @@
llvm::APSInt(llvm::APInt(ConstantExprBits.BitWidth, Int64Result()),
ConstantExprBits.IsUnsigned));
case ConstantExpr::RSK_None:
+ if (ConstantExprBits.APValueKind == APValue::Indeterminate)
+ return APValue::IndeterminateValue();
return APValue();
}
llvm_unreachable("invalid ResultKind");
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -6672,18 +6672,19 @@
ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) {
Error Err = Error::success();
auto ToSubExpr = importChecked(Err, E->getSubExpr());
+ auto ToResult = importChecked(Err, E->getAPValueResult());
if (Err)
return std::move(Err);
- // TODO : Handle APValue::ValueKind that require importing.
+ return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, ToResult);
- 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);
+ // 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);
}
ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
Error Err = Error::success();
@@ -8904,6 +8905,198 @@
return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data());
}
+llvm::Expected<APValue> ASTImporter::Import(const APValue &FromValue) {
+ APValue Result;
+ llvm::Error Error = llvm::Error::success();
+ auto ImportLoop = [&](const APValue *From, APValue *To, unsigned Size) {
+ for (unsigned Idx = 0; Idx < Size; Idx++) {
+ llvm::Expected<APValue> Tmp = Import(From[Idx]);
+ if (!Tmp) {
+ Error = Tmp.takeError();
+ return;
+ }
+ To[Idx] = std::move(Tmp.get());
+ }
+ };
+ switch (FromValue.getKind()) {
+ case APValue::None:
+ case APValue::Indeterminate:
+ case APValue::Int:
+ case APValue::Float:
+ case APValue::FixedPoint:
+ case APValue::ComplexInt:
+ case APValue::ComplexFloat:
+ Result = FromValue;
+ break;
+ case APValue::Vector:
+ Result.MakeVector();
+ Result.ReserveVector(FromValue.getVectorLength());
+ ImportLoop(
+ ((const APValue::Vec *)(const char *)FromValue.Data.buffer)->Elts,
+ ((const APValue::Vec *)(const char *)Result.Data.buffer)->Elts,
+ FromValue.getVectorLength());
+ break;
+ case APValue::Array:
+ Result.MakeArray(FromValue.getArrayInitializedElts(),
+ FromValue.getArraySize());
+ ImportLoop(
+ ((const APValue::Arr *)(const char *)FromValue.Data.buffer)->Elts,
+ ((const APValue::Arr *)(const char *)Result.Data.buffer)->Elts,
+ FromValue.getArrayInitializedElts());
+ break;
+ case APValue::Struct:
+ Result.MakeStruct(FromValue.getStructNumBases(),
+ FromValue.getStructNumFields());
+ ImportLoop(
+ ((const APValue::StructData *)(const char *)FromValue.Data.buffer)
+ ->Elts,
+ ((const APValue::StructData *)(const char *)Result.Data.buffer)->Elts,
+ FromValue.getStructNumBases() + FromValue.getStructNumFields());
+ break;
+ case APValue::Union: {
+ Result.MakeUnion();
+ llvm::Expected<const Decl *> ImpFDecl = Import(FromValue.getUnionField());
+ if (!ImpFDecl) {
+ Error = ImpFDecl.takeError();
+ break;
+ }
+ llvm::Expected<APValue> ImpValue = Import(FromValue.getUnionValue());
+ if (!ImpValue) {
+ Error = ImpValue.takeError();
+ break;
+ }
+ Result.setUnion(cast<FieldDecl>(ImpFDecl.get()), ImpValue.get());
+ break;
+ }
+ case APValue::AddrLabelDiff: {
+ Result.MakeAddrLabelDiff();
+ llvm::Expected<Expr *> ImpLHS =
+ Import(const_cast<AddrLabelExpr *>(FromValue.getAddrLabelDiffLHS()));
+ if (!ImpLHS) {
+ Error = ImpLHS.takeError();
+ break;
+ }
+ llvm::Expected<Expr *> ImpRHS =
+ Import(const_cast<AddrLabelExpr *>(FromValue.getAddrLabelDiffRHS()));
+ if (!ImpRHS) {
+ Error = ImpRHS.takeError();
+ break;
+ }
+ Result.setAddrLabelDiff(cast<AddrLabelExpr>(ImpLHS.get()),
+ cast<AddrLabelExpr>(ImpRHS.get()));
+ break;
+ }
+ case APValue::MemberPointer: {
+ llvm::Expected<const Decl *> ImpMemPtrDecl =
+ Import(FromValue.getMemberPointerDecl());
+ if (!ImpMemPtrDecl) {
+ Error = ImpMemPtrDecl.takeError();
+ break;
+ }
+ Result.MakeEmptyMemberPointer(cast<const ValueDecl>(ImpMemPtrDecl.get()),
+ FromValue.isMemberPointerToDerivedMember(),
+ FromValue.getMemberPointerPath().size());
+ llvm::ArrayRef<const CXXRecordDecl *> FromPath =
+ Result.getMemberPointerPath();
+ const CXXRecordDecl **ToPath = Result.GetInternalMemberPointerPathPtr();
+ for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size();
+ Idx++) {
+ llvm::Expected<const Decl *> ImpDecl = Import(FromPath[Idx]);
+ if (!ImpDecl) {
+ Error = ImpDecl.takeError();
+ break;
+ }
+ ToPath[Idx] =
+ cast<const CXXRecordDecl>(const_cast<Decl *>(ImpDecl.get()));
+ }
+ break;
+ }
+ case APValue::LValue:
+ APValue::LValueBase Base;
+ QualType FromElemTy;
+ if (FromValue.getLValueBase()) {
+ if (!FromValue.getLValueBase().is<TypeInfoLValue>()) {
+ if (auto *E = FromValue.getLValueBase().dyn_cast<const Expr *>()) {
+ FromElemTy = E->getType();
+ llvm::Expected<Expr *> ImpExpr = Import(const_cast<Expr *>(E));
+ if (!ImpExpr) {
+ Error = ImpExpr.takeError();
+ break;
+ }
+ Base = APValue::LValueBase(ImpExpr.get(),
+ FromValue.getLValueBase().getCallIndex(),
+ FromValue.getLValueBase().getVersion());
+ } else {
+ FromElemTy =
+ FromValue.getLValueBase().get<const ValueDecl *>()->getType();
+ llvm::Expected<const Decl *> ImpDecl =
+ Import(FromValue.getLValueBase().get<const ValueDecl *>());
+ if (!ImpDecl) {
+ Error = ImpDecl.takeError();
+ break;
+ }
+ Base = APValue::LValueBase(cast<ValueDecl>(ImpDecl.get()),
+ FromValue.getLValueBase().getCallIndex(),
+ FromValue.getLValueBase().getVersion());
+ }
+ } else {
+ FromElemTy = FromValue.getLValueBase().getTypeInfoType();
+ llvm::Expected<QualType> ImpTypeInfo = Import(QualType(
+ FromValue.getLValueBase().get<TypeInfoLValue>().getType(), 0));
+ if (!ImpTypeInfo) {
+ Error = ImpTypeInfo.takeError();
+ break;
+ }
+ llvm::Expected<QualType> ImpType =
+ Import(FromValue.getLValueBase().getTypeInfoType());
+ if (!ImpType) {
+ Error = ImpType.takeError();
+ break;
+ }
+ Base = APValue::LValueBase::getTypeInfo(
+ TypeInfoLValue(ImpTypeInfo.get().getTypePtr()), ImpType.get());
+ }
+ }
+ CharUnits Offset = FromValue.getLValueOffset();
+ unsigned PathLength = FromValue.getLValuePath().size();
+ Result.MakeLValue();
+ if (FromValue.hasLValuePath()) {
+ Result.SetLValueEmptyPath(Base, Offset, PathLength,
+ FromValue.isLValueOnePastTheEnd(),
+ FromValue.isNullPointer());
+ llvm::ArrayRef<APValue::LValuePathEntry> FromPath =
+ FromValue.getLValuePath();
+ APValue::LValuePathEntry *ToPath = Result.GetInternalLValuePathPtr();
+ for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) {
+ if (FromElemTy->getAs<RecordType>()) {
+ const Decl *FromDecl =
+ FromPath[LoopIdx].getAsBaseOrMember().getPointer();
+ llvm::Expected<const Decl *> ImpDecl = Import(FromDecl);
+ if (!ImpDecl) {
+ Error = ImpDecl.takeError();
+ break;
+ }
+ if (auto *RD = dyn_cast<CXXRecordDecl>(FromDecl))
+ FromElemTy = FromContext.getRecordType(RD);
+ else
+ FromElemTy = cast<ValueDecl>(FromDecl)->getType();
+ ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType(
+ ImpDecl.get(), FromPath[LoopIdx].getAsBaseOrMember().getInt()));
+ } else {
+ FromElemTy = FromContext.getAsArrayType(FromElemTy)->getElementType();
+ ToPath[LoopIdx] = APValue::LValuePathEntry::ArrayIndex(
+ FromPath[LoopIdx].getAsArrayIndex());
+ }
+ }
+ } else
+ Result.setLValue(Base, Offset, APValue::NoLValuePath{},
+ FromValue.isNullPointer());
+ }
+ if (Error)
+ return std::move(Error);
+ return Result;
+}
+
Expected<DeclarationName> ASTImporter::HandleNameConflict(DeclarationName Name,
DeclContext *DC,
unsigned IDNS,
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -1005,9 +1005,6 @@
for (const auto &Value : ModuleInitializers)
Value.second->~PerModuleInitializers();
-
- for (APValue *Value : APValueCleanups)
- Value->~APValue();
}
void ASTContext::setTraversalScope(const std::vector<Decl *> &TopLevelDecls) {
Index: clang/lib/AST/APValue.cpp
===================================================================
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -703,6 +703,10 @@
return ((const LV*)(const char*)Data.buffer)->IsNullPtr;
}
+APValue::LValuePathEntry *APValue::GetInternalLValuePathPtr() {
+ return ((LV *)(char *)Data.buffer)->getPath();
+}
+
void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
@@ -714,17 +718,24 @@
LVal.IsNullPtr = IsNullPtr;
}
-void APValue::setLValue(LValueBase B, const CharUnits &O,
- ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
- bool IsNullPtr) {
+void APValue::SetLValueEmptyPath(LValueBase B, const CharUnits &O,
+ unsigned Size, bool IsOnePastTheEnd,
+ bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
- LV &LVal = *((LV*)(char*)Data.buffer);
+ LV &LVal = *((LV *)(char *)Data.buffer);
LVal.Base = B;
LVal.IsOnePastTheEnd = IsOnePastTheEnd;
LVal.Offset = O;
- LVal.resizePath(Path.size());
- memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
LVal.IsNullPtr = IsNullPtr;
+ LVal.resizePath(Size);
+}
+
+void APValue::setLValue(LValueBase B, const CharUnits &O,
+ ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
+ bool IsNullPtr) {
+ SetLValueEmptyPath(B, O, Path.size(), IsOnePastTheEnd, IsNullPtr);
+ memcpy(((LV *)(char *)Data.buffer)->getPath(), Path.data(),
+ Path.size() * sizeof(LValuePathEntry));
}
const ValueDecl *APValue::getMemberPointerDecl() const {
@@ -761,13 +772,23 @@
Kind = Array;
}
-void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
- ArrayRef<const CXXRecordDecl*> Path) {
+void APValue::MakeEmptyMemberPointer(const ValueDecl *Member,
+ bool IsDerivedMember, unsigned Size) {
assert(isAbsent() && "Bad state change");
MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
Kind = MemberPointer;
MPD->MemberAndIsDerivedMember.setPointer(Member);
MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
- MPD->resizePath(Path.size());
- memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
+ MPD->resizePath(Size);
+}
+
+void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
+ ArrayRef<const CXXRecordDecl *> Path) {
+ MakeEmptyMemberPointer(Member, IsDerivedMember, Path.size());
+ memcpy(((MemberPointerData *)(char *)Data.buffer)->getPath(), Path.data(),
+ Path.size() * sizeof(const CXXRecordDecl *));
+}
+
+const CXXRecordDecl **APValue::GetInternalMemberPointerPathPtr() {
+ return ((MemberPointerData *)(char *)Data.buffer)->getPath();
}
Index: clang/include/clang/AST/ASTImporter.h
===================================================================
--- clang/include/clang/AST/ASTImporter.h
+++ clang/include/clang/AST/ASTImporter.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
#define LLVM_CLANG_AST_ASTIMPORTER_H
+#include "clang/AST/APValue.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExprCXX.h"
@@ -503,6 +504,13 @@
/// "to" context, or the import error.
llvm::Expected<CXXBaseSpecifier *> Import(const CXXBaseSpecifier *FromSpec);
+ /// Import the given APValue from the "from" context into
+ /// the "to" context.
+ ///
+ /// \return the equivalent APValue in the "to" context or the import
+ /// error.
+ llvm::Expected<APValue> Import(const APValue &FromValue);
+
/// Import the definition of the given declaration, including all of
/// the declarations it contains.
LLVM_NODISCARD llvm::Error ImportDefinition(Decl *From);
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -277,9 +277,6 @@
/// Mapping from GUIDs to the corresponding MSGuidDecl.
mutable llvm::FoldingSet<MSGuidDecl> MSGuidDecls;
- /// Used to cleanups APValues stored in the AST.
- mutable llvm::SmallVector<APValue *, 0> APValueCleanups;
-
/// A cache mapping a string value to a StringLiteral object with the same
/// value.
///
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits