diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 4c063ca00d7b42..d921a106b9f166 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -395,6 +395,9 @@ class APValue { 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 PrintingPolicy &Policy, QualType Ty, + const ASTContext *Ctx = nullptr) const; + std::string getAsString(const ASTContext &Ctx, QualType Ty) const; APSInt &getInt() { diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h index 616647f44430cd..dfd5851bb30d2e 100644 --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -56,8 +56,8 @@ struct PrintingPolicy { AnonymousTagLocations(true), SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), SuppressTemplateArgsInCXXConstructors(false), Bool(LO.Bool), - Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11), - UseVoidForZeroParams(!LO.CPlusPlus), + Nullptr(LO.CPlusPlus11), Restrict(LO.C99), Alignof(LO.CPlusPlus11), + UnderscoreAlignof(LO.C11), UseVoidForZeroParams(!LO.CPlusPlus), SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), @@ -171,6 +171,10 @@ struct PrintingPolicy { /// doesn't actually have 'bool', because, e.g., it is defined as a macro). unsigned Bool : 1; + /// Whether we should use 'nullptr' rather than '0' as a null pointer + /// constant. + unsigned Nullptr : 1; + /// Whether we can use 'restrict' rather than '__restrict'. unsigned Restrict : 1; diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 266421ce82e3b6..f8df221f570562 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -620,6 +620,11 @@ static double GetApproxValue(const llvm::APFloat &F) { void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, QualType Ty) const { + printPretty(Out, Ctx.getPrintingPolicy(), Ty, &Ctx); +} + +void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy, + QualType Ty, const ASTContext *Ctx) const { // There are no objects of type 'void', but values of this type can be // returned from functions. if (Ty->isVoidType()) { @@ -649,10 +654,10 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, case APValue::Vector: { Out << '{'; QualType ElemTy = Ty->castAs()->getElementType(); - getVectorElt(0).printPretty(Out, Ctx, ElemTy); + getVectorElt(0).printPretty(Out, Policy, ElemTy, Ctx); for (unsigned i = 1; i != getVectorLength(); ++i) { Out << ", "; - getVectorElt(i).printPretty(Out, Ctx, ElemTy); + getVectorElt(i).printPretty(Out, Policy, ElemTy, Ctx); } Out << '}'; return; @@ -674,12 +679,12 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, LValueBase Base = getLValueBase(); if (!Base) { if (isNullPointer()) { - Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0"); + Out << (Policy.Nullptr ? "nullptr" : "0"); } else if (IsReference) { - Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)" + Out << "*(" << InnerTy.stream(Policy) << "*)" << getLValueOffset().getQuantity(); } else { - Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")" + Out << "(" << Ty.stream(Policy) << ")" << getLValueOffset().getQuantity(); } return; @@ -688,11 +693,11 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, if (!hasLValuePath()) { // No lvalue path: just print the offset. CharUnits O = getLValueOffset(); - CharUnits S = Ctx.getTypeSizeInChars(InnerTy); + CharUnits S = Ctx ? Ctx->getTypeSizeInChars(InnerTy) : CharUnits::Zero(); if (!O.isZero()) { if (IsReference) Out << "*("; - if (O % S) { + if (S.isZero() || O % S) { Out << "(char*)"; S = CharUnits::One(); } @@ -704,16 +709,15 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, if (const ValueDecl *VD = Base.dyn_cast()) Out << *VD; else if (TypeInfoLValue TI = Base.dyn_cast()) { - TI.print(Out, Ctx.getPrintingPolicy()); + TI.print(Out, Policy); } else if (DynamicAllocLValue DA = Base.dyn_cast()) { Out << "{*new " - << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" + << Base.getDynamicAllocType().stream(Policy) << "#" << DA.getIndex() << "}"; } else { assert(Base.get() != nullptr && "Expecting non-null Expr"); - Base.get()->printPretty(Out, nullptr, - Ctx.getPrintingPolicy()); + Base.get()->printPretty(Out, nullptr, Policy); } if (!O.isZero()) { @@ -734,15 +738,14 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, if (const ValueDecl *VD = Base.dyn_cast()) { Out << *VD; } else if (TypeInfoLValue TI = Base.dyn_cast()) { - TI.print(Out, Ctx.getPrintingPolicy()); + TI.print(Out, Policy); } else if (DynamicAllocLValue DA = Base.dyn_cast()) { - Out << "{*new " - << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" + Out << "{*new " << Base.getDynamicAllocType().stream(Policy) << "#" << DA.getIndex() << "}"; } else { const Expr *E = Base.get(); assert(E != nullptr && "Expecting non-null Expr"); - E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); + E->printPretty(Out, nullptr, Policy); } ArrayRef Path = getLValuePath(); @@ -754,7 +757,8 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer(); if (const CXXRecordDecl *RD = dyn_cast(BaseOrMember)) { CastToBase = RD; - ElemTy = Ctx.getRecordType(RD); + // Leave ElemTy referring to the most-derived class. The actual type + // doesn't matter except for array types. } else { const ValueDecl *VD = cast(BaseOrMember); Out << "."; @@ -766,7 +770,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, } else { // The lvalue must refer to an array. Out << '[' << Path[I].getAsArrayIndex() << ']'; - ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); + ElemTy = ElemTy->castAsArrayTypeUnsafe()->getElementType(); } } @@ -781,11 +785,11 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, return; } case APValue::Array: { - const ArrayType *AT = Ctx.getAsArrayType(Ty); + const ArrayType *AT = Ty->castAsArrayTypeUnsafe(); QualType ElemTy = AT->getElementType(); Out << '{'; if (unsigned N = getArrayInitializedElts()) { - getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy); + getArrayInitializedElt(0).printPretty(Out, Policy, ElemTy, Ctx); for (unsigned I = 1; I != N; ++I) { Out << ", "; if (I == 10) { @@ -793,7 +797,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, Out << "..."; break; } - getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy); + getArrayInitializedElt(I).printPretty(Out, Policy, ElemTy, Ctx); } } Out << '}'; @@ -810,7 +814,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, assert(BI != CD->bases_end()); if (!First) Out << ", "; - getStructBase(I).printPretty(Out, Ctx, BI->getType()); + getStructBase(I).printPretty(Out, Policy, BI->getType(), Ctx); First = false; } } @@ -819,7 +823,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, Out << ", "; if (FI->isUnnamedBitfield()) continue; getStructField(FI->getFieldIndex()). - printPretty(Out, Ctx, FI->getType()); + printPretty(Out, Policy, FI->getType(), Ctx); First = false; } Out << '}'; @@ -829,7 +833,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, Out << '{'; if (const FieldDecl *FD = getUnionField()) { Out << "." << *FD << " = "; - getUnionValue().printPretty(Out, Ctx, FD->getType()); + getUnionValue().printPretty(Out, Policy, FD->getType(), Ctx); } Out << '}'; return;