// Returns true if |base| specifies one of the Chromium reference counted // classes (base::RefCounted / base::RefCountedThreadSafe). bool FindBadConstructsConsumer::IsRefCountedCallback( const CXXBaseSpecifier* base, CXXBasePath& path, void* user_data) { FindBadConstructsConsumer* self = static_cast<FindBadConstructsConsumer*>(user_data); const TemplateSpecializationType* base_type = dyn_cast<TemplateSpecializationType>( UnwrapType(base->getType().getTypePtr())); if (!base_type) { // Base-most definition is not a template, so this cannot derive from // base::RefCounted. However, it may still be possible to use with a // scoped_refptr<> and support ref-counting, so this is not a perfect // guarantee of safety. return false; } TemplateName name = base_type->getTemplateName(); if (TemplateDecl* decl = name.getAsTemplateDecl()) { std::string base_name = decl->getNameAsString(); // Check for both base::RefCounted and base::RefCountedThreadSafe. if (base_name.compare(0, 10, "RefCounted") == 0 && self->GetNamespace(decl) == "base") { return true; } } return false; }
bool RemoveNamespaceRewriteVisitor::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { const Type *Ty = D->getInjectedSpecializationType().getTypePtr(); TransAssert(Ty && "Bad TypePtr!"); 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(); TransAssert(ND && "Invalid NamedDecl!"); const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ND); TransAssert(CXXRD && "Invalid CXXRecordDecl!"); std::string Name; if (ConsumerInstance->getNewName(CXXRD, Name)) { const TypeSourceInfo *TyInfo = D->getTypeAsWritten(); if (!TyInfo) return true; TypeLoc TyLoc = TyInfo->getTypeLoc(); SourceLocation LocStart = TyLoc.getBeginLoc(); TransAssert(LocStart.isValid() && "Invalid Location!"); ConsumerInstance->TheRewriter.ReplaceText( LocStart, CXXRD->getNameAsString().size(), Name); } return true; }
void ReduceClassTemplateParameter::removeOneParameterByArgTemplate( const ClassTemplatePartialSpecializationDecl *PartialD, const TemplateArgument &Arg) { TransAssert((Arg.getKind() == TemplateArgument::Template) && "Arg is not TemplateArgument::Template!"); TemplateName TmplName = Arg.getAsTemplate(); TransAssert((TmplName.getKind() == TemplateName::Template) && "Invalid TemplateName Kind!"); const TemplateDecl *TmplD = TmplName.getAsTemplateDecl(); const TemplateParameterList *TPList = PartialD->getTemplateParameters(); unsigned Idx = 0; for (TemplateParameterList::const_iterator I = TPList->begin(), E = TPList->end(); I != E; ++I) { if ((*I) == TmplD) break; Idx++; } unsigned NumParams = TPList->size(); TransAssert((Idx < NumParams) && "Cannot find valid TemplateParameter!"); (void)NumParams; SourceRange Range = TmplD->getSourceRange(); removeParameterByRange(Range, TPList, Idx); return; }
static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, TemplateName &TName) { bool Changed = false; NestedNameSpecifier *NNS = nullptr; TemplateDecl *ArgTDecl = TName.getAsTemplateDecl(); // ArgTDecl won't be NULL because we asserted that this isn't a // dependent context very early in the call chain. assert(ArgTDecl != nullptr); QualifiedTemplateName *QTName = TName.getAsQualifiedTemplateName(); if (QTName && !QTName->hasTemplateKeyword()) { NNS = QTName->getQualifier(); NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier(Ctx, NNS); if (QNNS != NNS) { Changed = true; NNS = QNNS; } else { NNS = nullptr; } } else { NNS = createNestedNameSpecifierForScopeOf(Ctx, ArgTDecl, true); } if (NNS) { TName = Ctx.getQualifiedTemplateName(NNS, /*TemplateKeyword=*/false, ArgTDecl); Changed = true; } return Changed; }
void FindBadConstructsConsumer::CountType(const Type* type, int* trivial_member, int* non_trivial_member, int* templated_non_trivial_member) { switch (type->getTypeClass()) { case Type::Record: { // Simplifying; the whole class isn't trivial if the dtor is, but // we use this as a signal about complexity. if (TypeHasNonTrivialDtor(type)) (*trivial_member)++; else (*non_trivial_member)++; break; } case Type::TemplateSpecialization: { TemplateName name = dyn_cast<TemplateSpecializationType>(type)->getTemplateName(); bool whitelisted_template = false; // HACK: I'm at a loss about how to get the syntax checker to get // whether a template is exterened or not. For the first pass here, // just do retarded string comparisons. if (TemplateDecl* decl = name.getAsTemplateDecl()) { std::string base_name = decl->getNameAsString(); if (base_name == "basic_string") whitelisted_template = true; } if (whitelisted_template) (*non_trivial_member)++; else (*templated_non_trivial_member)++; break; } case Type::Elaborated: { CountType(dyn_cast<ElaboratedType>(type)->getNamedType().getTypePtr(), trivial_member, non_trivial_member, templated_non_trivial_member); break; } case Type::Typedef: { while (const TypedefType* TT = dyn_cast<TypedefType>(type)) { type = TT->getDecl()->getUnderlyingType().getTypePtr(); } CountType(type, trivial_member, non_trivial_member, templated_non_trivial_member); break; } default: { // Stupid assumption: anything we see that isn't the above is one of // the 20 integer types. (*trivial_member)++; break; } } }
CXCursor cxcursor::MakeCursorOverloadedDeclRef(TemplateName Name, SourceLocation Loc, CXTranslationUnit TU) { assert(Name.getAsOverloadedTemplate() && TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); OverloadedDeclRefStorage Storage(Name.getAsOverloadedTemplate()); CXCursor C = { CXCursor_OverloadedDeclRef, 0, { Storage.getOpaqueValue(), RawLoc, TU } }; return C; }
void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const { ID.AddInteger(getKind()); switch (getKind()) { case Null: break; case Type: getAsType().Profile(ID); break; case NullPtr: getNullPtrType().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); } }
bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, TemplateName Template, UnexpandedParameterPackContext UPPC) { if (Template.isNull() || !Template.containsUnexpandedParameterPack()) return false; SmallVector<UnexpandedParameterPack, 2> Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseTemplateName(Template); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); }
static bool IsSmallVector(QualType T) { const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>(); if (!TS) return false; TemplateName TM = TS->getTemplateName(); TemplateDecl *TD = TM.getAsTemplateDecl(); if (!TD || !InLLVMNamespace(TD)) return false; return TD->getName() == "SmallVector"; }
void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, unsigned NumArgs, const TemplateArgument *Args, TemplateArgumentLocInfo *ArgInfos, SourceLocation Loc) { for (unsigned i = 0, e = NumArgs; i != e; ++i) { switch (Args[i].getKind()) { case TemplateArgument::Null: llvm_unreachable("Impossible TemplateArgument"); case TemplateArgument::Integral: case TemplateArgument::Declaration: case TemplateArgument::NullPtr: ArgInfos[i] = TemplateArgumentLocInfo(); break; case TemplateArgument::Expression: ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr()); break; case TemplateArgument::Type: ArgInfos[i] = TemplateArgumentLocInfo( Context.getTrivialTypeSourceInfo(Args[i].getAsType(), Loc)); break; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: { NestedNameSpecifierLocBuilder Builder; TemplateName Template = Args[i].getAsTemplateOrTemplatePattern(); if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); ArgInfos[i] = TemplateArgumentLocInfo( Builder.getWithLocInContext(Context), Loc, Args[i].getKind() == TemplateArgument::Template ? SourceLocation() : Loc); break; } case TemplateArgument::Pack: ArgInfos[i] = TemplateArgumentLocInfo(); break; } } }
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); }
void printTemplateName(raw_ostream &OS, const PrintingPolicy &policy, TemplateName const &name, bool qualifyNames = false) { if (auto Template = name.getAsTemplateDecl()) OS << (qualifyNames ? Template->getQualifiedNameAsString() : Template->getNameAsString()); else if (auto QTN = name.getAsQualifiedTemplateName()) { OS << (qualifyNames ? QTN->getDecl()->getQualifiedNameAsString() : QTN->getDecl()->getNameAsString()); } else if (auto DTN = name.getAsDependentTemplateName()) { if (qualifyNames && DTN->getQualifier()) DTN->getQualifier()->print(OS, policy); OS << "template "; if (DTN->isIdentifier()) OS << DTN->getIdentifier()->getName(); else OS << "operator " << getOperatorSpelling(DTN->getOperator()); } else if (auto subst = name.getAsSubstTemplateTemplateParm()) { subst->getReplacement().print(OS, policy, !qualifyNames); } else if (auto SubstPack = name.getAsSubstTemplateTemplateParmPack()) OS << *SubstPack->getParameterPack(); else { auto OTS = name.getAsOverloadedTemplate(); (*OTS->begin())->printName(OS); } }
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; }
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 SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, TemplateTemplateParmDecl *parameter, TemplateName replacement) { ID.AddPointer(parameter); ID.AddPointer(replacement.getAsVoidPointer()); }
void StmtProfiler::VisitTemplateName(TemplateName Name) { if (Canonical) Name = Context.getCanonicalTemplateName(Name); Name.Profile(ID); }
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; }