diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 72 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 350 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 193 |
4 files changed, 491 insertions, 149 deletions
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 5c75536e94a..ea3872f4270 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -893,7 +893,6 @@ bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, return false; } - bool DeclSpec::SetConceptSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { if (Concept_specified) { @@ -906,30 +905,6 @@ bool DeclSpec::SetConceptSpec(SourceLocation Loc, const char *&PrevSpec, return false; } -void DeclSpec::setObjCTypeArgs(SourceLocation lAngleLoc, - ArrayRef<ParsedType> args, - SourceLocation rAngleLoc) { - ParsedType *argsCopy = new ParsedType[args.size()]; - memcpy(argsCopy, args.data(), args.size() * sizeof(ParsedType)); - ObjCTypeArgs = llvm::makeArrayRef(argsCopy, args.size()); - ObjCTypeArgsLAngleLoc = lAngleLoc; - ObjCTypeArgsRAngleLoc = rAngleLoc; -} - -void DeclSpec::setProtocolQualifiers(Decl * const *Protos, - unsigned NP, - SourceLocation *ProtoLocs, - SourceLocation LAngleLoc) { - if (NP == 0) return; - Decl **ProtoQuals = new Decl*[NP]; - memcpy(ProtoQuals, Protos, sizeof(Decl*)*NP); - ProtocolQualifiers = ProtoQuals; - ProtocolLocs = new SourceLocation[NP]; - memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP); - NumProtocolQualifiers = NP; - ProtocolLAngleLoc = LAngleLoc; -} - void DeclSpec::SaveWrittenBuiltinSpecs() { writtenBS.Sign = getTypeSpecSign(); writtenBS.Width = getTypeSpecWidth(); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index f28abf4c070..48aa2467d24 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -560,29 +560,19 @@ ActOnSuperClassOfClassInterface(Scope *S, // Handle type arguments on the superclass. TypeSourceInfo *SuperClassTInfo = nullptr; - if (!SuperTypeArgs.empty()) { - // Form declaration specifiers naming this superclass type with - // type arguments. - AttributeFactory attrFactory; - DeclSpec DS(attrFactory); - const char* prevSpec; // unused - unsigned diagID; // unused - TypeSourceInfo *parsedTSInfo - = Context.getTrivialTypeSourceInfo(SuperClassType, SuperLoc); - ParsedType parsedType = CreateParsedType(SuperClassType, parsedTSInfo); - - DS.SetTypeSpecType(DeclSpec::TST_typename, SuperLoc, prevSpec, diagID, - parsedType, Context.getPrintingPolicy()); - DS.SetRangeStart(SuperLoc); - DS.SetRangeEnd(SuperLoc); - DS.setObjCTypeArgs(SuperTypeArgsRange.getBegin(), - SuperTypeArgs, - SuperTypeArgsRange.getEnd()); - - // Form the declarator. - Declarator D(DS, Declarator::TypeNameContext); - - TypeResult fullSuperClassType = ActOnTypeName(S, D); + if (!SuperTypeArgs.empty()) { + TypeResult fullSuperClassType = actOnObjCTypeArgsAndProtocolQualifiers( + S, + SuperLoc, + CreateParsedType(SuperClassType, + nullptr), + SuperTypeArgsRange.getBegin(), + SuperTypeArgs, + SuperTypeArgsRange.getEnd(), + SourceLocation(), + { }, + { }, + SourceLocation()); if (!fullSuperClassType.isUsable()) return; @@ -1230,21 +1220,26 @@ class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback { void Sema::actOnObjCTypeArgsOrProtocolQualifiers( Scope *S, - DeclSpec &DS, SourceLocation lAngleLoc, ArrayRef<IdentifierInfo *> identifiers, ArrayRef<SourceLocation> identifierLocs, SourceLocation rAngleLoc, + SourceLocation &typeArgsLAngleLoc, + SmallVectorImpl<ParsedType> &typeArgs, + SourceLocation &typeArgsRAngleLoc, + SourceLocation &protocolLAngleLoc, + SmallVectorImpl<Decl *> &protocols, + SourceLocation &protocolRAngleLoc, bool warnOnIncompleteProtocols) { // Local function that updates the declaration specifiers with // protocol information. - SmallVector<ObjCProtocolDecl *, 4> protocols; unsigned numProtocolsResolved = 0; auto resolvedAsProtocols = [&] { assert(numProtocolsResolved == identifiers.size() && "Unresolved protocols"); for (unsigned i = 0, n = protocols.size(); i != n; ++i) { - ObjCProtocolDecl *&proto = protocols[i]; + ObjCProtocolDecl *&proto + = reinterpret_cast<ObjCProtocolDecl *&>(protocols[i]); // For an objc container, delay protocol reference checking until after we // can set the objc decl as the availability context, otherwise check now. if (!warnOnIncompleteProtocols) { @@ -1268,12 +1263,9 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( } } - DS.setProtocolQualifiers((Decl * const *)(protocols.data()), - protocols.size(), - const_cast<SourceLocation *>(identifierLocs.data()), - lAngleLoc); - if (rAngleLoc.isValid()) - DS.SetRangeEnd(rAngleLoc); + protocolLAngleLoc = lAngleLoc; + protocolRAngleLoc = rAngleLoc; + assert(protocols.size() == identifierLocs.size()); }; // Attempt to resolve all of the identifiers as protocols. @@ -1370,20 +1362,24 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // Local function that updates the declaration specifiers with // type argument information. auto resolvedAsTypeDecls = [&] { + // We did not resolve these as protocols. + protocols.clear(); + assert(numTypeDeclsResolved == identifiers.size() && "Unresolved type decl"); // Map type declarations to type arguments. - SmallVector<ParsedType, 4> typeArgs; for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { // Map type reference to a type. TypeResult type = resolveTypeReference(typeDecls[i], identifierLocs[i]); - if (!type.isUsable()) + if (!type.isUsable()) { + typeArgs.clear(); return; + } typeArgs.push_back(type.get()); } - // Record the Objective-C type arguments. - DS.setObjCTypeArgs(lAngleLoc, typeArgs, rAngleLoc); + typeArgsLAngleLoc = lAngleLoc; + typeArgsRAngleLoc = rAngleLoc; }; // If all of the identifiers can be resolved as type names or @@ -1432,6 +1428,8 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( << identifiers[0] << SourceRange(identifierLocs[0]); + protocols.clear(); + typeArgs.clear(); return; } @@ -1483,6 +1481,8 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( : lookupKind == LookupObjCProtocolName ? diag::err_undeclared_protocol : diag::err_unknown_typename)) << identifiers[i]; + protocols.clear(); + typeArgs.clear(); return; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 1257ae361f0..06d832c9de8 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -740,14 +740,18 @@ static void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS, /// Apply Objective-C type arguments to the given type. static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, - ArrayRef<ParsedType> typeArgs, - SourceRange typeArgsRange) { + ArrayRef<TypeSourceInfo *> typeArgs, + SourceRange typeArgsRange, + bool failOnError = false) { // We can only apply type arguments to an Objective-C class type. const auto *objcObjectType = type->getAs<ObjCObjectType>(); if (!objcObjectType || !objcObjectType->getInterface()) { S.Diag(loc, diag::err_objc_type_args_non_class) << type << typeArgsRange; + + if (failOnError) + return QualType(); return type; } @@ -758,6 +762,10 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, S.Diag(loc, diag::err_objc_type_args_non_parameterized_class) << objcClass->getDeclName() << FixItHint::CreateRemoval(typeArgsRange); + + if (failOnError) + return QualType(); + return type; } @@ -766,26 +774,20 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, S.Diag(loc, diag::err_objc_type_args_specialized_class) << type << FixItHint::CreateRemoval(typeArgsRange); - return type; - } - // Make sure that we have the right number of type arguments. - if (typeArgs.size() != typeParams->size()) { - S.Diag(loc, diag::err_objc_type_args_wrong_arity) - << (typeArgs.size() < typeParams->size()) - << objcClass->getDeclName() - << (unsigned)typeArgs.size() - << (unsigned)typeParams->size(); - S.Diag(objcClass->getLocation(), diag::note_previous_decl) - << objcClass; + if (failOnError) + return QualType(); + return type; } // Check the type arguments. SmallVector<QualType, 4> finalTypeArgs; + unsigned numTypeParams = typeParams->size(); + bool anyPackExpansions = false; for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) { - TypeSourceInfo *typeArgInfo = nullptr; - QualType typeArg = S.GetTypeFromParser(typeArgs[i], &typeArgInfo); + TypeSourceInfo *typeArgInfo = typeArgs[i]; + QualType typeArg = typeArgInfo->getType(); // Type arguments cannot explicitly specify nullability. if (auto nullability = AttributedType::stripOuterNullability(typeArg)) { @@ -801,10 +803,42 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, finalTypeArgs.push_back(typeArg); + if (typeArg->getAs<PackExpansionType>()) + anyPackExpansions = true; + + // Find the corresponding type parameter, if there is one. + ObjCTypeParamDecl *typeParam = nullptr; + if (!anyPackExpansions) { + if (i < numTypeParams) { + typeParam = typeParams->begin()[i]; + } else { + // Too many arguments. + S.Diag(loc, diag::err_objc_type_args_wrong_arity) + << false + << objcClass->getDeclName() + << (unsigned)typeArgs.size() + << numTypeParams; + S.Diag(objcClass->getLocation(), diag::note_previous_decl) + << objcClass; + + if (failOnError) + return QualType(); + + return type; + } + } + // Objective-C object pointer types must be substitutable for the bounds. if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) { + // If we don't have a type parameter to match against, assume + // everything is fine. There was a prior pack expansion that + // means we won't be able to match anything. + if (!typeParam) { + assert(anyPackExpansions && "Too many arguments?"); + continue; + } + // Retrieve the bound. - ObjCTypeParamDecl *typeParam = typeParams->begin()[i]; QualType bound = typeParam->getUnderlyingType(); const auto *boundObjC = bound->getAs<ObjCObjectPointerType>(); @@ -826,13 +860,23 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) << typeParam->getDeclName(); + if (failOnError) + return QualType(); + return type; } // Block pointer types are permitted for unqualified 'id' bounds. if (typeArg->isBlockPointerType()) { + // If we don't have a type parameter to match against, assume + // everything is fine. There was a prior pack expansion that + // means we won't be able to match anything. + if (!typeParam) { + assert(anyPackExpansions && "Too many arguments?"); + continue; + } + // Retrieve the bound. - ObjCTypeParamDecl *typeParam = typeParams->begin()[i]; QualType bound = typeParam->getUnderlyingType(); if (bound->isBlockCompatibleObjCPointerType(S.Context)) continue; @@ -844,6 +888,9 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) << typeParam->getDeclName(); + if (failOnError) + return QualType(); + return type; } @@ -857,6 +904,26 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, diag::err_objc_type_arg_not_id_compatible) << typeArg << typeArgInfo->getTypeLoc().getSourceRange(); + + if (failOnError) + return QualType(); + + return type; + } + + // Make sure we didn't have the wrong number of arguments. + if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) { + S.Diag(loc, diag::err_objc_type_args_wrong_arity) + << (typeArgs.size() < typeParams->size()) + << objcClass->getDeclName() + << (unsigned)finalTypeArgs.size() + << (unsigned)numTypeParams; + S.Diag(objcClass->getLocation(), diag::note_previous_decl) + << objcClass; + + if (failOnError) + return QualType(); + return type; } @@ -868,7 +935,8 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, static QualType applyObjCProtocolQualifiers( Sema &S, SourceLocation loc, SourceRange range, QualType type, ArrayRef<ObjCProtocolDecl *> protocols, - const SourceLocation *protocolLocs) { + const SourceLocation *protocolLocs, + bool failOnError = false) { ASTContext &ctx = S.Context; if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){ // FIXME: Check for protocols to which the class type is already @@ -902,9 +970,185 @@ static QualType applyObjCProtocolQualifiers( S.Diag(loc, diag::err_invalid_protocol_qualifiers) << range; + + if (failOnError) + return QualType(); + return type; } +QualType Sema::BuildObjCObjectType(QualType BaseType, + SourceLocation Loc, + SourceLocation TypeArgsLAngleLoc, + ArrayRef<TypeSourceInfo *> TypeArgs, + SourceLocation TypeArgsRAngleLoc, + SourceLocation ProtocolLAngleLoc, + ArrayRef<ObjCProtocolDecl *> Protocols, + ArrayRef<SourceLocation> ProtocolLocs, + SourceLocation ProtocolRAngleLoc, + bool FailOnError) { + QualType Result = BaseType; + if (!TypeArgs.empty()) { + Result = applyObjCTypeArgs(*this, Loc, Result, TypeArgs, + SourceRange(TypeArgsLAngleLoc, + TypeArgsRAngleLoc), + FailOnError); + if (FailOnError && Result.isNull()) + return QualType(); + } + + if (!Protocols.empty()) { + Result = applyObjCProtocolQualifiers(*this, Loc, + SourceRange(ProtocolLAngleLoc, + ProtocolRAngleLoc), + Result, Protocols, + ProtocolLocs.data(), + FailOnError); + if (FailOnError && Result.isNull()) + return QualType(); + } + + return Result; +} + +TypeResult Sema::actOnObjCProtocolQualifierType( + SourceLocation lAngleLoc, + ArrayRef<Decl *> protocols, + ArrayRef<SourceLocation> protocolLocs, + SourceLocation rAngleLoc) { + // Form id<protocol-list>. + QualType Result = Context.getObjCObjectType( + Context.ObjCBuiltinIdTy, { }, + llvm::makeArrayRef( + (ObjCProtocolDecl * const *)protocols.data(), + protocols.size())); + Result = Context.getObjCObjectPointerType(Result); + + TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); + TypeLoc ResultTL = ResultTInfo->getTypeLoc(); + + auto ObjCObjectPointerTL = ResultTL.castAs<ObjCObjectPointerTypeLoc>(); + ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit + + auto ObjCObjectTL = ObjCObjectPointerTL.getPointeeLoc() + .castAs<ObjCObjectTypeLoc>(); + ObjCObjectTL.setHasBaseTypeAsWritten(false); + ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation()); + + // No type arguments. + ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); + ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); + + // Fill in protocol qualifiers. + ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc); + ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc); + for (unsigned i = 0, n = protocols.size(); i != n; ++i) + ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]); + + // We're done. Return the completed type to the parser. + return CreateParsedType(Result, ResultTInfo); +} + +TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers( + Scope *S, + SourceLocation Loc, + ParsedType BaseType, + SourceLocation TypeArgsLAngleLoc, + ArrayRef<ParsedType> TypeArgs, + SourceLocation TypeArgsRAngleLoc, + SourceLocation ProtocolLAngleLoc, + ArrayRef<Decl *> Protocols, + ArrayRef<SourceLocation> ProtocolLocs, + SourceLocation ProtocolRAngleLoc) { + TypeSourceInfo *BaseTypeInfo = nullptr; + QualType T = GetTypeFromParser(BaseType, &BaseTypeInfo); + if (T.isNull()) + return true; + + // Handle missing type-source info. + if (!BaseTypeInfo) + BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc); + + // Extract type arguments. + SmallVector<TypeSourceInfo *, 4> ActualTypeArgInfos; + for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) { + TypeSourceInfo *TypeArgInfo = nullptr; + QualType TypeArg = GetTypeFromParser(TypeArgs[i], &TypeArgInfo); + if (TypeArg.isNull()) { + ActualTypeArgInfos.clear(); + break; + } + + assert(TypeArgInfo && "No type source info?"); + ActualTypeArgInfos.push_back(TypeArgInfo); + } + + // Build the object type. + QualType Result = BuildObjCObjectType( + T, + BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(), + TypeArgsLAngleLoc, + ActualTypeArgInfos, + TypeArgsRAngleLoc, + ProtocolLAngleLoc, + llvm::makeArrayRef((ObjCProtocolDecl **)Protocols.data(), + Protocols.size()), + ProtocolLocs, + ProtocolRAngleLoc, + /*FailOnError=*/false); + + if (Result == T) + return BaseType; + + // Create source information for this type. + TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); + TypeLoc ResultTL = ResultTInfo->getTypeLoc(); + + // For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an + // object pointer type. Fill in source information for it. + if (auto ObjCObjectPointerTL = ResultTL.getAs<ObjCObjectPointerTypeLoc>()) { + // The '*' is implicit. + ObjCObjectPointerTL.setStarLoc(SourceLocation()); + ResultTL = ObjCObjectPointerTL.getPointeeLoc(); + } + + auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>(); + + // Type argument information. + if (ObjCObjectTL.getNumTypeArgs() > 0) { + assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size()); + ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc); + ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc); + for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i) + ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]); + } else { + ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); + ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); + } + + // Protocol qualifier information. + if (ObjCObjectTL.getNumProtocols() > 0) { + assert(ObjCObjectTL.getNumProtocols() == Protocols.size()); + ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc); + ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc); + for (unsigned i = 0, n = Protocols.size(); i != n; ++i) + ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]); + } else { + ObjCObjectTL.setProtocolLAngleLoc(SourceLocation()); + ObjCObjectTL.setProtocolRAngleLoc(SourceLocation()); + } + + // Base type. + ObjCObjectTL.setHasBaseTypeAsWritten(true); + if (ObjCObjectTL.getType() == T) + ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc()); + else + ObjCObjectTL.getBaseLoc().initialize(Context, Loc); + + // We're done. Return the completed type to the parser. + return CreateParsedType(Result, ResultTInfo); +} + /// \brief Convert the specified declspec to the appropriate type /// object. /// \param state Specifies the declarator containing the declaration specifier @@ -968,16 +1212,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.Char32Ty; break; case DeclSpec::TST_unspecified: - // "<proto1,proto2>" is an objc qualified ID with a missing id. - if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { - Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, { }, - llvm::makeArrayRef( - (ObjCProtocolDecl*const*)PQ, - DS.getNumProtocolQualifiers())); - Result = Context.getObjCObjectPointerType(Result); - break; - } - // If this is a missing declspec in a block literal return context, then it // is inferred from the return statements inside the block. // The declspec is always missing in a lambda expr context; it is either @@ -1161,21 +1395,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { declarator.setInvalidType(true); } } - } else { - // Apply Objective-C type arguments. - if (DS.hasObjCTypeArgs()) { - Result = applyObjCTypeArgs(S, DeclLoc, Result, DS.getObjCTypeArgs(), - DS.getObjCTypeArgsRange()); - } - - // Apply Objective-C protocol qualifiers. - if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { - Result = applyObjCProtocolQualifiers( - S, DeclLoc, DS.getSourceRange(), Result, - llvm::makeArrayRef((ObjCProtocolDecl * const *)PQ, - DS.getNumProtocolQualifiers()), - DS.getProtocolLocs()); - } } // TypeQuals handled by caller. @@ -4282,47 +4501,14 @@ namespace { TL.setNameEndLoc(DS.getLocEnd()); } void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { - // Handle the base type, which might not have been written explicitly. - if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) { - TL.setHasBaseTypeAsWritten(false); - TL.getBaseLoc().initialize(Context, SourceLocation()); - } else { - TL.setHasBaseTypeAsWritten(true); - Visit(TL.getBaseLoc()); - } - - // Type arguments. - if (TL.getNumTypeArgs() > 0) { - assert(TL.getNumTypeArgs() == DS.getObjCTypeArgs().size()); - TL.setTypeArgsLAngleLoc(DS.getObjCTypeArgsLAngleLoc()); - TL.setTypeArgsRAngleLoc(DS.getObjCTypeArgsRAngleLoc()); - for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) { - TypeSourceInfo *typeArgInfo = nullptr; - (void)Sema::GetTypeFromParser(DS.getObjCTypeArgs()[i], &typeArgInfo); - TL.setTypeArgTInfo(i, typeArgInfo); - } - } else { - TL.setTypeArgsLAngleLoc(SourceLocation()); - TL.setTypeArgsRAngleLoc(SourceLocation()); - } - - // Protocol qualifiers. - if (DS.getProtocolQualifiers()) { - assert(TL.getNumProtocols() > 0); - assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers()); - TL.setProtocolLAngleLoc(DS.getProtocolLAngleLoc()); - TL.setProtocolRAngleLoc(DS.getSourceRange().getEnd()); - for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i) - TL.setProtocolLoc(i, DS.getProtocolLocs()[i]); - } else { - assert(TL.getNumProtocols() == 0); - TL.setProtocolLAngleLoc(SourceLocation()); - TL.setProtocolRAngleLoc(SourceLocation()); - } + TypeSourceInfo *RepTInfo = nullptr; + Sema::GetTypeFromParser(DS.getRepAsType(), &RepTInfo); + TL.copy(RepTInfo->getTypeLoc()); } void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - TL.setStarLoc(SourceLocation()); - Visit(TL.getPointeeLoc()); + TypeSourceInfo *RepTInfo = nullptr; + Sema::GetTypeFromParser(DS.getRepAsType(), &RepTInfo); + TL.copy(RepTInfo->getTypeLoc()); } void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { TypeSourceInfo *TInfo = nullptr; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 80896be981d..8b150c3a658 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -685,6 +685,27 @@ public: QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType, SourceLocation Sigil); + /// \brief Build an Objective-C object type. + /// + /// By default, performs semantic analysis when building the object type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildObjCObjectType(QualType BaseType, + SourceLocation Loc, + SourceLocation TypeArgsLAngleLoc, + ArrayRef<TypeSourceInfo *> TypeArgs, + SourceLocation TypeArgsRAngleLoc, + SourceLocation ProtocolLAngleLoc, + ArrayRef<ObjCProtocolDecl *> Protocols, + ArrayRef<SourceLocation> ProtocolLocs, + SourceLocation ProtocolRAngleLoc); + + /// \brief Build a new Objective-C object pointer type given the pointee type. + /// + /// By default, directly builds the pointer type, with no additional semantic + /// analysis. + QualType RebuildObjCObjectPointerType(QualType PointeeType, + SourceLocation Star); + /// \brief Build a new array type given the element type, size /// modifier, size of the array (if known), size expression, and index type /// qualifiers. @@ -5606,18 +5627,153 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB, ObjCObjectTypeLoc TL) { - // ObjCObjectType is never dependent. - TLB.pushFullCopy(TL); - return TL.getType(); + // Transform base type. + QualType BaseType = getDerived().TransformType(TLB, TL.getBaseLoc()); + if (BaseType.isNull()) + return QualType(); + + bool AnyChanged = BaseType != TL.getBaseLoc().getType(); + + // Transform type arguments. + SmallVector<TypeSourceInfo *, 4> NewTypeArgInfos; + for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) { + TypeSourceInfo *TypeArgInfo = TL.getTypeArgTInfo(i); + TypeLoc TypeArgLoc = TypeArgInfo->getTypeLoc(); + QualType TypeArg = TypeArgInfo->getType(); + if (auto PackExpansionLoc = TypeArgLoc.getAs<PackExpansionTypeLoc>()) { + AnyChanged = true; + + // We have a pack expansion. Instantiate it. + const auto *PackExpansion = PackExpansionLoc.getType() + ->castAs<PackExpansionType>(); + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(), + Unexpanded); + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); + + // Determine whether the set of unexpanded parameter packs can + // and should be expanded. + TypeLoc PatternLoc = PackExpansionLoc.getPatternLoc(); + bool Expand = false; + bool RetainExpansion = false; + Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions(); + if (getDerived().TryExpandParameterPacks( + PackExpansionLoc.getEllipsisLoc(), PatternLoc.getSourceRange(), + Unexpanded, Expand, RetainExpansion, NumExpansions)) + return QualType(); + + if (!Expand) { + // We can't expand this pack expansion into separate arguments yet; + // just substitute into the pattern and create a new pack expansion + // type. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + + TypeLocBuilder TypeArgBuilder; + TypeArgBuilder.reserve(PatternLoc.getFullDataSize()); + QualType NewPatternType = getDerived().TransformType(TypeArgBuilder, + PatternLoc); + if (NewPatternType.isNull()) + return QualType(); + + QualType NewExpansionType = SemaRef.Context.getPackExpansionType( + NewPatternType, NumExpansions); + auto NewExpansionLoc = TLB.push<PackExpansionTypeLoc>(NewExpansionType); + NewExpansionLoc.setEllipsisLoc(PackExpansionLoc.getEllipsisLoc()); + NewTypeArgInfos.push_back( + TypeArgBuilder.getTypeSourceInfo(SemaRef.Context, NewExpansionType)); + continue; + } + + // Substitute into the pack expansion pattern for each slice of the + // pack. + for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), ArgIdx); + + TypeLocBuilder TypeArgBuilder; + TypeArgBuilder.reserve(PatternLoc.getFullDataSize()); + + QualType NewTypeArg = getDerived().TransformType(TypeArgBuilder, + PatternLoc); + if (NewTypeArg.isNull()) + return QualType(); + + NewTypeArgInfos.push_back( + TypeArgBuilder.getTypeSourceInfo(SemaRef.Context, NewTypeArg)); + } + + continue; + } + + TypeLocBuilder TypeArgBuilder; + TypeArgBuilder.reserve(TypeArgLoc.getFullDataSize()); + QualType NewTypeArg = getDerived().TransformType(TypeArgBuilder, TypeArgLoc); + if (NewTypeArg.isNull()) + return QualType(); + + // If nothing changed, just keep the old TypeSourceInfo. + if (NewTypeArg == TypeArg) { + NewTypeArgInfos.push_back(TypeArgInfo); + continue; + } + + NewTypeArgInfos.push_back( + TypeArgBuilder.getTypeSourceInfo(SemaRef.Context, NewTypeArg)); + AnyChanged = true; + } + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || AnyChanged) { + // Rebuild the type. + Result = getDerived().RebuildObjCObjectType( + BaseType, + TL.getLocStart(), + TL.getTypeArgsLAngleLoc(), + NewTypeArgInfos, + TL.getTypeArgsRAngleLoc(), + TL.getProtocolLAngleLoc(), + llvm::makeArrayRef(TL.getTypePtr()->qual_begin(), + TL.getNumProtocols()), + TL.getProtocolLocs(), + TL.getProtocolRAngleLoc()); + + if (Result.isNull()) + return QualType(); + } + + ObjCObjectTypeLoc NewT = TLB.push<ObjCObjectTypeLoc>(Result); + assert(TL.hasBaseTypeAsWritten() && "Can't be dependent"); + NewT.setHasBaseTypeAsWritten(true); + NewT.setTypeArgsLAngleLoc(TL.getTypeArgsLAngleLoc()); + for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) + NewT.setTypeArgTInfo(i, NewTypeArgInfos[i]); + NewT.setTypeArgsRAngleLoc(TL.getTypeArgsRAngleLoc()); + NewT.setProtocolLAngleLoc(TL.getProtocolLAngleLoc()); + for (unsigned i = 0, n = TL.getNumProtocols(); i != n; ++i) + NewT.setProtocolLoc(i, TL.getProtocolLoc(i)); + NewT.setProtocolRAngleLoc(TL.getProtocolRAngleLoc()); + return Result; } template<typename Derived> QualType TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB, ObjCObjectPointerTypeLoc TL) { - // ObjCObjectPointerType is never dependent. - TLB.pushFullCopy(TL); - return TL.getType(); + QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc()); + if (PointeeType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + PointeeType != TL.getPointeeLoc().getType()) { + Result = getDerived().RebuildObjCObjectPointerType(PointeeType, + TL.getStarLoc()); + if (Result.isNull()) + return QualType(); + } + + ObjCObjectPointerTypeLoc NewT = TLB.push<ObjCObjectPointerTypeLoc>(Result); + NewT.setStarLoc(TL.getStarLoc()); + return Result; } //===----------------------------------------------------------------------===// @@ -10494,6 +10650,31 @@ TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, } template<typename Derived> +QualType TreeTransform<Derived>::RebuildObjCObjectType( + QualType BaseType, + SourceLocation Loc, + SourceLocation TypeArgsLAngleLoc, + ArrayRef<TypeSourceInfo *> TypeArgs, + SourceLocation TypeArgsRAngleLoc, + SourceLocation ProtocolLAngleLoc, + ArrayRef<ObjCProtocolDecl *> Protocols, + ArrayRef<SourceLocation> ProtocolLocs, + SourceLocation ProtocolRAngleLoc) { + return SemaRef.BuildObjCObjectType(BaseType, Loc, TypeArgsLAngleLoc, + TypeArgs, TypeArgsRAngleLoc, + ProtocolLAngleLoc, Protocols, ProtocolLocs, + ProtocolRAngleLoc, + /*FailOnError=*/true); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildObjCObjectPointerType( + QualType PointeeType, + SourceLocation Star) { + return SemaRef.Context.getObjCObjectPointerType(PointeeType); +} + +template<typename Derived> QualType TreeTransform<Derived>::RebuildArrayType(QualType ElementType, ArrayType::ArraySizeModifier SizeMod, |