static void printCXXConstructorDestructorName(QualType ClassType, raw_ostream &OS, const PrintingPolicy &Policy) { if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) { OS << *ClassRec->getDecl(); return; } if (!Policy.LangOpts.CPlusPlus) { // Passed policy is the default one from operator <<, use a C++ policy. LangOptions LO; LO.CPlusPlus = true; ClassType.print(OS, PrintingPolicy(LO)); } else { ClassType.print(OS, Policy); } }
void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) { // Normally, a PackExpansionType is written as T[3]... (for instance, as a // template argument), but if it is the type of a declaration, the ellipsis // is placed before the name being declared. if (auto *PET = T->getAs<PackExpansionType>()) { Pack = true; T = PET->getPattern(); } T.print(Out, Policy, (Pack ? "..." : "") + DeclName, Indentation); }
void Expr::print(StringBuilder& buffer, unsigned indent) const { QualType Q = getType(); Q.print(buffer); buffer.setColor(COL_ATTR); buffer << " ctc=" << ctc_strings[StmtBits.ExprIsCTC]; buffer << ", constant=" << isConstant(); if (getImpCast() != BuiltinType::Void) { buffer << ", cast=" << BuiltinType::kind2name(getImpCast()); } }
void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { if (!Policy.SuppressSpecifiers) { Out << "typedef "; if (D->isModulePrivate()) Out << "__module_private__ "; } QualType Ty = D->getTypeSourceInfo()->getType(); Ty.print(Out, Policy, D->getName(), Indentation); prettyPrintAttributes(D); }
CXString clang_getTypeSpelling(CXType CT) { QualType T = GetQualType(CT); if (T.isNull()) return cxstring::createEmpty(); CXTranslationUnit TU = GetTU(CT); SmallString<64> Str; llvm::raw_svector_ostream OS(Str); PrintingPolicy PP(cxtu::getASTUnit(TU)->getASTContext().getLangOpts()); T.print(OS, PP); return cxstring::createDup(OS.str()); }
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 VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const { if (!BT) { BT.reset(new APIMisuse(this, "Arguments passed to variadic method aren't all " "Objective-C pointer types")); ASTContext &Ctx = C.getASTContext(); arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx); dictionaryWithObjectsAndKeysS = GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx); setWithObjectsS = GetUnarySelector("setWithObjects", Ctx); orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx); initWithObjectsS = GetUnarySelector("initWithObjects", Ctx); initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx); } if (!isVariadicMessage(msg)) return; // We are not interested in the selector arguments since they have // well-defined types, so the compiler will issue a warning for them. unsigned variadicArgsBegin = msg.getSelector().getNumArgs(); // We're not interested in the last argument since it has to be nil or the // compiler would have issued a warning for it elsewhere. unsigned variadicArgsEnd = msg.getNumArgs() - 1; if (variadicArgsEnd <= variadicArgsBegin) return; // Verify that all arguments have Objective-C types. Optional<ExplodedNode*> errorNode; for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) { QualType ArgTy = msg.getArgExpr(I)->getType(); if (ArgTy->isObjCObjectPointerType()) continue; // Block pointers are treaded as Objective-C pointers. if (ArgTy->isBlockPointerType()) continue; // Ignore pointer constants. if (msg.getArgSVal(I).getAs<loc::ConcreteInt>()) continue; // Ignore pointer types annotated with 'NSObject' attribute. if (C.getASTContext().isObjCNSObjectType(ArgTy)) continue; // Ignore CF references, which can be toll-free bridged. if (coreFoundation::isCFObjectRef(ArgTy)) continue; // Generate only one error node to use for all bug reports. if (!errorNode.hasValue()) errorNode = C.generateNonFatalErrorNode(); if (!errorNode.getValue()) continue; SmallString<128> sbuf; llvm::raw_svector_ostream os(sbuf); StringRef TypeName = GetReceiverInterfaceName(msg); if (!TypeName.empty()) os << "Argument to '" << TypeName << "' method '"; else os << "Argument to method '"; msg.getSelector().print(os); os << "' should be an Objective-C pointer type, not '"; ArgTy.print(os, C.getLangOpts()); os << "'"; auto R = llvm::make_unique<BugReport>(*BT, os.str(), errorNode.getValue()); R->addRange(msg.getArgSourceRange(I)); C.emitReport(std::move(R)); } }
void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { DeclarationName &N = *this; switch (N.getNameKind()) { case DeclarationName::Identifier: if (const IdentifierInfo *II = N.getAsIdentifierInfo()) OS << II->getName(); return; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: N.getObjCSelector().print(OS); return; case DeclarationName::CXXConstructorName: return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); case DeclarationName::CXXDestructorName: { OS << '~'; return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); } case DeclarationName::CXXOperatorName: { static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = { nullptr, #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ Spelling, #include "clang/Basic/OperatorKinds.def" }; const char *OpName = OperatorNames[N.getCXXOverloadedOperator()]; assert(OpName && "not an overloaded operator"); OS << "operator"; if (OpName[0] >= 'a' && OpName[0] <= 'z') OS << ' '; OS << OpName; return; } case DeclarationName::CXXLiteralOperatorName: OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName(); return; case DeclarationName::CXXConversionFunctionName: { OS << "operator "; QualType Type = N.getCXXNameType(); if (const RecordType *Rec = Type->getAs<RecordType>()) { OS << *Rec->getDecl(); return; } if (!Policy.LangOpts.CPlusPlus) { // Passed policy is the default one from operator <<, use a C++ policy. LangOptions LO; LO.CPlusPlus = true; LO.Bool = true; Type.print(OS, PrintingPolicy(LO)); } else { Type.print(OS, Policy); } return; } case DeclarationName::CXXUsingDirective: OS << "<using-directive>"; return; } llvm_unreachable("Unexpected declaration name kind"); }
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (!D->getDescribedFunctionTemplate() && !D->isFunctionTemplateSpecialization()) prettyPrintPragmas(D); if (D->isFunctionTemplateSpecialization()) Out << "template<> "; CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); if (!Policy.SuppressSpecifiers) { switch (D->getStorageClass()) { case SC_None: break; case SC_Extern: Out << "extern "; break; case SC_Static: Out << "static "; break; case SC_PrivateExtern: Out << "__private_extern__ "; break; case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions"); } if (D->isInlineSpecified()) Out << "inline "; if (D->isVirtualAsWritten()) Out << "virtual "; if (D->isModulePrivate()) Out << "__module_private__ "; if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr "; if ((CDecl && CDecl->isExplicitSpecified()) || (ConversionDecl && ConversionDecl->isExplicit())) Out << "explicit "; } PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; std::string Proto = D->getNameInfo().getAsString(); if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { llvm::raw_string_ostream POut(Proto); DeclPrinter TArgPrinter(POut, SubPolicy, Indentation); TArgPrinter.printTemplateArguments(*TArgs); } QualType Ty = D->getType(); while (const ParenType *PT = dyn_cast<ParenType>(Ty)) { Proto = '(' + Proto + ')'; Ty = PT->getInnerType(); } prettyPrintAttributes(D); if (const FunctionType *AFT = Ty->getAs<FunctionType>()) { const FunctionProtoType *FT = nullptr; if (D->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(AFT); Proto += "("; if (FT) { llvm::raw_string_ostream POut(Proto); DeclPrinter ParamPrinter(POut, SubPolicy, Indentation); for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { if (i) POut << ", "; ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); } if (FT->isVariadic()) { if (D->getNumParams()) POut << ", "; POut << "..."; } } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { if (i) Proto += ", "; Proto += D->getParamDecl(i)->getNameAsString(); } } Proto += ")"; if (FT) { if (FT->isConst()) Proto += " const"; if (FT->isVolatile()) Proto += " volatile"; if (FT->isRestrict()) Proto += " restrict"; switch (FT->getRefQualifier()) { case RQ_None: break; case RQ_LValue: Proto += " &"; break; case RQ_RValue: Proto += " &&"; break; } } if (FT && FT->hasDynamicExceptionSpec()) { Proto += " throw("; if (FT->getExceptionSpecType() == EST_MSAny) Proto += "..."; else for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { if (I) Proto += ", "; Proto += FT->getExceptionType(I).getAsString(SubPolicy); } Proto += ")"; } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) { Proto += " noexcept"; if (FT->getExceptionSpecType() == EST_ComputedNoexcept) { Proto += "("; llvm::raw_string_ostream EOut(Proto); FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy, Indentation); EOut.flush(); Proto += EOut.str(); Proto += ")"; } } if (CDecl) { bool HasInitializerList = false; for (const auto *BMInitializer : CDecl->inits()) { if (BMInitializer->isInClassMemberInitializer()) continue; if (!HasInitializerList) { Proto += " : "; Out << Proto; Proto.clear(); HasInitializerList = true; } else Out << ", "; if (BMInitializer->isAnyMemberInitializer()) { FieldDecl *FD = BMInitializer->getAnyMember(); Out << *FD; } else { Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); } Out << "("; if (!BMInitializer->getInit()) { // Nothing to print } else { Expr *Init = BMInitializer->getInit(); if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) Init = Tmp->getSubExpr(); Init = Init->IgnoreParens(); Expr *SimpleInit = nullptr; Expr **Args = nullptr; unsigned NumArgs = 0; if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { Args = ParenList->getExprs(); NumArgs = ParenList->getNumExprs(); } else if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) { Args = Construct->getArgs(); NumArgs = Construct->getNumArgs(); } else SimpleInit = Init; if (SimpleInit) SimpleInit->printPretty(Out, nullptr, Policy, Indentation); else { for (unsigned I = 0; I != NumArgs; ++I) { assert(Args[I] != nullptr && "Expected non-null Expr"); if (isa<CXXDefaultArgExpr>(Args[I])) break; if (I) Out << ", "; Args[I]->printPretty(Out, nullptr, Policy, Indentation); } } } Out << ")"; if (BMInitializer->isPackExpansion()) Out << "..."; } } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) { if (FT && FT->hasTrailingReturn()) { Out << "auto " << Proto << " -> "; Proto.clear(); } AFT->getReturnType().print(Out, Policy, Proto); Proto.clear(); } Out << Proto; } else { Ty.print(Out, Policy, Proto); } if (D->isPure()) Out << " = 0"; else if (D->isDeletedAsWritten()) Out << " = delete"; else if (D->isExplicitlyDefaulted()) Out << " = default"; else if (D->doesThisDeclarationHaveABody()) { if (!Policy.TerseOutput) { if (!D->hasPrototype() && D->getNumParams()) { // This is a K&R function definition, so we need to print the // parameters. Out << '\n'; DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); Indentation += Policy.Indentation; for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { Indent(); ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); Out << ";\n"; } Indentation -= Policy.Indentation; } else Out << ' '; if (D->getBody()) D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation); } else { if (isa<CXXConstructorDecl>(*D)) Out << " {}"; } } }