std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx) { PrintingPolicy Policy(Ctx.getPrintingPolicy()); Policy.SuppressScope = false; Policy.AnonymousTagLocations = false; Policy.PolishForDeclaration = true; Policy.SuppressUnwrittenScope = true; QualType FQQT = getFullyQualifiedType(QT, Ctx); return FQQT.getAsString(Policy); }
void ClangInternalState::printAST(llvm::raw_ostream& Out, ASTContext& C) { TranslationUnitDecl* TU = C.getTranslationUnitDecl(); unsigned Indentation = 0; bool PrintInstantiation = false; std::string ErrMsg; clang::PrintingPolicy policy = C.getPrintingPolicy(); TU->print(Out, policy, Indentation, PrintInstantiation); // TODO: For future when we relpace the bump allocation with slab. // //Out << "Allocated memory: " << C.getAllocatedMemory(); //Out << "Side table allocated memory: " << C.getSideTableAllocatedMemory(); Out.flush(); }
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context, const Preprocessor &PP) { PrintingPolicy Policy = Context.getPrintingPolicy(); Policy.Bool = Context.getLangOpts().Bool; if (!Policy.Bool) { if (MacroInfo *BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) { Policy.Bool = BoolMacro->isObjectLike() && BoolMacro->getNumTokens() == 1 && BoolMacro->getReplacementToken(0).is(tok::kw__Bool); } } return Policy; }
SourceRange StackAddrEscapeChecker::genName(raw_ostream &os, const MemRegion *R, ASTContext &Ctx) { // Get the base region, stripping away fields and elements. R = R->getBaseRegion(); SourceManager &SM = Ctx.getSourceManager(); SourceRange range; os << "Address of "; // Check if the region is a compound literal. if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) { const CompoundLiteralExpr *CL = CR->getLiteralExpr(); os << "stack memory associated with a compound literal " "declared on line " << SM.getExpansionLineNumber(CL->getLocStart()) << " returned to caller"; range = CL->getSourceRange(); } else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) { const Expr *ARE = AR->getExpr(); SourceLocation L = ARE->getLocStart(); range = ARE->getSourceRange(); os << "stack memory allocated by call to alloca() on line " << SM.getExpansionLineNumber(L); } else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) { const BlockDecl *BD = BR->getCodeRegion()->getDecl(); SourceLocation L = BD->getLocStart(); range = BD->getSourceRange(); os << "stack-allocated block declared on line " << SM.getExpansionLineNumber(L); } else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { os << "stack memory associated with local variable '" << VR->getString() << '\''; range = VR->getDecl()->getSourceRange(); } else if (const CXXTempObjectRegion *TOR = dyn_cast<CXXTempObjectRegion>(R)) { QualType Ty = TOR->getValueType().getLocalUnqualifiedType(); os << "stack memory associated with temporary object of type '"; Ty.print(os, Ctx.getPrintingPolicy()); os << "'"; range = TOR->getExpr()->getSourceRange(); } else { llvm_unreachable("Invalid region in ReturnStackAddressChecker."); } return range; }
void TraverseTUnitConsumer::InvestigateASTContextTypes( ASTContext& context ) { // const SmallVectorImpl<Type *>& auto& types = context.getTypes(); TypePrinter printer(context.getPrintingPolicy(), /* indentation */ 2); const char *placeholder = ""; // "hey" for(const Type *type : types) { llvm::errs() << " - "; printer.print(type, Qualifiers(), llvm::errs(), placeholder); llvm::errs() << "\n"; } (terrs().magenta() << "InvestigateASTContextTypes(): END.\n").reset(); }
/// \brief Convert the given type to a string suitable for printing as part of /// a diagnostic. /// /// There are four main criteria when determining whether we should have an /// a.k.a. clause when pretty-printing a type: /// /// 1) Some types provide very minimal sugar that doesn't impede the /// user's understanding --- for example, elaborated type /// specifiers. If this is all the sugar we see, we don't want an /// a.k.a. clause. /// 2) Some types are technically sugared but are much more familiar /// when seen in their sugared form --- for example, va_list, /// vector types, and the magic Objective C types. We don't /// want to desugar these, even if we do produce an a.k.a. clause. /// 3) Some types may have already been desugared previously in this diagnostic. /// if this is the case, doing another "aka" would just be clutter. /// 4) Two different types within the same diagnostic have the same output /// string. In this case, force an a.k.a with the desugared type when /// doing so will provide additional information. /// /// \param Context the context in which the type was allocated /// \param Ty the type to print /// \param QualTypeVals pointer values to QualTypes which are used in the /// diagnostic message static std::string ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, const DiagnosticsEngine::ArgumentValue *PrevArgs, unsigned NumPrevArgs, ArrayRef<intptr_t> QualTypeVals) { // FIXME: Playing with std::string is really slow. bool ForceAKA = false; QualType CanTy = Ty.getCanonicalType(); std::string S = Ty.getAsString(Context.getPrintingPolicy()); std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) { QualType CompareTy = QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I])); if (CompareTy.isNull()) continue; if (CompareTy == Ty) continue; // Same types QualType CompareCanTy = CompareTy.getCanonicalType(); if (CompareCanTy == CanTy) continue; // Same canonical types std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy()); bool aka; QualType CompareDesugar = Desugar(Context, CompareTy, aka); std::string CompareDesugarStr = CompareDesugar.getAsString(Context.getPrintingPolicy()); if (CompareS != S && CompareDesugarStr != S) continue; // The type string is different than the comparison string // and the desugared comparison string. std::string CompareCanS = CompareCanTy.getAsString(Context.getPrintingPolicy()); if (CompareCanS == CanS) continue; // No new info from canonical type ForceAKA = true; break; } // Check to see if we already desugared this type in this // diagnostic. If so, don't do it again. bool Repeated = false; for (unsigned i = 0; i != NumPrevArgs; ++i) { // TODO: Handle ak_declcontext case. if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { void *Ptr = (void*)PrevArgs[i].second; QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); if (PrevTy == Ty) { Repeated = true; break; } } } // Consider producing an a.k.a. clause if removing all the direct // sugar gives us something "significantly different". if (!Repeated) { bool ShouldAKA = false; QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA); if (ShouldAKA || ForceAKA) { if (DesugaredTy == Ty) { DesugaredTy = Ty.getCanonicalType(); } std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy()); if (akaStr != S) { S = "'" + S + "' (aka '" + akaStr + "')"; return S; } } } S = "'" + S + "'"; return S; }
void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ switch (getKind()) { case APValue::Uninitialized: Out << "<uninitialized>"; return; case APValue::Int: if (Ty->isBooleanType()) Out << (getInt().getBoolValue() ? "true" : "false"); else Out << getInt(); return; case APValue::Float: Out << GetApproxValue(getFloat()); return; case APValue::Vector: { Out << '{'; QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); getVectorElt(0).printPretty(Out, Ctx, ElemTy); for (unsigned i = 1; i != getVectorLength(); ++i) { Out << ", "; getVectorElt(i).printPretty(Out, Ctx, ElemTy); } Out << '}'; return; } case APValue::ComplexInt: Out << getComplexIntReal() << "+" << getComplexIntImag() << "i"; return; case APValue::ComplexFloat: Out << GetApproxValue(getComplexFloatReal()) << "+" << GetApproxValue(getComplexFloatImag()) << "i"; return; case APValue::LValue: { LValueBase Base = getLValueBase(); if (!Base) { Out << "0"; return; } bool IsReference = Ty->isReferenceType(); QualType InnerTy = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); if (InnerTy.isNull()) InnerTy = Ty; if (!hasLValuePath()) { // No lvalue path: just print the offset. CharUnits O = getLValueOffset(); CharUnits S = Ctx.getTypeSizeInChars(InnerTy); if (!O.isZero()) { if (IsReference) Out << "*("; if (O % S) { Out << "(char*)"; S = CharUnits::One(); } Out << '&'; } else if (!IsReference) Out << '&'; if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) Out << *VD; else { assert(Base.get<const Expr *>() != nullptr && "Expecting non-null Expr"); Base.get<const Expr*>()->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); } if (!O.isZero()) { Out << " + " << (O / S); if (IsReference) Out << ')'; } return; } // We have an lvalue path. Print it out nicely. if (!IsReference) Out << '&'; else if (isLValueOnePastTheEnd()) Out << "*(&"; QualType ElemTy; if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { Out << *VD; ElemTy = VD->getType(); } else { const Expr *E = Base.get<const Expr*>(); assert(E != nullptr && "Expecting non-null Expr"); E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); ElemTy = E->getType(); } ArrayRef<LValuePathEntry> Path = getLValuePath(); const CXXRecordDecl *CastToBase = nullptr; for (unsigned I = 0, N = Path.size(); I != N; ++I) { if (ElemTy->getAs<RecordType>()) { // The lvalue refers to a class type, so the next path entry is a base // or member. const Decl *BaseOrMember = BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer(); if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) { CastToBase = RD; ElemTy = Ctx.getRecordType(RD); } else { const ValueDecl *VD = cast<ValueDecl>(BaseOrMember); Out << "."; if (CastToBase) Out << *CastToBase << "::"; Out << *VD; ElemTy = VD->getType(); } } else { // The lvalue must refer to an array. Out << '[' << Path[I].ArrayIndex << ']'; ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); } } // Handle formatting of one-past-the-end lvalues. if (isLValueOnePastTheEnd()) { // FIXME: If CastToBase is non-0, we should prefix the output with // "(CastToBase*)". Out << " + 1"; if (IsReference) Out << ')'; } return; } case APValue::Array: { const ArrayType *AT = Ctx.getAsArrayType(Ty); QualType ElemTy = AT->getElementType(); Out << '{'; if (unsigned N = getArrayInitializedElts()) { getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy); for (unsigned I = 1; I != N; ++I) { Out << ", "; if (I == 10) { // Avoid printing out the entire contents of large arrays. Out << "..."; break; } getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy); } } Out << '}'; return; } case APValue::Struct: { Out << '{'; const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); bool First = true; if (unsigned N = getStructNumBases()) { const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD); CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin(); for (unsigned I = 0; I != N; ++I, ++BI) { assert(BI != CD->bases_end()); if (!First) Out << ", "; getStructBase(I).printPretty(Out, Ctx, BI->getType()); First = false; } } for (const auto *FI : RD->fields()) { if (!First) Out << ", "; if (FI->isUnnamedBitfield()) continue; getStructField(FI->getFieldIndex()). printPretty(Out, Ctx, FI->getType()); First = false; } Out << '}'; return; } case APValue::Union: Out << '{'; if (const FieldDecl *FD = getUnionField()) { Out << "." << *FD << " = "; getUnionValue().printPretty(Out, Ctx, FD->getType()); } Out << '}'; return; case APValue::MemberPointer: // FIXME: This is not enough to unambiguously identify the member in a // multiple-inheritance scenario. if (const ValueDecl *VD = getMemberPointerDecl()) { Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD; return; } Out << "0"; return; case APValue::AddrLabelDiff: Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName(); Out << " - "; Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName(); return; } llvm_unreachable("Unknown APValue kind!"); }