diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -375,6 +375,7 @@ void dump(raw_ostream &OS, const ASTContext &Context) const; void printPretty(raw_ostream &OS, const 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() { diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -388,6 +388,11 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, QualType Ty) const { + printPretty(Out, &Ctx, Ty); +} + +void APValue::printPretty(raw_ostream &Out, const ASTContext *Ctx, + QualType Ty) const { switch (getKind()) { case APValue::None: Out << ""; @@ -426,6 +431,7 @@ << GetApproxValue(getComplexFloatImag()) << "i"; return; case APValue::LValue: { + assert(Ctx); bool IsReference = Ty->isReferenceType(); QualType InnerTy = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); @@ -435,12 +441,12 @@ LValueBase Base = getLValueBase(); if (!Base) { if (isNullPointer()) { - Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0"); + Out << (Ctx->getLangOpts().CPlusPlus11 ? "nullptr" : "0"); } else if (IsReference) { - Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)" + Out << "*(" << InnerTy.stream(Ctx->getPrintingPolicy()) << "*)" << getLValueOffset().getQuantity(); } else { - Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")" + Out << "(" << Ty.stream(Ctx->getPrintingPolicy()) << ")" << getLValueOffset().getQuantity(); } return; @@ -449,7 +455,7 @@ if (!hasLValuePath()) { // No lvalue path: just print the offset. CharUnits O = getLValueOffset(); - CharUnits S = Ctx.getTypeSizeInChars(InnerTy); + CharUnits S = Ctx->getTypeSizeInChars(InnerTy); if (!O.isZero()) { if (IsReference) Out << "*("; @@ -465,16 +471,16 @@ if (const ValueDecl *VD = Base.dyn_cast()) Out << *VD; else if (TypeInfoLValue TI = Base.dyn_cast()) { - TI.print(Out, Ctx.getPrintingPolicy()); + TI.print(Out, Ctx->getPrintingPolicy()); } else if (DynamicAllocLValue DA = Base.dyn_cast()) { Out << "{*new " - << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" - << DA.getIndex() << "}"; + << Base.getDynamicAllocType().stream(Ctx->getPrintingPolicy()) + << "#" << DA.getIndex() << "}"; } else { assert(Base.get() != nullptr && "Expecting non-null Expr"); - Base.get()->printPretty(Out, nullptr, - Ctx.getPrintingPolicy()); + Base.get()->printPretty(Out, nullptr, + Ctx->getPrintingPolicy()); } if (!O.isZero()) { @@ -496,17 +502,17 @@ Out << *VD; ElemTy = VD->getType(); } else if (TypeInfoLValue TI = Base.dyn_cast()) { - TI.print(Out, Ctx.getPrintingPolicy()); + TI.print(Out, Ctx->getPrintingPolicy()); ElemTy = Base.getTypeInfoType(); } else if (DynamicAllocLValue DA = Base.dyn_cast()) { Out << "{*new " - << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" + << Base.getDynamicAllocType().stream(Ctx->getPrintingPolicy()) << "#" << DA.getIndex() << "}"; ElemTy = Base.getDynamicAllocType(); } else { const Expr *E = Base.get(); assert(E != nullptr && "Expecting non-null Expr"); - E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); + E->printPretty(Out, nullptr, Ctx->getPrintingPolicy()); // FIXME: This is wrong if E is a MaterializeTemporaryExpr with an lvalue // adjustment. ElemTy = E->getType(); @@ -521,7 +527,7 @@ const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer(); if (const CXXRecordDecl *RD = dyn_cast(BaseOrMember)) { CastToBase = RD; - ElemTy = Ctx.getRecordType(RD); + ElemTy = Ctx->getRecordType(RD); } else { const ValueDecl *VD = cast(BaseOrMember); Out << "."; @@ -533,7 +539,7 @@ } else { // The lvalue must refer to an array. Out << '[' << Path[I].getAsArrayIndex() << ']'; - ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); + ElemTy = Ctx->getAsArrayType(ElemTy)->getElementType(); } } @@ -548,7 +554,8 @@ return; } case APValue::Array: { - const ArrayType *AT = Ctx.getAsArrayType(Ty); + assert(Ctx); + const ArrayType *AT = Ctx->getAsArrayType(Ty); QualType ElemTy = AT->getElementType(); Out << '{'; if (unsigned N = getArrayInitializedElts()) { diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -493,7 +493,11 @@ return; case APValue::LValue: (void)Context; - OS << "LValue "; + OS << "LValue "; + if (Context) + Value.printPretty(OS, Context, Ty); + else + OS << ""; return; case APValue::Array: { unsigned ArraySize = Value.getArraySize(); @@ -558,10 +562,12 @@ return; } case APValue::MemberPointer: - OS << "MemberPointer "; + OS << "MemberPointer "; + Value.printPretty(OS, Context, Ty); return; case APValue::AddrLabelDiff: - OS << "AddrLabelDiff "; + OS << "AddrLabelDiff "; + Value.printPretty(OS, Context, Ty); return; } llvm_unreachable("Unknown APValue kind!"); diff --git a/clang/test/AST/ast-dump-APValue-LValue.cpp b/clang/test/AST/ast-dump-APValue-LValue.cpp new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-APValue-LValue.cpp @@ -0,0 +1,12 @@ +// Test without serialization: +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \ +// RUN: -ast-dump %s -ast-dump-filter Test \ +// RUN: | FileCheck --strict-whitespace %s + +int i; + +void Test() { + constexpr int *pi = &i; + // CHECK: VarDecl {{.*}} col:{{.*}} pi 'int *const' constexpr cinit + // CHECK-NEXT: |-value: LValue &i +} diff --git a/clang/test/AST/ast-dump-APValue-MemPtr.cpp b/clang/test/AST/ast-dump-APValue-MemPtr.cpp new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-APValue-MemPtr.cpp @@ -0,0 +1,15 @@ +// Test without serialization: +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \ +// RUN: -ast-dump %s -ast-dump-filter Test \ +// RUN: | FileCheck --strict-whitespace %s + +int i; +struct S { + int i; +}; + +void Test() { + constexpr int(S::*pmi) = &S::i; + // CHECK: VarDecl {{.*}} col:{{.*}} pmi 'int (S::*const)' constexpr cinit + // CHECK-NEXT: value: MemberPointer &S::i +} diff --git a/clang/test/AST/ast-dump-APValue-todo.cpp b/clang/test/AST/ast-dump-APValue-todo.cpp deleted file mode 100644 --- a/clang/test/AST/ast-dump-APValue-todo.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Test without serialization: -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \ -// RUN: -ast-dump %s -ast-dump-filter Test \ -// RUN: | FileCheck --strict-whitespace --match-full-lines %s -// -// Test with serialization: -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 -emit-pch -o %t %s -// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \ -// RUN: -include-pch %t -ast-dump-all -ast-dump-filter Test /dev/null \ -// RUN: | sed -e "s/ //" -e "s/ imported//" \ -// RUN: | FileCheck --strict-whitespace --match-full-lines %s - -int i; -struct S { - int i; -}; - -void Test() { - constexpr int *pi = &i; - // CHECK: | `-VarDecl {{.*}} col:{{.*}} pi 'int *const' constexpr cinit - // CHECK-NEXT: | |-value: LValue - - constexpr int(S::*pmi) = &S::i; - // CHECK: `-VarDecl {{.*}} col:{{.*}} pmi 'int (S::*const)' constexpr cinit - // CHECK-NEXT: |-value: MemberPointer -}