summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/DeclSpec.cpp25
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp72
-rw-r--r--clang/lib/Sema/SemaType.cpp350
-rw-r--r--clang/lib/Sema/TreeTransform.h193
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,
OpenPOWER on IntegriCloud