static bool isEnumRawType(const Decl* D, TypeLoc TL) { assert (TL.getType()); if (auto ED = dyn_cast<EnumDecl>(D)) { return ED->hasRawType() && ED->getRawType()->isEqual(TL.getType()); } return false; }
TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern( TemplateArgumentLoc OrigLoc, SourceLocation &Ellipsis, Optional<unsigned> &NumExpansions) const { const TemplateArgument &Argument = OrigLoc.getArgument(); assert(Argument.isPackExpansion()); switch (Argument.getKind()) { case TemplateArgument::Type: { // FIXME: We shouldn't ever have to worry about missing // type-source info! TypeSourceInfo *ExpansionTSInfo = OrigLoc.getTypeSourceInfo(); if (!ExpansionTSInfo) ExpansionTSInfo = Context.getTrivialTypeSourceInfo(Argument.getAsType(), Ellipsis); PackExpansionTypeLoc Expansion = ExpansionTSInfo->getTypeLoc().castAs<PackExpansionTypeLoc>(); Ellipsis = Expansion.getEllipsisLoc(); TypeLoc Pattern = Expansion.getPatternLoc(); NumExpansions = Expansion.getTypePtr()->getNumExpansions(); // We need to copy the TypeLoc because TemplateArgumentLocs store a // TypeSourceInfo. // FIXME: Find some way to avoid the copy? TypeLocBuilder TLB; TLB.pushFullCopy(Pattern); TypeSourceInfo *PatternTSInfo = TLB.getTypeSourceInfo(Context, Pattern.getType()); return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), PatternTSInfo); } case TemplateArgument::Expression: { PackExpansionExpr *Expansion = cast<PackExpansionExpr>(Argument.getAsExpr()); Expr *Pattern = Expansion->getPattern(); Ellipsis = Expansion->getEllipsisLoc(); NumExpansions = Expansion->getNumExpansions(); return TemplateArgumentLoc(Pattern, Pattern); } case TemplateArgument::TemplateExpansion: Ellipsis = OrigLoc.getTemplateEllipsisLoc(); NumExpansions = Argument.getNumTemplateExpansions(); return TemplateArgumentLoc(Argument.getPackExpansionPattern(), OrigLoc.getTemplateQualifierLoc(), OrigLoc.getTemplateNameLoc()); case TemplateArgument::Declaration: case TemplateArgument::NullPtr: case TemplateArgument::Template: case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: return TemplateArgumentLoc(); } llvm_unreachable("Invalid TemplateArgument Kind!"); }
static bool extendedTypeIsPrivate(TypeLoc inheritedType) { if (!inheritedType.getType()) return true; SmallVector<ProtocolDecl *, 2> protocols; if (!inheritedType.getType()->isAnyExistentialType(protocols)) { // Be conservative. We don't know how to deal with other extended types. return false; } return std::all_of(protocols.begin(), protocols.end(), declIsPrivate); }
bool IndexSwiftASTWalker::passRelatedType(const TypeLoc &Ty) { if (IdentTypeRepr *T = dyn_cast_or_null<IdentTypeRepr>(Ty.getTypeRepr())) { auto Comps = T->getComponentRange(); if (auto NTD = dyn_cast_or_null<NominalTypeDecl>( Comps.back()->getBoundDecl())) { if (!passRelated(NTD, Comps.back()->getIdLoc())) return false; } return true; } if (Ty.getType()) { if (auto nominal = dyn_cast_or_null<NominalTypeDecl>( Ty.getType()->getDirectlyReferencedTypeDecl())) if (!passRelated(nominal, Ty.getLoc())) return false; } return true; }
/// \brief If the new variable name conflicts with any type used in the loop, /// then we mark that variable name as taken. bool DeclFinderASTVisitor::VisitTypeLoc(TypeLoc TL) { QualType QType = TL.getType(); // Check if our name conflicts with a type, to handle for typedefs. if (QType.getAsString() == Name) { Found = true; return false; } // Check for base type conflicts. For example, when a struct is being // referenced in the body of the loop, the above getAsString() will return the // whole type (ex. "struct s"), but will be caught here. if (const IdentifierInfo *Ident = QType.getBaseTypeIdentifier()) { if (Ident->getName() == Name) { Found = true; return false; } } return true; }
static bool extendedTypeIsPrivate(TypeLoc inheritedType) { auto type = inheritedType.getType(); if (!type) return true; if (!type->isExistentialType()) { // Be conservative. We don't know how to deal with other extended types. return false; } auto layout = type->getExistentialLayout(); assert(!layout.superclass && "Should not have a subclass existential " "in the inheritance clause of an extension"); for (auto protoTy : layout.getProtocols()) { if (!declIsPrivate(protoTy->getDecl())) return false; } return true; }
void IterativeTypeChecker::processResolveInheritedClauseEntry( TypeCheckRequest::InheritedClauseEntryPayloadType payload, UnsatisfiedDependency unsatisfiedDependency) { TypeResolutionOptions options; DeclContext *dc; TypeLoc *inherited; std::tie(options, dc, inherited) = decomposeInheritedClauseEntry(payload); // FIXME: Declaration validation is overkill. Sink it down into type // resolution when it is actually needed. if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) TC.validateDeclForNameLookup(nominal); else if (auto ext = dyn_cast<ExtensionDecl>(dc)) { TC.validateExtension(ext); } // Validate the type of this inherited clause entry. // FIXME: Recursion into existing type checker. ProtocolRequirementTypeResolver protoResolver; GenericTypeToArchetypeResolver archetypeResolver(dc); GenericTypeResolver *resolver; if (isa<ProtocolDecl>(dc)) { resolver = &protoResolver; } else { resolver = &archetypeResolver; } if (TC.validateType(*inherited, dc, options, resolver, &unsatisfiedDependency)) { inherited->setInvalidType(getASTContext()); } auto type = inherited->getType(); if (!type.isNull() && !isa<ProtocolDecl>(dc)) inherited->setType(type->mapTypeOutOfContext()); }
/// \brief Determines if the given type loc corresponds to a /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in /// the type hierarchy, this is made somewhat complicated. /// /// There are a lot of types that currently use TypeSpecTypeLoc /// because it's a convenient base class. Ideally we would not accept /// those here, but ideally we would have better implementations for /// them. bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) { if (TL.getType().hasLocalQualifiers()) return false; return TSTChecker().Visit(TL); }
bool VisitTypeLoc(TypeLoc TypeLocation) { Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc()); return true; }
void TypeRenameTransform::processTypeLoc(TypeLoc TL, bool forceRewriteMacro) { if (TL.isNull()) { return; } auto BL = TL.getBeginLoc(); // ignore system headers if (shouldIgnore(BL)) { return; } // is a result from macro expansion? sorry... if (BL.isMacroID() && !forceRewriteMacro) { llvm::errs() << "Cannot rename type from macro expansion at: " << loc(BL) << "\n"; return; } // TODO: Take care of spelling loc finesses // BL = sema->getSourceManager().getSpellingLoc(BL); pushIndent(); auto QT = TL.getType(); // llvm::errs() << indent() // << "TypeLoc" // << ", typeLocClass: " << typeLocClassName(TL.getTypeLocClass()) // << "\n" << indent() << "qualType as str: " << QT.getAsString() // << "\n" << indent() << "beginLoc: " << loc(TL.getBeginLoc()) // << "\n"; switch(TL.getTypeLocClass()) { case TypeLoc::FunctionProto: { if (auto FTL = dyn_cast<FunctionTypeLoc>(&TL)) { for (unsigned I = 0, E = FTL->getNumArgs(); I != E; ++I) { processParmVarDecl(FTL->getArg(I)); } } break; } // an elaborated type loc captures the "prefix" of a type // for example, the elaborated type loc of "A::B::C" is A::B // we need to know if A::B and A are types we are renaming // (so that we can handle nested classes, in-class typedefs, etc.) case TypeLoc::Elaborated: { if (auto ETL = dyn_cast<ElaboratedTypeLoc>(&TL)) { processQualifierLoc(ETL->getQualifierLoc(), forceRewriteMacro); } break; } case TypeLoc::ObjCObject: { if (auto OT = dyn_cast<ObjCObjectTypeLoc>(&TL)) { for (unsigned I = 0, E = OT->getNumProtocols(); I != E; ++I) { if (auto P = OT->getProtocol(I)) { std::string newName; if (nameMatches(P, newName, true)) { renameLocation(OT->getProtocolLoc(I), newName); } } } } break; } case TypeLoc::InjectedClassName: { if (auto TSTL = dyn_cast<InjectedClassNameTypeLoc>(&TL)) { auto CD = TSTL->getDecl(); std::string newName; if (nameMatches(CD, newName, true)) { renameLocation(BL, newName); } } break; } case TypeLoc::TemplateSpecialization: { if (auto TSTL = dyn_cast<TemplateSpecializationTypeLoc>(&TL)) { // See if it's the template name that needs renaming auto T = TL.getTypePtr(); if (auto TT = dyn_cast<TemplateSpecializationType>(T)) { auto TN = TT->getTemplateName(); auto TD = TN.getAsTemplateDecl(); auto TTD = TD->getTemplatedDecl(); std::string newName; if (nameMatches(TTD, newName, true)) { renameLocation(TSTL->getTemplateNameLoc(), newName); } } // iterate through the args for (unsigned I = 0, E = TSTL->getNumArgs(); I != E; ++I) { // need to see if the template argument is also a type // (we skip things like Foo<1> ) auto AL = TSTL->getArgLoc(I); auto A = AL.getArgument(); if (A.getKind() != TemplateArgument::Type) { continue; } if (auto TSI = AL.getTypeSourceInfo()) { processTypeLoc(TSI->getTypeLoc(), forceRewriteMacro); } } } break; } // typedef is tricky case TypeLoc::Typedef: { auto T = TL.getTypePtr(); if (auto TDT = dyn_cast<TypedefType>(T)) { auto TDD = TDT->getDecl(); std::string newName; if (nameMatches(TDD, newName, true)) { renameLocation(BL, newName); } } break; } // leaf types // TODO: verify correctness, need test cases for each // TODO: Check if Builtin works case TypeLoc::Builtin: case TypeLoc::Enum: case TypeLoc::Record: case TypeLoc::ObjCInterface: case TypeLoc::TemplateTypeParm: { // skip if it's an anonymous type // read Clang`s definition (in RecordDecl) -- not exactly what you think // so we use the length of name std::string newName; if (auto TT = dyn_cast<TagType>(TL.getTypePtr())) { auto TD = TT->getDecl(); if (nameMatches(TD, newName, true)) { renameLocation(BL, newName); } } else { if (stringMatches(QT.getAsString(), newName)) { renameLocation(BL, newName); } } break; } default: break; } processTypeLoc(TL.getNextTypeLoc(), forceRewriteMacro); popIndent(); }
TemplateArgumentLoc TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, llvm::Optional<unsigned> &NumExpansions, ASTContext &Context) const { assert(Argument.isPackExpansion()); switch (Argument.getKind()) { case TemplateArgument::Type: { // FIXME: We shouldn't ever have to worry about missing // type-source info! TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo(); if (!ExpansionTSInfo) ExpansionTSInfo = Context.getTrivialTypeSourceInfo( getArgument().getAsType(), Ellipsis); PackExpansionTypeLoc Expansion = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); Ellipsis = Expansion.getEllipsisLoc(); TypeLoc Pattern = Expansion.getPatternLoc(); NumExpansions = Expansion.getTypePtr()->getNumExpansions(); // FIXME: This is horrible. We know where the source location data is for // the pattern, and we have the pattern's type, but we are forced to copy // them into an ASTContext because TypeSourceInfo bundles them together // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. TypeSourceInfo *PatternTSInfo = Context.CreateTypeSourceInfo(Pattern.getType(), Pattern.getFullDataSize()); memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), Pattern.getOpaqueData(), Pattern.getFullDataSize()); return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), PatternTSInfo); } case TemplateArgument::Expression: { PackExpansionExpr *Expansion = cast<PackExpansionExpr>(Argument.getAsExpr()); Expr *Pattern = Expansion->getPattern(); Ellipsis = Expansion->getEllipsisLoc(); NumExpansions = Expansion->getNumExpansions(); return TemplateArgumentLoc(Pattern, Pattern); } case TemplateArgument::TemplateExpansion: Ellipsis = getTemplateEllipsisLoc(); NumExpansions = Argument.getNumTemplateExpansions(); return TemplateArgumentLoc(Argument.getPackExpansionPattern(), getTemplateQualifierLoc(), getTemplateNameLoc()); case TemplateArgument::Declaration: case TemplateArgument::NullPtr: case TemplateArgument::Template: case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: return TemplateArgumentLoc(); } llvm_unreachable("Invalid TemplateArgument Kind!"); }