static bool IsStdVector(QualType T) { const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>(); if (!TS) return false; TemplateName TM = TS->getTemplateName(); TemplateDecl *TD = TM.getAsTemplateDecl(); if (!TD || !InNamespace(TD, "std")) return false; return TD->getName() == "vector"; }
void USRGenerator::VisitTemplateName(TemplateName Name) { if (TemplateDecl *Template = Name.getAsTemplateDecl()) { if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) { Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); return; } Visit(Template); return; } // FIXME: Visit dependent template names. }
void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const { ID.AddInteger(Kind); switch (Kind) { case Null: break; case Type: getAsType().Profile(ID); break; case Declaration: ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); break; case Template: case TemplateExpansion: { TemplateName Template = getAsTemplateOrTemplatePattern(); if (TemplateTemplateParmDecl *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>( Template.getAsTemplateDecl())) { ID.AddBoolean(true); ID.AddInteger(TTP->getDepth()); ID.AddInteger(TTP->getPosition()); ID.AddBoolean(TTP->isParameterPack()); } else { ID.AddBoolean(false); ID.AddPointer(Context.getCanonicalTemplateName(Template) .getAsVoidPointer()); } break; } case Integral: getAsIntegral().Profile(ID); getIntegralType().Profile(ID); break; case Expression: getAsExpr()->Profile(ID, Context, true); break; case Pack: ID.AddInteger(Args.NumArgs); for (unsigned I = 0; I != Args.NumArgs; ++I) Args.Args[I].Profile(ID, Context); } }
void ODRHash::AddTemplateName(TemplateName Name) { auto Kind = Name.getKind(); ID.AddInteger(Kind); switch (Kind) { case TemplateName::Template: AddDecl(Name.getAsTemplateDecl()); break; // TODO: Support these cases. case TemplateName::OverloadedTemplate: case TemplateName::QualifiedTemplate: case TemplateName::DependentTemplate: case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: break; } }
void TemplateArgToInt::handleTemplateSpecializationTypeLoc( const TemplateSpecializationTypeLoc &TLoc) { const Type *Ty = TLoc.getTypePtr(); const TemplateSpecializationType *TST = Ty->getAs<TemplateSpecializationType>(); TemplateName TplName = TST->getTemplateName(); const TemplateDecl *TplD = TplName.getAsTemplateDecl(); TemplateParameterIdxSet *InvalidIdx = DeclToParamIdx[dyn_cast<TemplateDecl>(TplD->getCanonicalDecl())]; if (!InvalidIdx) return; for (unsigned I = 0; I < TLoc.getNumArgs(); ++I) { if (!InvalidIdx->count(I)) handleOneTemplateArgumentLoc(TLoc.getArgLoc(I)); } }
const NamedDecl *ReduceClassTemplateParameter::getNamedDecl( const TemplateArgument &Arg) { if (!Arg.isInstantiationDependent()) return NULL; TemplateArgument::ArgKind K = Arg.getKind(); switch (K) { case TemplateArgument::Expression: { const Expr *E = Arg.getAsExpr(); if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()); } else { return NULL; } } case TemplateArgument::Template: { TemplateName TmplName = Arg.getAsTemplate(); TransAssert((TmplName.getKind() == TemplateName::Template) && "Invalid TemplateName Kind!"); return TmplName.getAsTemplateDecl(); } case TemplateArgument::Type: { const Type *Ty = Arg.getAsType().getTypePtr(); if (const TemplateTypeParmType *TmplTy = dyn_cast<TemplateTypeParmType>(Ty)) { return TmplTy->getDecl(); } else { return NULL; } } default: return NULL; } TransAssert(0 && "Unreachable code!"); return NULL; }
bool CXXRecordDecl::FindOrdinaryMemberInDependentClasses( const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name) { const TemplateSpecializationType *TST = Specifier->getType()->getAs<TemplateSpecializationType>(); if (!TST) { auto *RT = Specifier->getType()->getAs<RecordType>(); if (!RT) return false; return findOrdinaryMember(RT->getDecl(), Path, Name); } TemplateName TN = TST->getTemplateName(); const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()); if (!TD) return false; CXXRecordDecl *RD = TD->getTemplatedDecl(); if (!RD) return false; return findOrdinaryMember(RD, Path, Name); }
bool RemoveNamespaceRewriteVisitor::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TSPLoc) { const Type *Ty = TSPLoc.getTypePtr(); const TemplateSpecializationType *TST = dyn_cast<TemplateSpecializationType>(Ty); TransAssert(TST && "Bad TemplateSpecializationType!"); TemplateName TplName = TST->getTemplateName(); const TemplateDecl *TplD = TplName.getAsTemplateDecl(); TransAssert(TplD && "Invalid TemplateDecl!"); NamedDecl *ND = TplD->getTemplatedDecl(); // in some cases, ND could be NULL, e.g., the // template template parameter code below: // template<template<class> class BBB> // struct AAA { // template <class T> // struct CCC { // static BBB<T> a; // }; // }; // where we don't know BBB if (!ND) return true; const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ND); if (!CXXRD) return true; std::string Name; if (ConsumerInstance->getNewName(CXXRD, Name)) { SourceLocation LocStart = TSPLoc.getTemplateNameLoc(); ConsumerInstance->TheRewriter.ReplaceText( LocStart, CXXRD->getNameAsString().size(), Name); } return true; }
bool CXXBasePaths::lookupInBases(ASTContext &Context, const CXXRecordDecl *Record, CXXRecordDecl::BaseMatchesCallback BaseMatches, bool LookupInDependent) { bool FoundPath = false; // The access of the path down to this record. AccessSpecifier AccessToHere = ScratchPath.Access; bool IsFirstStep = ScratchPath.empty(); for (const auto &BaseSpec : Record->bases()) { // Find the record of the base class subobjects for this type. QualType BaseType = Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType(); // C++ [temp.dep]p3: // In the definition of a class template or a member of a class template, // if a base class of the class template depends on a template-parameter, // the base class scope is not examined during unqualified name lookup // either at the point of definition of the class template or member or // during an instantiation of the class tem- plate or member. if (!LookupInDependent && BaseType->isDependentType()) continue; // Determine whether we need to visit this base class at all, // updating the count of subobjects appropriately. std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType]; bool VisitBase = true; bool SetVirtual = false; if (BaseSpec.isVirtual()) { VisitBase = !Subobjects.first; Subobjects.first = true; if (isDetectingVirtual() && DetectedVirtual == nullptr) { // If this is the first virtual we find, remember it. If it turns out // there is no base path here, we'll reset it later. DetectedVirtual = BaseType->getAs<RecordType>(); SetVirtual = true; } } else ++Subobjects.second; if (isRecordingPaths()) { // Add this base specifier to the current path. CXXBasePathElement Element; Element.Base = &BaseSpec; Element.Class = Record; if (BaseSpec.isVirtual()) Element.SubobjectNumber = 0; else Element.SubobjectNumber = Subobjects.second; ScratchPath.push_back(Element); // Calculate the "top-down" access to this base class. // The spec actually describes this bottom-up, but top-down is // equivalent because the definition works out as follows: // 1. Write down the access along each step in the inheritance // chain, followed by the access of the decl itself. // For example, in // class A { public: int foo; }; // class B : protected A {}; // class C : public B {}; // class D : private C {}; // we would write: // private public protected public // 2. If 'private' appears anywhere except far-left, access is denied. // 3. Otherwise, overall access is determined by the most restrictive // access in the sequence. if (IsFirstStep) ScratchPath.Access = BaseSpec.getAccessSpecifier(); else ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere, BaseSpec.getAccessSpecifier()); } // Track whether there's a path involving this specific base. bool FoundPathThroughBase = false; if (BaseMatches(&BaseSpec, ScratchPath)) { // We've found a path that terminates at this base. FoundPath = FoundPathThroughBase = true; if (isRecordingPaths()) { // We have a path. Make a copy of it before moving on. Paths.push_back(ScratchPath); } else if (!isFindingAmbiguities()) { // We found a path and we don't care about ambiguities; // return immediately. return FoundPath; } } else if (VisitBase) { CXXRecordDecl *BaseRecord; if (LookupInDependent) { BaseRecord = nullptr; const TemplateSpecializationType *TST = BaseSpec.getType()->getAs<TemplateSpecializationType>(); if (!TST) { if (auto *RT = BaseSpec.getType()->getAs<RecordType>()) BaseRecord = cast<CXXRecordDecl>(RT->getDecl()); } else { TemplateName TN = TST->getTemplateName(); if (auto *TD = dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) BaseRecord = TD->getTemplatedDecl(); } if (BaseRecord) { if (!BaseRecord->hasDefinition() || VisitedDependentRecords.count(BaseRecord)) { BaseRecord = nullptr; } else { VisitedDependentRecords.insert(BaseRecord); } } } else { BaseRecord = cast<CXXRecordDecl>( BaseSpec.getType()->castAs<RecordType>()->getDecl()); } if (BaseRecord && lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) { // C++ [class.member.lookup]p2: // A member name f in one sub-object B hides a member name f in // a sub-object A if A is a base class sub-object of B. Any // declarations that are so hidden are eliminated from // consideration. // There is a path to a base class that meets the criteria. If we're // not collecting paths or finding ambiguities, we're done. FoundPath = FoundPathThroughBase = true; if (!isFindingAmbiguities()) return FoundPath; } } // Pop this base specifier off the current path (if we're // collecting paths). if (isRecordingPaths()) { ScratchPath.pop_back(); } // If we set a virtual earlier, and this isn't a path, forget it again. if (SetVirtual && !FoundPathThroughBase) { DetectedVirtual = nullptr; } } // Reset the scratch path access. ScratchPath.Access = AccessToHere; return FoundPath; }