CXType clang_Cursor_getTemplateArgumentType(CXCursor C, unsigned I) { TemplateArgument TA; if (clang_Cursor_getTemplateArgument(C, I, &TA) != CXGetTemplateArgumentStatus_Success) { return cxtype::MakeCXType(QualType(), getCursorTU(C)); } if (TA.getKind() != TemplateArgument::Type) { return cxtype::MakeCXType(QualType(), getCursorTU(C)); } return cxtype::MakeCXType(TA.getAsType(), getCursorTU(C)); }
void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { // Mostly repetitive with TemplateArgument::Profile! ID.AddInteger(Arg.getKind()); switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Type: VisitType(Arg.getAsType()); break; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); break; case TemplateArgument::Declaration: VisitDecl(Arg.getAsDecl()); break; case TemplateArgument::NullPtr: VisitType(Arg.getNullPtrType()); break; case TemplateArgument::Integral: Arg.getAsIntegral().Profile(ID); VisitType(Arg.getIntegralType()); break; case TemplateArgument::Expression: Visit(Arg.getAsExpr()); break; case TemplateArgument::Pack: for (const auto &P : Arg.pack_elements()) VisitTemplateArgument(P); break; } }
static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx, TemplateArgument &Arg) { bool Changed = false; // Note: we do not handle TemplateArgument::Expression, to replace it // we need the information for the template instance decl. if (Arg.getKind() == TemplateArgument::Template) { TemplateName TName = Arg.getAsTemplate(); Changed = getFullyQualifiedTemplateName(Ctx, TName); if (Changed) { Arg = TemplateArgument(TName); } } else if (Arg.getKind() == TemplateArgument::Type) { QualType SubTy = Arg.getAsType(); // Check if the type needs more desugaring and recurse. QualType QTFQ = getFullyQualifiedType(SubTy, Ctx); if (QTFQ != SubTy) { Arg = TemplateArgument(QTFQ); Changed = true; } } return Changed; }
void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { // Mostly repetitive with TemplateArgument::Profile! ID.AddInteger(Arg.getKind()); switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Type: VisitType(Arg.getAsType()); break; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); break; case TemplateArgument::Declaration: VisitDecl(Arg.getAsDecl()); break; case TemplateArgument::Integral: Arg.getAsIntegral()->Profile(ID); VisitType(Arg.getIntegralType()); break; case TemplateArgument::Expression: Visit(Arg.getAsExpr()); break; case TemplateArgument::Pack: const TemplateArgument *Pack = Arg.pack_begin(); for (unsigned i = 0, e = Arg.pack_size(); i != e; ++i) VisitTemplateArgument(Pack[i]); break; } }
long long clang_Cursor_getTemplateArgumentValue(CXCursor C, unsigned I) { TemplateArgument TA; if (clang_Cursor_getTemplateArgument(C, I, &TA) != CXGetTemplateArgumentStatus_Success) { assert(0 && "Unable to retrieve TemplateArgument"); return 0; } if (TA.getKind() != TemplateArgument::Integral) { assert(0 && "Passed template argument is not Integral"); return 0; } return TA.getAsIntegral().getSExtValue(); }
void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) { switch (Arg.getKind()) { default: break; case TemplateArgument::Type: assert(Arg.getAsType().isCanonical() && "Type must be canonical!"); break; } assert(NumFlatArgs < MaxFlatArgs && "Argument list builder is full!"); assert(!StructuredArgs && "Can't append arguments when an argument pack has been added!"); if (!FlatArgs) FlatArgs = new TemplateArgument[MaxFlatArgs]; FlatArgs[NumFlatArgs++] = Arg; }
void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) { IndentScope Indent(*this); OS << "TemplateArgument"; if (R.isValid()) dumpSourceRange(R); switch (A.getKind()) { case TemplateArgument::Null: OS << " null"; break; case TemplateArgument::Type: OS << " type"; dumpType(A.getAsType()); break; case TemplateArgument::Declaration: OS << " decl"; dumpDeclRef(A.getAsDecl()); break; case TemplateArgument::NullPtr: OS << " nullptr"; break; case TemplateArgument::Integral: OS << " integral " << A.getAsIntegral(); break; case TemplateArgument::Template: OS << " template "; A.getAsTemplate().dump(OS); break; case TemplateArgument::TemplateExpansion: OS << " template expansion"; A.getAsTemplateOrTemplatePattern().dump(OS); break; case TemplateArgument::Expression: OS << " expr"; dumpStmt(A.getAsExpr()); break; case TemplateArgument::Pack: OS << " pack"; for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end(); I != E; ++I) dumpTemplateArgument(*I); break; } }
// Get |count| number of template arguments. Returns false if there // are fewer than |count| arguments or any of the arguments are not // of a valid Type structure. If |count| is non-positive, all // arguments are collected. bool RecordInfo::GetTemplateArgs(size_t count, TemplateArgs* output_args) { ClassTemplateSpecializationDecl* tmpl = dyn_cast<ClassTemplateSpecializationDecl>(record_); if (!tmpl) return false; const TemplateArgumentList& args = tmpl->getTemplateArgs(); if (args.size() < count) return false; if (count <= 0) count = args.size(); for (unsigned i = 0; i < count; ++i) { TemplateArgument arg = args[i]; if (arg.getKind() == TemplateArgument::Type && !arg.getAsType().isNull()) { output_args->push_back(arg.getAsType().getTypePtr()); } else { return false; } } return true; }
void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Declaration: Visit(Arg.getAsDecl()); break; case TemplateArgument::NullPtr: break; case TemplateArgument::TemplateExpansion: Out << 'P'; // pack expansion of... // Fall through case TemplateArgument::Template: VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); break; case TemplateArgument::Expression: // FIXME: Visit expressions. break; case TemplateArgument::Pack: Out << 'p' << Arg.pack_size(); for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end(); P != PEnd; ++P) VisitTemplateArgument(*P); break; case TemplateArgument::Type: VisitType(Arg.getAsType()); break; case TemplateArgument::Integral: Out << 'V'; VisitType(Arg.getIntegralType()); Out << Arg.getAsIntegral(); break; } }
void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Declaration: Visit(Arg.getAsDecl()); break; case TemplateArgument::NullPtr: break; case TemplateArgument::TemplateExpansion: Out << 'P'; // pack expansion of... LLVM_FALLTHROUGH; case TemplateArgument::Template: VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); break; case TemplateArgument::Expression: // FIXME: Visit expressions. break; case TemplateArgument::Pack: Out << 'p' << Arg.pack_size(); for (const auto &P : Arg.pack_elements()) VisitTemplateArgument(P); break; case TemplateArgument::Type: VisitType(Arg.getAsType()); break; case TemplateArgument::Integral: Out << 'V'; VisitType(Arg.getIntegralType()); Out << Arg.getAsIntegral(); break; } }
enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C, unsigned I) { TemplateArgument TA; if (clang_Cursor_getTemplateArgument(C, I, &TA)) { return CXTemplateArgumentKind_Invalid; } switch (TA.getKind()) { case TemplateArgument::Null: return CXTemplateArgumentKind_Null; case TemplateArgument::Type: return CXTemplateArgumentKind_Type; case TemplateArgument::Declaration: return CXTemplateArgumentKind_Declaration; case TemplateArgument::NullPtr: return CXTemplateArgumentKind_NullPtr; case TemplateArgument::Integral: return CXTemplateArgumentKind_Integral; case TemplateArgument::Template: return CXTemplateArgumentKind_Template; case TemplateArgument::TemplateExpansion: return CXTemplateArgumentKind_TemplateExpansion; case TemplateArgument::Expression: return CXTemplateArgumentKind_Expression; case TemplateArgument::Pack: return CXTemplateArgumentKind_Pack; } return CXTemplateArgumentKind_Invalid; }
static void PrintTemplateArgument(std::string &Buffer, const TemplateArgument &Arg, const PrintingPolicy &Policy) { switch (Arg.getKind()) { case TemplateArgument::Null: assert(false && "Null template argument"); break; case TemplateArgument::Type: Arg.getAsType().getAsStringInternal(Buffer, Policy); break; case TemplateArgument::Declaration: Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); break; case TemplateArgument::Template: { llvm::raw_string_ostream s(Buffer); Arg.getAsTemplate().print(s, Policy); break; } case TemplateArgument::Integral: Buffer = Arg.getAsIntegral()->toString(10, true); break; case TemplateArgument::Expression: { llvm::raw_string_ostream s(Buffer); Arg.getAsExpr()->printPretty(s, 0, Policy); break; } case TemplateArgument::Pack: assert(0 && "FIXME: Implement!"); break; } }
void InstantiateTemplateParam::getForwardDeclStr( const Type *Ty, std::string &ForwardStr, RecordDeclSet &TempAvailableRecordDecls) { if (const RecordType *RT = Ty->getAsUnionType()) { const RecordDecl *RD = RT->getDecl(); addOneForwardDeclStr(RD, ForwardStr, TempAvailableRecordDecls); return; } const CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl(); if (!CXXRD) return; const ClassTemplateSpecializationDecl *SpecD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD); if (!SpecD) { addOneForwardDeclStr(CXXRD, ForwardStr, TempAvailableRecordDecls); return; } addForwardTemplateDeclStr(SpecD->getSpecializedTemplate(), ForwardStr, TempAvailableRecordDecls); const TemplateArgumentList &ArgList = SpecD->getTemplateArgs(); unsigned NumArgs = ArgList.size(); for (unsigned I = 0; I < NumArgs; ++I) { const TemplateArgument Arg = ArgList[I]; if (Arg.getKind() != TemplateArgument::Type) continue; getForwardDeclStr(Arg.getAsType().getTypePtr(), ForwardStr, TempAvailableRecordDecls); } }
string getTemplateArgumentName(const TemplateArgument & argument) { string qualifiedName; switch(argument.getKind()) { case TemplateArgument::Null: qualifiedName = "NULL"; break; case TemplateArgument::Type: qualifiedName = CppType(argument.getAsType()).getQualifiedName(); break; case TemplateArgument::Declaration: qualifiedName = dyn_cast<NamedDecl>(argument.getAsDecl())->getQualifiedNameAsString(); break; case TemplateArgument::Integral: case TemplateArgument::Expression: qualifiedName = exprToText(argument.getAsExpr()); break; case TemplateArgument::Template: qualifiedName = argument.getAsTemplate().getAsTemplateDecl()->getQualifiedNameAsString(); break; case TemplateArgument::TemplateExpansion: break; case TemplateArgument::Pack: break; } return qualifiedName; }
static Optional<QualType> TemplateArgumentToQualType(const TemplateArgument &A) { if (A.getKind() == TemplateArgument::Type) return A.getAsType(); return None; }
// This is a wrapper around NamedDecl::getQualifiedNameAsString. // It produces more qualified output to distinguish several cases // which would otherwise be ambiguous. std::string support::getQualifiedName(const clang::NamedDecl &d) { std::string ret; const DeclContext *ctx = d.getDeclContext(); if (ctx->isFunctionOrMethod() && isa<NamedDecl>(ctx)) { // This is a local variable. // d.getQualifiedNameAsString() will return the unqualifed name for this // but we want an actual qualified name so we can distinguish variables // with the same name but that are in different functions. ret = getQualifiedName(*cast<NamedDecl>(ctx)) + "::" + d.getNameAsString(); } else { ret = d.getQualifiedNameAsString(); } if (const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(&d)) { if (fd->isFunctionTemplateSpecialization()) { ret += "<"; const TemplateArgumentList *TemplateArgs = fd->getTemplateSpecializationArgs(); if (TemplateArgs) { unsigned num_args = TemplateArgs->size(); for (unsigned i = 0; i < num_args; ++i) { if (i) ret +=","; TemplateArgument TemplateArg = TemplateArgs->get(i); if (TemplateArg.getKind() == TemplateArgument::ArgKind::Type) ret += TemplateArg.getAsType().getAsString(); } } ret += ">"; } // This is a function. getQualifiedNameAsString will return a string // like "ANamespace::AFunction". To this we append the list of parameters // so that we can distinguish correctly between // void ANamespace::AFunction(int); // and // void ANamespace::AFunction(float); ret += "("; const FunctionType *ft = fd->getType()->castAs<FunctionType>(); if (const FunctionProtoType *fpt = dyn_cast_or_null<FunctionProtoType>(ft)) { unsigned num_params = fd->getNumParams(); for (unsigned i = 0; i < num_params; ++i) { if (i) ret += ", "; ret += fd->getParamDecl(i)->getType().getAsString(); } if (fpt->isVariadic()) { if (num_params > 0) ret += ", "; ret += "..."; } } ret += ")"; if (ft->isConst()) ret += " const"; } return ret; }
void ReduceClassTemplateParameter::removeOneParameterByArgType( const ClassTemplatePartialSpecializationDecl *PartialD, const TemplateArgument &Arg) { TransAssert((Arg.getKind() == TemplateArgument::Type) && "Arg is not TemplateArgument::Type!"); llvm::DenseMap<const Type *, unsigned> TypeToVisitsCount; llvm::DenseMap<const Type *, const NamedDecl *> TypeToNamedDecl; llvm::DenseMap<const Type *, unsigned> TypeToIndex; // retrieve all TemplateTypeParmType const TemplateParameterList *TPList = PartialD->getTemplateParameters(); unsigned Idx = 0; for (TemplateParameterList::const_iterator I = TPList->begin(), E = TPList->end(); I != E; ++I) { const NamedDecl *ND = (*I); const TemplateTypeParmDecl *TypeD = dyn_cast<TemplateTypeParmDecl>(ND); if (!TypeD) { Idx++; continue; } const Type *ParmTy = TypeD->getTypeForDecl(); TypeToVisitsCount[ParmTy] = 0; TypeToNamedDecl[ParmTy] = ND; TypeToIndex[ParmTy] = Idx; } QualType QTy = Arg.getAsType(); ArgumentDependencyVisitor V(TypeToVisitsCount); // collect TemplateTypeParmType being used by Arg V.TraverseType(QTy); llvm::DenseMap<const Type *, unsigned> DependentTypeToVisitsCount; for (llvm::DenseMap<const Type *, unsigned>::iterator I = TypeToVisitsCount.begin(), E = TypeToVisitsCount.end(); I != E; ++I) { if ((*I).second > 0) DependentTypeToVisitsCount[(*I).first] = 1; } // check if the used TemplateTypeParmType[s] have dependencies // on other Args. If yes, we cannot remove it from the parameter list. // For example: // template <typename T> // struct S <T*, T&> {}; // removing either of the arguments needs to keep the template // parameter ArgumentDependencyVisitor AccumV(DependentTypeToVisitsCount); const ASTTemplateArgumentListInfo *ArgList = PartialD->getTemplateArgsAsWritten(); const TemplateArgumentLoc *ArgLocs = ArgList->getTemplateArgs(); unsigned NumArgs = ArgList->NumTemplateArgs; TransAssert((TheParameterIndex < NumArgs) && "Bad NumArgs from partial template decl!"); for (unsigned I = 0; I < NumArgs; ++I) { if (I == TheParameterIndex) continue; const TemplateArgumentLoc ArgLoc = ArgLocs[I]; TemplateArgument OtherArg = ArgLoc.getArgument(); if (OtherArg.isInstantiationDependent() && (OtherArg.getKind() == TemplateArgument::Type)) { QualType QTy = OtherArg.getAsType(); AccumV.TraverseType(QTy); } } for (llvm::DenseMap<const Type *, unsigned>::iterator I = DependentTypeToVisitsCount.begin(), E = DependentTypeToVisitsCount.end(); I != E; ++I) { if ((*I).second != 1) continue; const NamedDecl *Param = TypeToNamedDecl[(*I).first]; TransAssert(Param && "NULL Parameter!"); SourceRange Range = Param->getSourceRange(); removeParameterByRange(Range, TPList, TypeToIndex[(*I).first]); } }
// Adapted from tools\clang\lib\AST\TemplateBase.cpp TemplateArgument::print void printTemplateArgument(raw_ostream &out, const PrintingPolicy &policy, TemplateArgument const &arg, bool qualifyNames) { switch (arg.getKind()) { case TemplateArgument::Null: out << "(no value)"; break; case TemplateArgument::Type: { PrintingPolicy SubPolicy(policy); SubPolicy.SuppressStrongLifetime = true; arg.getAsType().print(out, SubPolicy); break; } case TemplateArgument::Declaration: { NamedDecl *ND = cast<NamedDecl>(arg.getAsDecl()); out << '&'; if (ND->getDeclName()) { // FIXME: distinguish between pointer and reference args? ND->printQualifiedName(out); } else { out << "(anonymous)"; } break; } case TemplateArgument::NullPtr: out << "nullptr"; break; case TemplateArgument::Template: // Orig: arg.getAsTemplate().print(out, policy); { auto templateName = arg.getAsTemplate(); printTemplateName(out, policy, templateName, qualifyNames); break; } case TemplateArgument::TemplateExpansion: arg.getAsTemplateOrTemplatePattern().print(out, policy); out << "..."; break; case TemplateArgument::Integral: { printIntegral(arg, out, policy); break; } case TemplateArgument::Expression: arg.getAsExpr()->printPretty(out, nullptr, policy); break; case TemplateArgument::Pack: out << "<"; bool First = true; for (const auto &P : arg.pack_elements()) { if (First) First = false; else out << ", "; P.print(policy, out); } out << ">"; break; } }