summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp102
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp137
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp200
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp1004
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp82
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp123
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp576
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h195
22 files changed, 2183 insertions, 439 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
index 69ae4f0..18e9a59 100644
--- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -444,7 +444,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
if (Results[I].Hidden)
OS << " (Hidden)";
if (CodeCompletionString *CCS
- = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(),
+ = Results[I].CreateCodeCompletionString(SemaRef, Context,
+ getAllocator(),
CCTUInfo,
includeBriefComments())) {
OS << " : " << CCS->getAsString();
@@ -462,7 +463,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
case CodeCompletionResult::RK_Macro: {
OS << Results[I].Macro->getName();
if (CodeCompletionString *CCS
- = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(),
+ = Results[I].CreateCodeCompletionString(SemaRef, Context,
+ getAllocator(),
CCTUInfo,
includeBriefComments())) {
OS << " : " << CCS->getAsString();
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index d5c8871..ea3872f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -905,20 +905,6 @@ bool DeclSpec::SetConceptSpec(SourceLocation Loc, const char *&PrevSpec,
return false;
}
-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/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
index d9dc4df9..c0754ba 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
@@ -975,7 +975,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
if (tcr != TC_NotApplicable)
return tcr;
- // C++0x [expr.static.cast]p3:
+ // C++11 [expr.static.cast]p3:
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
// T2" if "cv2 T2" is reference-compatible with "cv1 T1".
tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
@@ -1133,7 +1133,7 @@ TryCastResult
TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, CastKind &Kind, CXXCastPath &BasePath,
unsigned &msg) {
- // C++0x [expr.static.cast]p3:
+ // C++11 [expr.static.cast]p3:
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
// cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
const RValueReferenceType *R = DestType->getAs<RValueReferenceType>();
@@ -1161,6 +1161,8 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
DerivedToBase, ObjCConversion,
ObjCLifetimeConversion)
< Sema::Ref_Compatible_With_Added_Qualification) {
+ if (CStyle)
+ return TC_NotApplicable;
msg = diag::err_bad_lvalue_to_rvalue_cast;
return TC_Failed;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index bdfff80..d9d26e2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -6884,6 +6884,101 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
S.getFixItZeroLiteralForType(T, Loc));
}
+static void checkObjCArrayLiteral(Sema &S, QualType TargetType,
+ ObjCArrayLiteral *ArrayLiteral);
+static void checkObjCDictionaryLiteral(Sema &S, QualType TargetType,
+ ObjCDictionaryLiteral *DictionaryLiteral);
+
+/// Check a single element within a collection literal against the
+/// target element type.
+static void checkObjCCollectionLiteralElement(Sema &S,
+ QualType TargetElementType,
+ Expr *Element,
+ unsigned ElementKind) {
+ // Skip a bitcast to 'id' or qualified 'id'.
+ if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) {
+ if (ICE->getCastKind() == CK_BitCast &&
+ ICE->getSubExpr()->getType()->getAs<ObjCObjectPointerType>())
+ Element = ICE->getSubExpr();
+ }
+
+ QualType ElementType = Element->getType();
+ ExprResult ElementResult(Element);
+ if (ElementType->getAs<ObjCObjectPointerType>() &&
+ S.CheckSingleAssignmentConstraints(TargetElementType,
+ ElementResult,
+ false, false)
+ != Sema::Compatible) {
+ S.Diag(Element->getLocStart(),
+ diag::warn_objc_collection_literal_element)
+ << ElementType << ElementKind << TargetElementType
+ << Element->getSourceRange();
+ }
+
+ if (auto ArrayLiteral = dyn_cast<ObjCArrayLiteral>(Element))
+ checkObjCArrayLiteral(S, TargetElementType, ArrayLiteral);
+ else if (auto DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(Element))
+ checkObjCDictionaryLiteral(S, TargetElementType, DictionaryLiteral);
+}
+
+/// Check an Objective-C array literal being converted to the given
+/// target type.
+static void checkObjCArrayLiteral(Sema &S, QualType TargetType,
+ ObjCArrayLiteral *ArrayLiteral) {
+ if (!S.NSArrayDecl)
+ return;
+
+ const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();
+ if (!TargetObjCPtr)
+ return;
+
+ if (TargetObjCPtr->isUnspecialized() ||
+ TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl()
+ != S.NSArrayDecl->getCanonicalDecl())
+ return;
+
+ auto TypeArgs = TargetObjCPtr->getTypeArgs();
+ if (TypeArgs.size() != 1)
+ return;
+
+ QualType TargetElementType = TypeArgs[0];
+ for (unsigned I = 0, N = ArrayLiteral->getNumElements(); I != N; ++I) {
+ checkObjCCollectionLiteralElement(S, TargetElementType,
+ ArrayLiteral->getElement(I),
+ 0);
+ }
+}
+
+/// Check an Objective-C dictionary literal being converted to the given
+/// target type.
+static void checkObjCDictionaryLiteral(
+ Sema &S, QualType TargetType,
+ ObjCDictionaryLiteral *DictionaryLiteral) {
+ if (!S.NSDictionaryDecl)
+ return;
+
+ const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();
+ if (!TargetObjCPtr)
+ return;
+
+ if (TargetObjCPtr->isUnspecialized() ||
+ TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl()
+ != S.NSDictionaryDecl->getCanonicalDecl())
+ return;
+
+ auto TypeArgs = TargetObjCPtr->getTypeArgs();
+ if (TypeArgs.size() != 2)
+ return;
+
+ QualType TargetKeyType = TypeArgs[0];
+ QualType TargetObjectType = TypeArgs[1];
+ for (unsigned I = 0, N = DictionaryLiteral->getNumElements(); I != N; ++I) {
+ auto Element = DictionaryLiteral->getKeyValueElement(I);
+ checkObjCCollectionLiteralElement(S, TargetKeyType, Element.Key, 1);
+ checkObjCCollectionLiteralElement(S, TargetObjectType, Element.Value, 2);
+ }
+}
+
void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
SourceLocation CC, bool *ICContext = nullptr) {
if (E->isTypeDependent() || E->isValueDependent()) return;
@@ -6923,6 +7018,13 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
}
}
+ // Check implicit casts from Objective-C collection literals to specialized
+ // collection types, e.g., NSArray<NSString *> *.
+ if (auto *ArrayLiteral = dyn_cast<ObjCArrayLiteral>(E))
+ checkObjCArrayLiteral(S, QualType(Target, 0), ArrayLiteral);
+ else if (auto *DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(E))
+ checkObjCDictionaryLiteral(S, QualType(Target, 0), DictionaryLiteral);
+
// Strip vector types.
if (isa<VectorType>(Source)) {
if (!isa<VectorType>(Target)) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
index ff6a3ee..8626527 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -2057,6 +2057,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
static void AddResultTypeChunk(ASTContext &Context,
const PrintingPolicy &Policy,
const NamedDecl *ND,
+ QualType BaseType,
CodeCompletionBuilder &Result) {
if (!ND)
return;
@@ -2070,16 +2071,28 @@ static void AddResultTypeChunk(ASTContext &Context,
QualType T;
if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getReturnType();
- else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
- T = Method->getReturnType();
- else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+ if (!BaseType.isNull())
+ T = Method->getSendResultType(BaseType);
+ else
+ T = Method->getReturnType();
+ } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
else if (isa<UnresolvedUsingValueDecl>(ND)) {
/* Do nothing: ignore unresolved using declarations*/
+ } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
+ if (!BaseType.isNull())
+ T = Ivar->getUsageType(BaseType);
+ else
+ T = Ivar->getType();
} else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
T = Value->getType();
- } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
- T = Property->getType();
+ } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
+ if (!BaseType.isNull())
+ T = Property->getUsageType(BaseType);
+ else
+ T = Property->getType();
+ }
if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
return;
@@ -2140,7 +2153,8 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
const ParmVarDecl *Param,
bool SuppressName = false,
- bool SuppressBlock = false) {
+ bool SuppressBlock = false,
+ Optional<ArrayRef<QualType>> ObjCSubsts = None) {
bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
if (Param->getType()->isDependentType() ||
!Param->getType()->isBlockPointerType()) {
@@ -2152,6 +2166,9 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Result = Param->getIdentifier()->getName();
QualType Type = Param->getType();
+ if (ObjCSubsts)
+ Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
+ ObjCSubstitutionContext::Parameter);
if (ObjCMethodParam) {
Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
Type);
@@ -2187,6 +2204,11 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
TL = QualifiedTL.getUnqualifiedLoc();
continue;
}
+
+ if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
+ TL = AttrTL.getModifiedLoc();
+ continue;
+ }
}
// Try to get the function prototype behind the block pointer type,
@@ -2226,6 +2248,10 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
// written in the source.
std::string Result;
QualType ResultType = Block.getTypePtr()->getReturnType();
+ if (ObjCSubsts)
+ ResultType = ResultType.substObjCTypeArgs(Param->getASTContext(),
+ *ObjCSubsts,
+ ObjCSubstitutionContext::Result);
if (!ResultType->isVoidType() || SuppressBlock)
ResultType.getAsStringInternal(Result, Policy);
@@ -2243,7 +2269,8 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Params += ", ";
Params += FormatFunctionParameter(Policy, Block.getParam(I),
/*SuppressName=*/false,
- /*SuppressBlock=*/true);
+ /*SuppressBlock=*/true,
+ ObjCSubsts);
if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Params += ", ...";
@@ -2537,11 +2564,12 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
}
CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
+ const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments) {
- return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo,
- IncludeBriefComments);
+ return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
+ CCTUInfo, IncludeBriefComments);
}
/// \brief If possible, create a new code completion string for the given
@@ -2553,6 +2581,7 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
CodeCompletionString *
CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Preprocessor &PP,
+ const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments) {
@@ -2666,7 +2695,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
for (const auto *I : ND->specific_attrs<AnnotateAttr>())
Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
- AddResultTypeChunk(Ctx, Policy, ND, Result);
+ AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
@@ -2786,14 +2815,22 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
continue;
std::string Arg;
-
- if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
- Arg = FormatFunctionParameter(Policy, *P, true);
+ QualType ParamType = (*P)->getType();
+ Optional<ArrayRef<QualType>> ObjCSubsts;
+ if (!CCContext.getBaseType().isNull())
+ ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
+
+ if (ParamType->isBlockPointerType() && !DeclaringEntity)
+ Arg = FormatFunctionParameter(Policy, *P, true,
+ /*SuppressBlock=*/false,
+ ObjCSubsts);
else {
- QualType Type = (*P)->getType();
+ if (ObjCSubsts)
+ ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
+ ObjCSubstitutionContext::Parameter);
Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
- Type);
- Arg += Type.getAsString(Policy) + ")";
+ ParamType);
+ Arg += ParamType.getAsString(Policy) + ")";
if (IdentifierInfo *II = (*P)->getIdentifier())
if (DeclaringEntity || AllParametersAreInformative)
Arg += II->getName();
@@ -2930,7 +2967,7 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
if (auto RC = S.getASTContext().getRawCommentForAnyRedecl(
FDecl->getParamDecl(CurrentArg)))
Result.addBriefComment(RC->getBriefText(S.getASTContext()));
- AddResultTypeChunk(S.Context, Policy, FDecl, Result);
+ AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Result.AddTextChunk(
Result.getAllocator().CopyString(FDecl->getNameAsString()));
} else {
@@ -3029,7 +3066,9 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
case Decl::Import:
return CXCursor_ModuleImportDecl;
-
+
+ case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
+
default:
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
switch (TD->getTagKind()) {
@@ -3520,7 +3559,8 @@ static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
return Container;
}
-static void AddObjCProperties(ObjCContainerDecl *Container,
+static void AddObjCProperties(const CodeCompletionContext &CCContext,
+ ObjCContainerDecl *Container,
bool AllowCategories,
bool AllowNullaryMethods,
DeclContext *CurContext,
@@ -3547,7 +3587,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
if (AddedProperties.insert(Name).second) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
- AddResultTypeChunk(Context, Policy, M, Builder);
+ AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(),
+ Builder);
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(Name->getName()));
@@ -3562,32 +3603,32 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
// Add properties in referenced protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
for (auto *P : Protocol->protocols())
- AddObjCProperties(P, AllowCategories, AllowNullaryMethods, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
+ CurContext, AddedProperties, Results);
} else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
if (AllowCategories) {
// Look through categories.
for (auto *Cat : IFace->known_categories())
- AddObjCProperties(Cat, AllowCategories, AllowNullaryMethods, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
+ CurContext, AddedProperties, Results);
}
// Look through protocols.
for (auto *I : IFace->all_referenced_protocols())
- AddObjCProperties(I, AllowCategories, AllowNullaryMethods, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
+ CurContext, AddedProperties, Results);
// Look in the superclass.
if (IFace->getSuperClass())
- AddObjCProperties(IFace->getSuperClass(), AllowCategories,
+ AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
AllowNullaryMethods, CurContext,
AddedProperties, Results);
} else if (const ObjCCategoryDecl *Category
= dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
for (auto *P : Category->protocols())
- AddObjCProperties(P, AllowCategories, AllowNullaryMethods, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
+ CurContext, AddedProperties, Results);
}
}
@@ -3629,11 +3670,11 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
contextKind = CodeCompletionContext::CCC_DotMemberAccess;
}
}
-
+
+ CodeCompletionContext CCContext(contextKind, BaseType);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext(contextKind,
- BaseType),
+ CCContext,
&ResultBuilder::IsMember);
Results.EnterNewScope();
if (const RecordType *Record = BaseType->getAs<RecordType>()) {
@@ -3673,14 +3714,14 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
const ObjCObjectPointerType *ObjCPtr
= BaseType->getAsObjCInterfacePointerType();
assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
- AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
+ AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
/*AllowNullaryMethods=*/true, CurContext,
AddedProperties, Results);
// Add properties from the protocols in a qualified interface.
for (auto *I : ObjCPtr->quals())
- AddObjCProperties(I, true, /*AllowNullaryMethods=*/true, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
+ CurContext, AddedProperties, Results);
} else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
(!IsArrow && BaseType->isObjCObjectType())) {
// Objective-C instance variable access.
@@ -4368,9 +4409,12 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
void Sema::CodeCompleteConstructorInitializer(
Decl *ConstructorD,
ArrayRef <CXXCtorInitializer *> Initializers) {
- PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
- CXXConstructorDecl *Constructor
- = static_cast<CXXConstructorDecl *>(ConstructorD);
+ if (!ConstructorD)
+ return;
+
+ AdjustDeclIfTemplate(ConstructorD);
+
+ CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
if (!Constructor)
return;
@@ -4394,6 +4438,7 @@ void Sema::CodeCompleteConstructorInitializer(
// Add completions for base classes.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
+ PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
bool SawLastInitializer = Initializers.empty();
CXXRecordDecl *ClassDecl = Constructor->getParent();
for (const auto &Base : ClassDecl->bases()) {
@@ -5334,7 +5379,8 @@ static ObjCMethodDecl *AddSuperSendCompletion(
Results.getCodeCompletionTUInfo());
// Give this completion a return type.
- AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
+ AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
+ Results.getCompletionContext().getBaseType(),
Builder);
// If we need the "super" keyword, add it (plus some spacing).
@@ -6088,9 +6134,10 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
}
void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
+ CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_Other);
+ CCContext);
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container
@@ -6111,11 +6158,12 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Results.EnterNewScope();
if (ObjCImplementationDecl *ClassImpl
= dyn_cast<ObjCImplementationDecl>(Container))
- AddObjCProperties(ClassImpl->getClassInterface(), false,
+ AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
/*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
else
- AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
+ AddObjCProperties(CCContext,
+ cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
false, /*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
Results.ExitScope();
@@ -7032,7 +7080,8 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
// If the result type was not already provided, add it to the
// pattern as (type).
if (ReturnType.isNull())
- AddObjCPassingTypeChunk(Method->getReturnType(),
+ AddObjCPassingTypeChunk(Method->getSendResultType()
+ .stripObjCKindOfType(Context),
Method->getObjCDeclQualifier(), Context, Policy,
Builder);
@@ -7063,6 +7112,8 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
ParamType = (*P)->getType();
else
ParamType = (*P)->getOriginalType();
+ ParamType = ParamType.substObjCTypeArgs(Context, {},
+ ObjCSubstitutionContext::Parameter);
AddObjCPassingTypeChunk(ParamType,
(*P)->getObjCDeclQualifier(),
Context, Policy,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index 6508d6f..99d4a79 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -2577,6 +2577,48 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
return false;
}
+template<typename T> static bool isExternC(T *D) { return D->isExternC(); }
+static bool isExternC(VarTemplateDecl *) { return false; }
+
+/// \brief Check whether a redeclaration of an entity introduced by a
+/// using-declaration is valid, given that we know it's not an overload
+/// (nor a hidden tag declaration).
+template<typename ExpectedDecl>
+static bool checkUsingShadowRedecl(Sema &S, UsingShadowDecl *OldS,
+ ExpectedDecl *New) {
+ // C++11 [basic.scope.declarative]p4:
+ // Given a set of declarations in a single declarative region, each of
+ // which specifies the same unqualified name,
+ // -- they shall all refer to the same entity, or all refer to functions
+ // and function templates; or
+ // -- exactly one declaration shall declare a class name or enumeration
+ // name that is not a typedef name and the other declarations shall all
+ // refer to the same variable or enumerator, or all refer to functions
+ // and function templates; in this case the class name or enumeration
+ // name is hidden (3.3.10).
+
+ // C++11 [namespace.udecl]p14:
+ // If a function declaration in namespace scope or block scope has the
+ // same name and the same parameter-type-list as a function introduced
+ // by a using-declaration, and the declarations do not declare the same
+ // function, the program is ill-formed.
+
+ auto *Old = dyn_cast<ExpectedDecl>(OldS->getTargetDecl());
+ if (Old &&
+ !Old->getDeclContext()->getRedeclContext()->Equals(
+ New->getDeclContext()->getRedeclContext()) &&
+ !(isExternC(Old) && isExternC(New)))
+ Old = nullptr;
+
+ if (!Old) {
+ S.Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
+ S.Diag(OldS->getTargetDecl()->getLocation(), diag::note_using_decl_target);
+ S.Diag(OldS->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ return true;
+ }
+ return false;
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -2603,28 +2645,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
return true;
}
- // C++11 [namespace.udecl]p14:
- // If a function declaration in namespace scope or block scope has the
- // same name and the same parameter-type-list as a function introduced
- // by a using-declaration, and the declarations do not declare the same
- // function, the program is ill-formed.
-
// Check whether the two declarations might declare the same function.
- Old = dyn_cast<FunctionDecl>(Shadow->getTargetDecl());
- if (Old &&
- !Old->getDeclContext()->getRedeclContext()->Equals(
- New->getDeclContext()->getRedeclContext()) &&
- !(Old->isExternC() && New->isExternC()))
- Old = nullptr;
-
- if (!Old) {
- Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
- Diag(Shadow->getTargetDecl()->getLocation(),
- diag::note_using_decl_target);
- Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ if (checkUsingShadowRedecl<FunctionDecl>(*this, Shadow, New))
return true;
- }
- OldD = Old;
+ OldD = Old = cast<FunctionDecl>(Shadow->getTargetDecl());
} else {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
@@ -3246,9 +3270,16 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old,
//
// Neither C nor C++ requires a diagnostic for this, but we should still try
// to diagnose it.
- Diag(New->getLocation(), diag::err_redefinition_different_type)
- << New->getDeclName() << New->getType() << Old->getType();
- Diag(Old->getLocation(), diag::note_previous_definition);
+ Diag(New->getLocation(), New->isThisDeclarationADefinition()
+ ? diag::err_redefinition_different_type
+ : diag::err_redeclaration_different_type)
+ << New->getDeclName() << New->getType() << Old->getType();
+
+ diag::kind PrevDiag;
+ SourceLocation OldLocation;
+ std::tie(PrevDiag, OldLocation) =
+ getNoteDiagForInvalidRedeclaration(Old, New);
+ Diag(OldLocation, PrevDiag);
return New->setInvalidDecl();
}
@@ -3309,8 +3340,19 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (NewTemplate) {
OldTemplate = dyn_cast<VarTemplateDecl>(Previous.getFoundDecl());
Old = OldTemplate ? OldTemplate->getTemplatedDecl() : nullptr;
- } else
+
+ if (auto *Shadow =
+ dyn_cast<UsingShadowDecl>(Previous.getRepresentativeDecl()))
+ if (checkUsingShadowRedecl<VarTemplateDecl>(*this, Shadow, NewTemplate))
+ return New->setInvalidDecl();
+ } else {
Old = dyn_cast<VarDecl>(Previous.getFoundDecl());
+
+ if (auto *Shadow =
+ dyn_cast<UsingShadowDecl>(Previous.getRepresentativeDecl()))
+ if (checkUsingShadowRedecl<VarDecl>(*this, Shadow, New))
+ return New->setInvalidDecl();
+ }
}
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
@@ -4742,15 +4784,16 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
}
}
- if (DiagnoseClassNameShadow(DC, NameInfo))
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType R = TInfo->getType();
+
+ if (!R->isFunctionType() && DiagnoseClassNameShadow(DC, NameInfo))
// If this is a typedef, we'll end up spewing multiple diagnostics.
- // Just return early; it's safer.
+ // Just return early; it's safer. If this is a function, let the
+ // "constructor cannot have a return type" diagnostic handle it.
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
return nullptr;
- TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
- QualType R = TInfo->getType();
-
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_DeclarationType))
D.setInvalidType();
@@ -9785,6 +9828,16 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
FinalizeVarWithDestructor(var, recordType);
}
+/// \brief Determines if a variable's alignment is dependent.
+static bool hasDependentAlignment(VarDecl *VD) {
+ if (VD->getType()->isDependentType())
+ return true;
+ for (auto *I : VD->specific_attrs<AlignedAttr>())
+ if (I->isAlignmentDependent())
+ return true;
+ return false;
+}
+
/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
/// any semantic actions necessary after any initializer has been attached.
void
@@ -9798,6 +9851,22 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
checkAttributesAfterMerging(*this, *VD);
+ // Perform TLS alignment check here after attributes attached to the variable
+ // which may affect the alignment have been processed. Only perform the check
+ // if the target has a maximum TLS alignment (zero means no constraints).
+ if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
+ // Protect the check so that it's not performed on dependent types and
+ // dependent alignments (we can't determine the alignment in that case).
+ if (VD->getTLSKind() && !hasDependentAlignment(VD)) {
+ CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
+ if (Context.getDeclAlign(VD) > MaxAlignChars) {
+ Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
+ << (unsigned)Context.getDeclAlign(VD).getQuantity() << VD
+ << (unsigned)MaxAlignChars.getQuantity();
+ }
+ }
+ }
+
// Static locals inherit dll attributes from their function.
if (VD->isStaticLocal()) {
if (FunctionDecl *FD =
@@ -11258,7 +11327,7 @@ static bool isClassCompatTagKind(TagTypeKind Tag)
bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
TagTypeKind NewTag, bool isDefinition,
SourceLocation NewTagLoc,
- const IdentifierInfo &Name) {
+ const IdentifierInfo *Name) {
// C++ [dcl.type.elab]p3:
// The class-key or enum keyword present in the
// elaborated-type-specifier shall agree in kind with the
@@ -11287,7 +11356,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
// In a template instantiation, do not offer fix-its for tag mismatches
// since they usually mess up the template instead of fixing the problem.
Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
- << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
+ << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
<< getRedeclDiagFromTagKind(OldTag);
return true;
}
@@ -11306,7 +11375,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
if (!previousMismatch) {
previousMismatch = true;
Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch)
- << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
+ << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
<< getRedeclDiagFromTagKind(I->getTagKind());
}
Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion)
@@ -11328,7 +11397,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
}
Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
- << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
+ << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
<< getRedeclDiagFromTagKind(OldTag);
Diag(Redecl->getLocation(), diag::note_previous_use);
@@ -11388,6 +11457,27 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S,
return FixItHint::CreateInsertion(NameLoc, Insertion);
}
+/// \brief Determine whether a tag originally declared in context \p OldDC can
+/// be redeclared with an unqualfied name in \p NewDC (assuming name lookup
+/// found a declaration in \p OldDC as a previous decl, perhaps through a
+/// using-declaration).
+static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
+ DeclContext *NewDC) {
+ OldDC = OldDC->getRedeclContext();
+ NewDC = NewDC->getRedeclContext();
+
+ if (OldDC->Equals(NewDC))
+ return true;
+
+ // In MSVC mode, we allow a redeclaration if the contexts are related (either
+ // encloses the other).
+ if (S.getLangOpts().MSVCCompat &&
+ (OldDC->Encloses(NewDC) || NewDC->Encloses(OldDC)))
+ return true;
+
+ return false;
+}
+
/// \brief This is invoked when we see 'struct foo' or 'struct {'. In the
/// former case, Name will be non-null. In the later case, Name will be null.
/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
@@ -11559,6 +11649,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
goto CreateNewDecl;
}
} else if (Name) {
+ // C++14 [class.mem]p14:
+ // If T is the name of a class, then each of the following shall have a
+ // name different from T:
+ // -- every member of class T that is itself a type
+ if (TUK != TUK_Reference && TUK != TUK_Friend &&
+ DiagnoseClassNameShadow(SearchDC, DeclarationNameInfo(Name, NameLoc)))
+ return nullptr;
+
// If this is a named struct, check to see if there was a previous forward
// declaration or definition.
// FIXME: We're looking into outer scopes here, even when we
@@ -11724,8 +11822,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (!Previous.empty()) {
NamedDecl *PrevDecl = Previous.getFoundDecl();
- NamedDecl *DirectPrevDecl =
- getLangOpts().MSVCCompat ? *Previous.begin() : PrevDecl;
+ NamedDecl *DirectPrevDecl = Previous.getRepresentativeDecl();
// It's okay to have a tag decl in the same scope as a typedef
// which hides a tag decl in the same scope. Finding this
@@ -11752,6 +11849,26 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
}
+ // If this is a redeclaration of a using shadow declaration, it must
+ // declare a tag in the same context. In MSVC mode, we allow a
+ // redefinition if either context is within the other.
+ if (auto *Shadow = dyn_cast<UsingShadowDecl>(DirectPrevDecl)) {
+ auto *OldTag = dyn_cast<TagDecl>(PrevDecl);
+ if (SS.isEmpty() && TUK != TUK_Reference && TUK != TUK_Friend &&
+ isDeclInScope(Shadow, SearchDC, S, isExplicitSpecialization) &&
+ !(OldTag && isAcceptableTagRedeclContext(
+ *this, OldTag->getDeclContext(), SearchDC))) {
+ Diag(KWLoc, diag::err_using_decl_conflict_reverse);
+ Diag(Shadow->getTargetDecl()->getLocation(),
+ diag::note_using_decl_target);
+ Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl)
+ << 0;
+ // Recover by ignoring the old declaration.
+ Previous.clear();
+ goto CreateNewDecl;
+ }
+ }
+
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
// If this is a use of a previous tag, or if the tag is already declared
// in the same scope (so that the definition/declaration completes or
@@ -11763,7 +11880,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// struct or something similar.
if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind,
TUK == TUK_Definition, KWLoc,
- *Name)) {
+ Name)) {
bool SafeToContinue
= (PrevTagDecl->getTagKind() != TTK_Enum &&
Kind != TTK_Enum);
@@ -11940,7 +12057,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
Invalid = true;
// Otherwise, only diagnose if the declaration is in scope.
- } else if (!isDeclInScope(PrevDecl, SearchDC, S,
+ } else if (!isDeclInScope(DirectPrevDecl, SearchDC, S,
SS.isNotEmpty() || isExplicitSpecialization)) {
// do nothing
@@ -13619,12 +13736,9 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
// different from T:
// - every enumerator of every member of class T that is an unscoped
// enumerated type
- if (CXXRecordDecl *Record
- = dyn_cast<CXXRecordDecl>(
- TheEnumDecl->getDeclContext()->getRedeclContext()))
- if (!TheEnumDecl->isScoped() &&
- Record->getIdentifier() && Record->getIdentifier() == Id)
- Diag(IdLoc, diag::err_member_name_of_class) << Id;
+ if (!TheEnumDecl->isScoped())
+ DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(),
+ DeclarationNameInfo(Id, IdLoc));
EnumConstantDecl *New =
CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index b8d0830..191dbd0 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2985,11 +2985,27 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
// specifier shall have no effect
// C11 6.7.5p6:
// An alignment specification of zero has no effect.
- if (!(TmpAttr.isAlignas() && !Alignment) &&
- !llvm::isPowerOf2_64(Alignment.getZExtValue())) {
- Diag(AttrLoc, diag::err_alignment_not_power_of_two)
- << E->getSourceRange();
- return;
+ if (!(TmpAttr.isAlignas() && !Alignment)) {
+ if(!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
+ Diag(AttrLoc, diag::err_alignment_not_power_of_two)
+ << E->getSourceRange();
+ return;
+ }
+ if (Context.getTargetInfo().isTLSSupported()) {
+ if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->getTLSKind()) {
+ CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
+ if (Alignment.getSExtValue() > MaxAlignChars.getQuantity()) {
+ Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
+ << (unsigned)Alignment.getZExtValue() << VD
+ << (unsigned)MaxAlignChars.getQuantity();
+ return;
+ }
+ }
+ }
+ }
+ }
}
// Alignment calculations can wrap around if it's greater than 2**28.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index d0b2998..f42c4b7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -20,12 +20,15 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "TypeLocBuilder.h"
using namespace clang;
@@ -461,10 +464,424 @@ static void diagnoseUseOfProtocols(Sema &TheSema,
}
}
+void Sema::
+ActOnSuperClassOfClassInterface(Scope *S,
+ SourceLocation AtInterfaceLoc,
+ ObjCInterfaceDecl *IDecl,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs,
+ SourceRange SuperTypeArgsRange) {
+ // Check if a different kind of symbol declared in this scope.
+ NamedDecl *PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
+ LookupOrdinaryName);
+
+ if (!PrevDecl) {
+ // Try to correct for a typo in the superclass name without correcting
+ // to the class we're defining.
+ if (TypoCorrection Corrected = CorrectTypo(
+ DeclarationNameInfo(SuperName, SuperLoc),
+ LookupOrdinaryName, TUScope,
+ NULL, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
+ CTK_ErrorRecovery)) {
+ diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
+ << SuperName << ClassName);
+ PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
+ }
+ }
+
+ if (declaresSameEntity(PrevDecl, IDecl)) {
+ Diag(SuperLoc, diag::err_recursive_superclass)
+ << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+ IDecl->setEndOfDefinitionLoc(ClassLoc);
+ } else {
+ ObjCInterfaceDecl *SuperClassDecl =
+ dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+ QualType SuperClassType;
+
+ // Diagnose classes that inherit from deprecated classes.
+ if (SuperClassDecl) {
+ (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
+ SuperClassType = Context.getObjCInterfaceType(SuperClassDecl);
+ }
+
+ if (PrevDecl && SuperClassDecl == 0) {
+ // The previous declaration was not a class decl. Check if we have a
+ // typedef. If we do, get the underlying class type.
+ if (const TypedefNameDecl *TDecl =
+ dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
+ QualType T = TDecl->getUnderlyingType();
+ if (T->isObjCObjectType()) {
+ if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
+ SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+ SuperClassType = Context.getTypeDeclType(TDecl);
+
+ // This handles the following case:
+ // @interface NewI @end
+ // typedef NewI DeprI __attribute__((deprecated("blah")))
+ // @interface SI : DeprI /* warn here */ @end
+ (void)DiagnoseUseOfDecl(const_cast<TypedefNameDecl*>(TDecl), SuperLoc);
+ }
+ }
+ }
+
+ // This handles the following case:
+ //
+ // typedef int SuperClass;
+ // @interface MyClass : SuperClass {} @end
+ //
+ if (!SuperClassDecl) {
+ Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ }
+ }
+
+ if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
+ if (!SuperClassDecl)
+ Diag(SuperLoc, diag::err_undef_superclass)
+ << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+ else if (RequireCompleteType(SuperLoc,
+ SuperClassType,
+ diag::err_forward_superclass,
+ SuperClassDecl->getDeclName(),
+ ClassName,
+ SourceRange(AtInterfaceLoc, ClassLoc))) {
+ SuperClassDecl = 0;
+ SuperClassType = QualType();
+ }
+ }
+
+ if (SuperClassType.isNull()) {
+ assert(!SuperClassDecl && "Failed to set SuperClassType?");
+ return;
+ }
+
+ // Handle type arguments on the superclass.
+ TypeSourceInfo *SuperClassTInfo = nullptr;
+ if (!SuperTypeArgs.empty()) {
+ TypeResult fullSuperClassType = actOnObjCTypeArgsAndProtocolQualifiers(
+ S,
+ SuperLoc,
+ CreateParsedType(SuperClassType,
+ nullptr),
+ SuperTypeArgsRange.getBegin(),
+ SuperTypeArgs,
+ SuperTypeArgsRange.getEnd(),
+ SourceLocation(),
+ { },
+ { },
+ SourceLocation());
+ if (!fullSuperClassType.isUsable())
+ return;
+
+ SuperClassType = GetTypeFromParser(fullSuperClassType.get(),
+ &SuperClassTInfo);
+ }
+
+ if (!SuperClassTInfo) {
+ SuperClassTInfo = Context.getTrivialTypeSourceInfo(SuperClassType,
+ SuperLoc);
+ }
+
+ IDecl->setSuperClass(SuperClassTInfo);
+ IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getLocEnd());
+ }
+}
+
+DeclResult Sema::actOnObjCTypeParam(Scope *S,
+ ObjCTypeParamVariance variance,
+ SourceLocation varianceLoc,
+ unsigned index,
+ IdentifierInfo *paramName,
+ SourceLocation paramLoc,
+ SourceLocation colonLoc,
+ ParsedType parsedTypeBound) {
+ // If there was an explicitly-provided type bound, check it.
+ TypeSourceInfo *typeBoundInfo = nullptr;
+ if (parsedTypeBound) {
+ // The type bound can be any Objective-C pointer type.
+ QualType typeBound = GetTypeFromParser(parsedTypeBound, &typeBoundInfo);
+ if (typeBound->isObjCObjectPointerType()) {
+ // okay
+ } else if (typeBound->isObjCObjectType()) {
+ // The user forgot the * on an Objective-C pointer type, e.g.,
+ // "T : NSView".
+ SourceLocation starLoc = PP.getLocForEndOfToken(
+ typeBoundInfo->getTypeLoc().getEndLoc());
+ Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),
+ diag::err_objc_type_param_bound_missing_pointer)
+ << typeBound << paramName
+ << FixItHint::CreateInsertion(starLoc, " *");
+
+ // Create a new type location builder so we can update the type
+ // location information we have.
+ TypeLocBuilder builder;
+ builder.pushFullCopy(typeBoundInfo->getTypeLoc());
+
+ // Create the Objective-C pointer type.
+ typeBound = Context.getObjCObjectPointerType(typeBound);
+ ObjCObjectPointerTypeLoc newT
+ = builder.push<ObjCObjectPointerTypeLoc>(typeBound);
+ newT.setStarLoc(starLoc);
+
+ // Form the new type source information.
+ typeBoundInfo = builder.getTypeSourceInfo(Context, typeBound);
+ } else {
+ // Not a valid type bound.
+ Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),
+ diag::err_objc_type_param_bound_nonobject)
+ << typeBound << paramName;
+
+ // Forget the bound; we'll default to id later.
+ typeBoundInfo = nullptr;
+ }
+
+ // Type bounds cannot have explicit nullability.
+ if (typeBoundInfo) {
+ // Type arguments cannot explicitly specify nullability.
+ if (auto nullability = AttributedType::stripOuterNullability(typeBound)) {
+ // Look at the type location information to find the nullability
+ // specifier so we can zap it.
+ SourceLocation nullabilityLoc
+ = typeBoundInfo->getTypeLoc().findNullabilityLoc();
+ SourceLocation diagLoc
+ = nullabilityLoc.isValid()? nullabilityLoc
+ : typeBoundInfo->getTypeLoc().getLocStart();
+ Diag(diagLoc, diag::err_type_param_bound_explicit_nullability)
+ << paramName << typeBoundInfo->getType()
+ << FixItHint::CreateRemoval(nullabilityLoc);
+ }
+ }
+ }
+
+ // If there was no explicit type bound (or we removed it due to an error),
+ // use 'id' instead.
+ if (!typeBoundInfo) {
+ colonLoc = SourceLocation();
+ typeBoundInfo = Context.getTrivialTypeSourceInfo(Context.getObjCIdType());
+ }
+
+ // Create the type parameter.
+ return ObjCTypeParamDecl::Create(Context, CurContext, variance, varianceLoc,
+ index, paramLoc, paramName, colonLoc,
+ typeBoundInfo);
+}
+
+ObjCTypeParamList *Sema::actOnObjCTypeParamList(Scope *S,
+ SourceLocation lAngleLoc,
+ ArrayRef<Decl *> typeParamsIn,
+ SourceLocation rAngleLoc) {
+ // We know that the array only contains Objective-C type parameters.
+ ArrayRef<ObjCTypeParamDecl *>
+ typeParams(
+ reinterpret_cast<ObjCTypeParamDecl * const *>(typeParamsIn.data()),
+ typeParamsIn.size());
+
+ // Diagnose redeclarations of type parameters.
+ // We do this now because Objective-C type parameters aren't pushed into
+ // scope until later (after the instance variable block), but we want the
+ // diagnostics to occur right after we parse the type parameter list.
+ llvm::SmallDenseMap<IdentifierInfo *, ObjCTypeParamDecl *> knownParams;
+ for (auto typeParam : typeParams) {
+ auto known = knownParams.find(typeParam->getIdentifier());
+ if (known != knownParams.end()) {
+ Diag(typeParam->getLocation(), diag::err_objc_type_param_redecl)
+ << typeParam->getIdentifier()
+ << SourceRange(known->second->getLocation());
+
+ typeParam->setInvalidDecl();
+ } else {
+ knownParams.insert(std::make_pair(typeParam->getIdentifier(), typeParam));
+
+ // Push the type parameter into scope.
+ PushOnScopeChains(typeParam, S, /*AddToContext=*/false);
+ }
+ }
+
+ // Create the parameter list.
+ return ObjCTypeParamList::create(Context, lAngleLoc, typeParams, rAngleLoc);
+}
+
+void Sema::popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList) {
+ for (auto typeParam : *typeParamList) {
+ if (!typeParam->isInvalidDecl()) {
+ S->RemoveDecl(typeParam);
+ IdResolver.RemoveDecl(typeParam);
+ }
+ }
+}
+
+namespace {
+ /// The context in which an Objective-C type parameter list occurs, for use
+ /// in diagnostics.
+ enum class TypeParamListContext {
+ ForwardDeclaration,
+ Definition,
+ Category,
+ Extension
+ };
+}
+
+/// Check consistency between two Objective-C type parameter lists, e.g.,
+/// between a category/extension and an \@interface or between an \@class and an
+/// \@interface.
+static bool checkTypeParamListConsistency(Sema &S,
+ ObjCTypeParamList *prevTypeParams,
+ ObjCTypeParamList *newTypeParams,
+ TypeParamListContext newContext) {
+ // If the sizes don't match, complain about that.
+ if (prevTypeParams->size() != newTypeParams->size()) {
+ SourceLocation diagLoc;
+ if (newTypeParams->size() > prevTypeParams->size()) {
+ diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation();
+ } else {
+ diagLoc = S.PP.getLocForEndOfToken(newTypeParams->back()->getLocEnd());
+ }
+
+ S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch)
+ << static_cast<unsigned>(newContext)
+ << (newTypeParams->size() > prevTypeParams->size())
+ << prevTypeParams->size()
+ << newTypeParams->size();
+
+ return true;
+ }
+
+ // Match up the type parameters.
+ for (unsigned i = 0, n = prevTypeParams->size(); i != n; ++i) {
+ ObjCTypeParamDecl *prevTypeParam = prevTypeParams->begin()[i];
+ ObjCTypeParamDecl *newTypeParam = newTypeParams->begin()[i];
+
+ // Check for consistency of the variance.
+ if (newTypeParam->getVariance() != prevTypeParam->getVariance()) {
+ if (newTypeParam->getVariance() == ObjCTypeParamVariance::Invariant &&
+ newContext != TypeParamListContext::Definition) {
+ // When the new type parameter is invariant and is not part
+ // of the definition, just propagate the variance.
+ newTypeParam->setVariance(prevTypeParam->getVariance());
+ } else if (prevTypeParam->getVariance()
+ == ObjCTypeParamVariance::Invariant &&
+ !(isa<ObjCInterfaceDecl>(prevTypeParam->getDeclContext()) &&
+ cast<ObjCInterfaceDecl>(prevTypeParam->getDeclContext())
+ ->getDefinition() == prevTypeParam->getDeclContext())) {
+ // When the old parameter is invariant and was not part of the
+ // definition, just ignore the difference because it doesn't
+ // matter.
+ } else {
+ {
+ // Diagnose the conflict and update the second declaration.
+ SourceLocation diagLoc = newTypeParam->getVarianceLoc();
+ if (diagLoc.isInvalid())
+ diagLoc = newTypeParam->getLocStart();
+
+ auto diag = S.Diag(diagLoc,
+ diag::err_objc_type_param_variance_conflict)
+ << static_cast<unsigned>(newTypeParam->getVariance())
+ << newTypeParam->getDeclName()
+ << static_cast<unsigned>(prevTypeParam->getVariance())
+ << prevTypeParam->getDeclName();
+ switch (prevTypeParam->getVariance()) {
+ case ObjCTypeParamVariance::Invariant:
+ diag << FixItHint::CreateRemoval(newTypeParam->getVarianceLoc());
+ break;
+
+ case ObjCTypeParamVariance::Covariant:
+ case ObjCTypeParamVariance::Contravariant: {
+ StringRef newVarianceStr
+ = prevTypeParam->getVariance() == ObjCTypeParamVariance::Covariant
+ ? "__covariant"
+ : "__contravariant";
+ if (newTypeParam->getVariance()
+ == ObjCTypeParamVariance::Invariant) {
+ diag << FixItHint::CreateInsertion(newTypeParam->getLocStart(),
+ (newVarianceStr + " ").str());
+ } else {
+ diag << FixItHint::CreateReplacement(newTypeParam->getVarianceLoc(),
+ newVarianceStr);
+ }
+ }
+ }
+ }
+
+ S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)
+ << prevTypeParam->getDeclName();
+
+ // Override the variance.
+ newTypeParam->setVariance(prevTypeParam->getVariance());
+ }
+ }
+
+ // If the bound types match, there's nothing to do.
+ if (S.Context.hasSameType(prevTypeParam->getUnderlyingType(),
+ newTypeParam->getUnderlyingType()))
+ continue;
+
+ // If the new type parameter's bound was explicit, complain about it being
+ // different from the original.
+ if (newTypeParam->hasExplicitBound()) {
+ SourceRange newBoundRange = newTypeParam->getTypeSourceInfo()
+ ->getTypeLoc().getSourceRange();
+ S.Diag(newBoundRange.getBegin(), diag::err_objc_type_param_bound_conflict)
+ << newTypeParam->getUnderlyingType()
+ << newTypeParam->getDeclName()
+ << prevTypeParam->hasExplicitBound()
+ << prevTypeParam->getUnderlyingType()
+ << (newTypeParam->getDeclName() == prevTypeParam->getDeclName())
+ << prevTypeParam->getDeclName()
+ << FixItHint::CreateReplacement(
+ newBoundRange,
+ prevTypeParam->getUnderlyingType().getAsString(
+ S.Context.getPrintingPolicy()));
+
+ S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)
+ << prevTypeParam->getDeclName();
+
+ // Override the new type parameter's bound type with the previous type,
+ // so that it's consistent.
+ newTypeParam->setTypeSourceInfo(
+ S.Context.getTrivialTypeSourceInfo(prevTypeParam->getUnderlyingType()));
+ continue;
+ }
+
+ // The new type parameter got the implicit bound of 'id'. That's okay for
+ // categories and extensions (overwrite it later), but not for forward
+ // declarations and @interfaces, because those must be standalone.
+ if (newContext == TypeParamListContext::ForwardDeclaration ||
+ newContext == TypeParamListContext::Definition) {
+ // Diagnose this problem for forward declarations and definitions.
+ SourceLocation insertionLoc
+ = S.PP.getLocForEndOfToken(newTypeParam->getLocation());
+ std::string newCode
+ = " : " + prevTypeParam->getUnderlyingType().getAsString(
+ S.Context.getPrintingPolicy());
+ S.Diag(newTypeParam->getLocation(),
+ diag::err_objc_type_param_bound_missing)
+ << prevTypeParam->getUnderlyingType()
+ << newTypeParam->getDeclName()
+ << (newContext == TypeParamListContext::ForwardDeclaration)
+ << FixItHint::CreateInsertion(insertionLoc, newCode);
+
+ S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)
+ << prevTypeParam->getDeclName();
+ }
+
+ // Update the new type parameter's bound to match the previous one.
+ newTypeParam->setTypeSourceInfo(
+ S.Context.getTrivialTypeSourceInfo(prevTypeParam->getUnderlyingType()));
+ }
+
+ return false;
+}
+
Decl *Sema::
-ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ ObjCTypeParamList *typeParamList,
IdentifierInfo *SuperName, SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs,
+ SourceRange SuperTypeArgsRange,
Decl * const *ProtoRefs, unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc, AttributeList *AttrList) {
@@ -498,10 +915,50 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
ClassName = PrevIDecl->getIdentifier();
}
+ // If there was a forward declaration with type parameters, check
+ // for consistency.
+ if (PrevIDecl) {
+ if (ObjCTypeParamList *prevTypeParamList = PrevIDecl->getTypeParamList()) {
+ if (typeParamList) {
+ // Both have type parameter lists; check for consistency.
+ if (checkTypeParamListConsistency(*this, prevTypeParamList,
+ typeParamList,
+ TypeParamListContext::Definition)) {
+ typeParamList = nullptr;
+ }
+ } else {
+ Diag(ClassLoc, diag::err_objc_parameterized_forward_class_first)
+ << ClassName;
+ Diag(prevTypeParamList->getLAngleLoc(), diag::note_previous_decl)
+ << ClassName;
+
+ // Clone the type parameter list.
+ SmallVector<ObjCTypeParamDecl *, 4> clonedTypeParams;
+ for (auto typeParam : *prevTypeParamList) {
+ clonedTypeParams.push_back(
+ ObjCTypeParamDecl::Create(
+ Context,
+ CurContext,
+ typeParam->getVariance(),
+ SourceLocation(),
+ typeParam->getIndex(),
+ SourceLocation(),
+ typeParam->getIdentifier(),
+ SourceLocation(),
+ Context.getTrivialTypeSourceInfo(typeParam->getUnderlyingType())));
+ }
+
+ typeParamList = ObjCTypeParamList::create(Context,
+ SourceLocation(),
+ clonedTypeParams,
+ SourceLocation());
+ }
+ }
+ }
+
ObjCInterfaceDecl *IDecl
= ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName,
- PrevIDecl, ClassLoc);
-
+ typeParamList, PrevIDecl, ClassLoc);
if (PrevIDecl) {
// Class already seen. Was it a definition?
if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
@@ -522,84 +979,13 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IDecl->startDefinition();
if (SuperName) {
- // Check if a different kind of symbol declared in this scope.
- PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
- LookupOrdinaryName);
-
- if (!PrevDecl) {
- // Try to correct for a typo in the superclass name without correcting
- // to the class we're defining.
- if (TypoCorrection Corrected =
- CorrectTypo(DeclarationNameInfo(SuperName, SuperLoc),
- LookupOrdinaryName, TUScope, nullptr,
- llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
- CTK_ErrorRecovery)) {
- diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
- << SuperName << ClassName);
- PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
- }
- }
-
- if (declaresSameEntity(PrevDecl, IDecl)) {
- Diag(SuperLoc, diag::err_recursive_superclass)
- << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
- IDecl->setEndOfDefinitionLoc(ClassLoc);
- } else {
- ObjCInterfaceDecl *SuperClassDecl =
- dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
-
- // Diagnose availability in the context of the @interface.
- ContextRAII SavedContext(*this, IDecl);
- // Diagnose classes that inherit from deprecated classes.
- if (SuperClassDecl)
- (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
-
- if (PrevDecl && !SuperClassDecl) {
- // The previous declaration was not a class decl. Check if we have a
- // typedef. If we do, get the underlying class type.
- if (const TypedefNameDecl *TDecl =
- dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
- QualType T = TDecl->getUnderlyingType();
- if (T->isObjCObjectType()) {
- if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
- SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
- // This handles the following case:
- // @interface NewI @end
- // typedef NewI DeprI __attribute__((deprecated("blah")))
- // @interface SI : DeprI /* warn here */ @end
- (void)DiagnoseUseOfDecl(const_cast<TypedefNameDecl*>(TDecl), SuperLoc);
- }
- }
- }
+ // Diagnose availability in the context of the @interface.
+ ContextRAII SavedContext(*this, IDecl);
- // This handles the following case:
- //
- // typedef int SuperClass;
- // @interface MyClass : SuperClass {} @end
- //
- if (!SuperClassDecl) {
- Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
- Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- }
- }
-
- if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
- if (!SuperClassDecl)
- Diag(SuperLoc, diag::err_undef_superclass)
- << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
- else if (RequireCompleteType(SuperLoc,
- Context.getObjCInterfaceType(SuperClassDecl),
- diag::err_forward_superclass,
- SuperClassDecl->getDeclName(),
- ClassName,
- SourceRange(AtInterfaceLoc, ClassLoc))) {
- SuperClassDecl = nullptr;
- }
- }
- IDecl->setSuperClass(SuperClassDecl);
- IDecl->setSuperClassLoc(SuperLoc);
- IDecl->setEndOfDefinitionLoc(SuperLoc);
- }
+ ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl,
+ ClassName, ClassLoc,
+ SuperName, SuperLoc, SuperTypeArgs,
+ SuperTypeArgsRange);
} else { // we have a root class.
IDecl->setEndOfDefinitionLoc(ClassLoc);
}
@@ -846,6 +1232,400 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
}
}
+namespace {
+// Callback to only accept typo corrections that are either
+// Objective-C protocols or valid Objective-C type arguments.
+class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback {
+ ASTContext &Context;
+ Sema::LookupNameKind LookupKind;
+ public:
+ ObjCTypeArgOrProtocolValidatorCCC(ASTContext &context,
+ Sema::LookupNameKind lookupKind)
+ : Context(context), LookupKind(lookupKind) { }
+
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ // If we're allowed to find protocols and we have a protocol, accept it.
+ if (LookupKind != Sema::LookupOrdinaryName) {
+ if (candidate.getCorrectionDeclAs<ObjCProtocolDecl>())
+ return true;
+ }
+
+ // If we're allowed to find type names and we have one, accept it.
+ if (LookupKind != Sema::LookupObjCProtocolName) {
+ // If we have a type declaration, we might accept this result.
+ if (auto typeDecl = candidate.getCorrectionDeclAs<TypeDecl>()) {
+ // If we found a tag declaration outside of C++, skip it. This
+ // can happy because we look for any name when there is no
+ // bias to protocol or type names.
+ if (isa<RecordDecl>(typeDecl) && !Context.getLangOpts().CPlusPlus)
+ return false;
+
+ // Make sure the type is something we would accept as a type
+ // argument.
+ auto type = Context.getTypeDeclType(typeDecl);
+ if (type->isObjCObjectPointerType() ||
+ type->isBlockPointerType() ||
+ type->isDependentType() ||
+ type->isObjCObjectType())
+ return true;
+
+ return false;
+ }
+
+ // If we have an Objective-C class type, accept it; there will
+ // be another fix to add the '*'.
+ if (candidate.getCorrectionDeclAs<ObjCInterfaceDecl>())
+ return true;
+
+ return false;
+ }
+
+ return false;
+ }
+};
+} // end anonymous namespace
+
+void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
+ Scope *S,
+ ParsedType baseType,
+ 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.
+ unsigned numProtocolsResolved = 0;
+ auto resolvedAsProtocols = [&] {
+ assert(numProtocolsResolved == identifiers.size() && "Unresolved protocols");
+
+ // Determine whether the base type is a parameterized class, in
+ // which case we want to warn about typos such as
+ // "NSArray<NSObject>" (that should be NSArray<NSObject *>).
+ ObjCInterfaceDecl *baseClass = nullptr;
+ QualType base = GetTypeFromParser(baseType, nullptr);
+ bool allAreTypeNames = false;
+ SourceLocation firstClassNameLoc;
+ if (!base.isNull()) {
+ if (const auto *objcObjectType = base->getAs<ObjCObjectType>()) {
+ baseClass = objcObjectType->getInterface();
+ if (baseClass) {
+ if (auto typeParams = baseClass->getTypeParamList()) {
+ if (typeParams->size() == numProtocolsResolved) {
+ // Note that we should be looking for type names, too.
+ allAreTypeNames = true;
+ }
+ }
+ }
+ }
+ }
+
+ for (unsigned i = 0, n = protocols.size(); i != n; ++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) {
+ (void)DiagnoseUseOfDecl(proto, identifierLocs[i]);
+ }
+
+ // If this is a forward protocol declaration, get its definition.
+ if (!proto->isThisDeclarationADefinition() && proto->getDefinition())
+ proto = proto->getDefinition();
+
+ // If this is a forward declaration and we are supposed to warn in this
+ // case, do it.
+ // FIXME: Recover nicely in the hidden case.
+ ObjCProtocolDecl *forwardDecl = nullptr;
+ if (warnOnIncompleteProtocols &&
+ NestedProtocolHasNoDefinition(proto, forwardDecl)) {
+ Diag(identifierLocs[i], diag::warn_undef_protocolref)
+ << proto->getDeclName();
+ Diag(forwardDecl->getLocation(), diag::note_protocol_decl_undefined)
+ << forwardDecl;
+ }
+
+ // If everything this far has been a type name (and we care
+ // about such things), check whether this name refers to a type
+ // as well.
+ if (allAreTypeNames) {
+ if (auto *decl = LookupSingleName(S, identifiers[i], identifierLocs[i],
+ LookupOrdinaryName)) {
+ if (isa<ObjCInterfaceDecl>(decl)) {
+ if (firstClassNameLoc.isInvalid())
+ firstClassNameLoc = identifierLocs[i];
+ } else if (!isa<TypeDecl>(decl)) {
+ // Not a type.
+ allAreTypeNames = false;
+ }
+ } else {
+ allAreTypeNames = false;
+ }
+ }
+ }
+
+ // All of the protocols listed also have type names, and at least
+ // one is an Objective-C class name. Check whether all of the
+ // protocol conformances are declared by the base class itself, in
+ // which case we warn.
+ if (allAreTypeNames && firstClassNameLoc.isValid()) {
+ llvm::SmallPtrSet<ObjCProtocolDecl*, 8> knownProtocols;
+ Context.CollectInheritedProtocols(baseClass, knownProtocols);
+ bool allProtocolsDeclared = true;
+ for (auto proto : protocols) {
+ if (knownProtocols.count(static_cast<ObjCProtocolDecl *>(proto)) == 0) {
+ allProtocolsDeclared = false;
+ break;
+ }
+ }
+
+ if (allProtocolsDeclared) {
+ Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type)
+ << baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc)
+ << FixItHint::CreateInsertion(
+ PP.getLocForEndOfToken(firstClassNameLoc), " *");
+ }
+ }
+
+ protocolLAngleLoc = lAngleLoc;
+ protocolRAngleLoc = rAngleLoc;
+ assert(protocols.size() == identifierLocs.size());
+ };
+
+ // Attempt to resolve all of the identifiers as protocols.
+ for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
+ ObjCProtocolDecl *proto = LookupProtocol(identifiers[i], identifierLocs[i]);
+ protocols.push_back(proto);
+ if (proto)
+ ++numProtocolsResolved;
+ }
+
+ // If all of the names were protocols, these were protocol qualifiers.
+ if (numProtocolsResolved == identifiers.size())
+ return resolvedAsProtocols();
+
+ // Attempt to resolve all of the identifiers as type names or
+ // Objective-C class names. The latter is technically ill-formed,
+ // but is probably something like \c NSArray<NSView *> missing the
+ // \c*.
+ typedef llvm::PointerUnion<TypeDecl *, ObjCInterfaceDecl *> TypeOrClassDecl;
+ SmallVector<TypeOrClassDecl, 4> typeDecls;
+ unsigned numTypeDeclsResolved = 0;
+ for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
+ NamedDecl *decl = LookupSingleName(S, identifiers[i], identifierLocs[i],
+ LookupOrdinaryName);
+ if (!decl) {
+ typeDecls.push_back(TypeOrClassDecl());
+ continue;
+ }
+
+ if (auto typeDecl = dyn_cast<TypeDecl>(decl)) {
+ typeDecls.push_back(typeDecl);
+ ++numTypeDeclsResolved;
+ continue;
+ }
+
+ if (auto objcClass = dyn_cast<ObjCInterfaceDecl>(decl)) {
+ typeDecls.push_back(objcClass);
+ ++numTypeDeclsResolved;
+ continue;
+ }
+
+ typeDecls.push_back(TypeOrClassDecl());
+ }
+
+ AttributeFactory attrFactory;
+
+ // Local function that forms a reference to the given type or
+ // Objective-C class declaration.
+ auto resolveTypeReference = [&](TypeOrClassDecl typeDecl, SourceLocation loc)
+ -> TypeResult {
+ // Form declaration specifiers. They simply refer to the type.
+ DeclSpec DS(attrFactory);
+ const char* prevSpec; // unused
+ unsigned diagID; // unused
+ QualType type;
+ if (auto *actualTypeDecl = typeDecl.dyn_cast<TypeDecl *>())
+ type = Context.getTypeDeclType(actualTypeDecl);
+ else
+ type = Context.getObjCInterfaceType(typeDecl.get<ObjCInterfaceDecl *>());
+ TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc);
+ ParsedType parsedType = CreateParsedType(type, parsedTSInfo);
+ DS.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, diagID,
+ parsedType, Context.getPrintingPolicy());
+ // Use the identifier location for the type source range.
+ DS.SetRangeStart(loc);
+ DS.SetRangeEnd(loc);
+
+ // Form the declarator.
+ Declarator D(DS, Declarator::TypeNameContext);
+
+ // If we have a typedef of an Objective-C class type that is missing a '*',
+ // add the '*'.
+ if (type->getAs<ObjCInterfaceType>()) {
+ SourceLocation starLoc = PP.getLocForEndOfToken(loc);
+ ParsedAttributes parsedAttrs(attrFactory);
+ D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc,
+ SourceLocation(),
+ SourceLocation(),
+ SourceLocation(),
+ SourceLocation()),
+ parsedAttrs,
+ starLoc);
+
+ // Diagnose the missing '*'.
+ Diag(loc, diag::err_objc_type_arg_missing_star)
+ << type
+ << FixItHint::CreateInsertion(starLoc, " *");
+ }
+
+ // Convert this to a type.
+ return ActOnTypeName(S, D);
+ };
+
+ // 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.
+ 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()) {
+ typeArgs.clear();
+ return;
+ }
+
+ typeArgs.push_back(type.get());
+ }
+
+ typeArgsLAngleLoc = lAngleLoc;
+ typeArgsRAngleLoc = rAngleLoc;
+ };
+
+ // If all of the identifiers can be resolved as type names or
+ // Objective-C class names, we have type arguments.
+ if (numTypeDeclsResolved == identifiers.size())
+ return resolvedAsTypeDecls();
+
+ // Error recovery: some names weren't found, or we have a mix of
+ // type and protocol names. Go resolve all of the unresolved names
+ // and complain if we can't find a consistent answer.
+ LookupNameKind lookupKind = LookupAnyName;
+ for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
+ // If we already have a protocol or type. Check whether it is the
+ // right thing.
+ if (protocols[i] || typeDecls[i]) {
+ // If we haven't figured out whether we want types or protocols
+ // yet, try to figure it out from this name.
+ if (lookupKind == LookupAnyName) {
+ // If this name refers to both a protocol and a type (e.g., \c
+ // NSObject), don't conclude anything yet.
+ if (protocols[i] && typeDecls[i])
+ continue;
+
+ // Otherwise, let this name decide whether we'll be correcting
+ // toward types or protocols.
+ lookupKind = protocols[i] ? LookupObjCProtocolName
+ : LookupOrdinaryName;
+ continue;
+ }
+
+ // If we want protocols and we have a protocol, there's nothing
+ // more to do.
+ if (lookupKind == LookupObjCProtocolName && protocols[i])
+ continue;
+
+ // If we want types and we have a type declaration, there's
+ // nothing more to do.
+ if (lookupKind == LookupOrdinaryName && typeDecls[i])
+ continue;
+
+ // We have a conflict: some names refer to protocols and others
+ // refer to types.
+ Diag(identifierLocs[i], diag::err_objc_type_args_and_protocols)
+ << (protocols[i] != nullptr)
+ << identifiers[i]
+ << identifiers[0]
+ << SourceRange(identifierLocs[0]);
+
+ protocols.clear();
+ typeArgs.clear();
+ return;
+ }
+
+ // Perform typo correction on the name.
+ TypoCorrection corrected = CorrectTypo(
+ DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S,
+ nullptr,
+ llvm::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(Context,
+ lookupKind),
+ CTK_ErrorRecovery);
+ if (corrected) {
+ // Did we find a protocol?
+ if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) {
+ diagnoseTypo(corrected,
+ PDiag(diag::err_undeclared_protocol_suggest)
+ << identifiers[i]);
+ lookupKind = LookupObjCProtocolName;
+ protocols[i] = proto;
+ ++numProtocolsResolved;
+ continue;
+ }
+
+ // Did we find a type?
+ if (auto typeDecl = corrected.getCorrectionDeclAs<TypeDecl>()) {
+ diagnoseTypo(corrected,
+ PDiag(diag::err_unknown_typename_suggest)
+ << identifiers[i]);
+ lookupKind = LookupOrdinaryName;
+ typeDecls[i] = typeDecl;
+ ++numTypeDeclsResolved;
+ continue;
+ }
+
+ // Did we find an Objective-C class?
+ if (auto objcClass = corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
+ diagnoseTypo(corrected,
+ PDiag(diag::err_unknown_type_or_class_name_suggest)
+ << identifiers[i] << true);
+ lookupKind = LookupOrdinaryName;
+ typeDecls[i] = objcClass;
+ ++numTypeDeclsResolved;
+ continue;
+ }
+ }
+
+ // We couldn't find anything.
+ Diag(identifierLocs[i],
+ (lookupKind == LookupAnyName ? diag::err_objc_type_arg_missing
+ : lookupKind == LookupObjCProtocolName ? diag::err_undeclared_protocol
+ : diag::err_unknown_typename))
+ << identifiers[i];
+ protocols.clear();
+ typeArgs.clear();
+ return;
+ }
+
+ // If all of the names were (corrected to) protocols, these were
+ // protocol qualifiers.
+ if (numProtocolsResolved == identifiers.size())
+ return resolvedAsProtocols();
+
+ // Otherwise, all of the names were (corrected to) types.
+ assert(numTypeDeclsResolved == identifiers.size() && "Not all types?");
+ return resolvedAsTypeDecls();
+}
+
/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of
/// a class method in its extension.
///
@@ -906,6 +1686,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
Decl *Sema::
ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ ObjCTypeParamList *typeParamList,
IdentifierInfo *CategoryName,
SourceLocation CategoryLoc,
Decl * const *ProtoRefs,
@@ -925,7 +1706,8 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
// the enclosing method declarations. We mark the decl invalid
// to make it clear that this isn't a valid AST.
CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
- ClassLoc, CategoryLoc, CategoryName,IDecl);
+ ClassLoc, CategoryLoc, CategoryName,
+ IDecl, typeParamList);
CDecl->setInvalidDecl();
CurContext->addDecl(CDecl);
@@ -951,8 +1733,28 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
}
}
+ // If we have a type parameter list, check it.
+ if (typeParamList) {
+ if (auto prevTypeParamList = IDecl->getTypeParamList()) {
+ if (checkTypeParamListConsistency(*this, prevTypeParamList, typeParamList,
+ CategoryName
+ ? TypeParamListContext::Category
+ : TypeParamListContext::Extension))
+ typeParamList = nullptr;
+ } else {
+ Diag(typeParamList->getLAngleLoc(),
+ diag::err_objc_parameterized_category_nonclass)
+ << (CategoryName != nullptr)
+ << ClassName
+ << typeParamList->getSourceRange();
+
+ typeParamList = nullptr;
+ }
+ }
+
CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
- ClassLoc, CategoryLoc, CategoryName, IDecl);
+ ClassLoc, CategoryLoc, CategoryName, IDecl,
+ typeParamList);
// FIXME: PushOnScopeChains?
CurContext->addDecl(CDecl);
@@ -987,7 +1789,8 @@ Decl *Sema::ActOnStartCategoryImplementation(
// Create and install one.
CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, AtCatImplLoc,
ClassLoc, CatLoc,
- CatName, IDecl);
+ CatName, IDecl,
+ /*typeParamList=*/nullptr);
CatIDecl->setImplicit();
}
}
@@ -1101,12 +1904,14 @@ Decl *Sema::ActOnStartClassImplementation(
// FIXME: Do we support attributes on the @implementation? If so we should
// copy them over.
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
- ClassName, /*PrevDecl=*/nullptr, ClassLoc,
+ ClassName, /*typeParamList=*/nullptr,
+ /*PrevDecl=*/nullptr, ClassLoc,
true);
IDecl->startDefinition();
if (SDecl) {
- IDecl->setSuperClass(SDecl);
- IDecl->setSuperClassLoc(SuperClassLoc);
+ IDecl->setSuperClass(Context.getTrivialTypeSourceInfo(
+ Context.getObjCInterfaceType(SDecl),
+ SuperClassLoc));
IDecl->setEndOfDefinitionLoc(SuperClassLoc);
} else {
IDecl->setEndOfDefinitionLoc(ClassLoc);
@@ -2083,6 +2888,7 @@ Sema::DeclGroupPtrTy
Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
SourceLocation *IdentLocs,
+ ArrayRef<ObjCTypeParamList *> TypeParamLists,
unsigned NumElts) {
SmallVector<Decl *, 8> DeclsInGroup;
for (unsigned i = 0; i != NumElts; ++i) {
@@ -2137,9 +2943,33 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
ClassName = PrevIDecl->getIdentifier();
}
+ // If this forward declaration has type parameters, compare them with the
+ // type parameters of the previous declaration.
+ ObjCTypeParamList *TypeParams = TypeParamLists[i];
+ if (PrevIDecl && TypeParams) {
+ if (ObjCTypeParamList *PrevTypeParams = PrevIDecl->getTypeParamList()) {
+ // Check for consistency with the previous declaration.
+ if (checkTypeParamListConsistency(
+ *this, PrevTypeParams, TypeParams,
+ TypeParamListContext::ForwardDeclaration)) {
+ TypeParams = nullptr;
+ }
+ } else if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
+ // The @interface does not have type parameters. Complain.
+ Diag(IdentLocs[i], diag::err_objc_parameterized_forward_class)
+ << ClassName
+ << TypeParams->getSourceRange();
+ Diag(Def->getLocation(), diag::note_defined_here)
+ << ClassName;
+
+ TypeParams = nullptr;
+ }
+ }
+
ObjCInterfaceDecl *IDecl
= ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
- ClassName, PrevIDecl, IdentLocs[i]);
+ ClassName, TypeParams, PrevIDecl,
+ IdentLocs[i]);
IDecl->setAtEndRange(IdentLocs[i]);
PushOnScopeChains(IDecl, TUScope);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index 2e3e63e..0941870 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -397,7 +397,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
// - both are dynamic-exception-specifications that have the same set of
// adjusted types.
//
- // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is
+ // C++0x [except.spec]p12: An exception-specification is non-throwing if it is
// of the form throw(), noexcept, or noexcept(constant-expression) where the
// constant-expression yields true.
//
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index c023c85..1ae983c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -2466,8 +2466,8 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
ObjCIvarRefExpr *Result = new (Context)
- ObjCIvarRefExpr(IV, IV->getType(), Loc, IV->getLocation(),
- SelfExpr.get(), true, true);
+ ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc,
+ IV->getLocation(), SelfExpr.get(), true, true);
if (getLangOpts().ObjCAutoRefCount) {
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
@@ -5185,17 +5185,17 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
}
/// Do an explicit extend of the given block pointer if we're in ARC.
-static void maybeExtendBlockObject(Sema &S, ExprResult &E) {
+void Sema::maybeExtendBlockObject(ExprResult &E) {
assert(E.get()->getType()->isBlockPointerType());
assert(E.get()->isRValue());
// Only do this in an r-value context.
- if (!S.getLangOpts().ObjCAutoRefCount) return;
+ if (!getLangOpts().ObjCAutoRefCount) return;
- E = ImplicitCastExpr::Create(S.Context, E.get()->getType(),
+ E = ImplicitCastExpr::Create(Context, E.get()->getType(),
CK_ARCExtendBlockObject, E.get(),
/*base path*/ nullptr, VK_RValue);
- S.ExprNeedsCleanups = true;
+ ExprNeedsCleanups = true;
}
/// Prepare a conversion of the given expression to an ObjC object
@@ -5205,7 +5205,7 @@ CastKind Sema::PrepareCastToObjCObjectPointer(ExprResult &E) {
if (type->isObjCObjectPointerType()) {
return CK_BitCast;
} else if (type->isBlockPointerType()) {
- maybeExtendBlockObject(*this, E);
+ maybeExtendBlockObject(E);
return CK_BlockPointerToObjCPointerCast;
} else {
assert(type->isPointerType());
@@ -5247,7 +5247,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
return CK_BitCast;
if (SrcKind == Type::STK_CPointer)
return CK_CPointerToObjCPointerCast;
- maybeExtendBlockObject(*this, Src);
+ maybeExtendBlockObject(Src);
return CK_BlockPointerToObjCPointerCast;
case Type::STK_Bool:
return CK_PointerToBoolean;
@@ -5826,36 +5826,6 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
return ResultTy;
}
-/// \brief Returns true if QT is quelified-id and implements 'NSObject' and/or
-/// 'NSCopying' protocols (and nothing else); or QT is an NSObject and optionally
-/// implements 'NSObject' and/or NSCopying' protocols (and nothing else).
-static bool isObjCPtrBlockCompatible(Sema &S, ASTContext &C, QualType QT) {
- if (QT->isObjCIdType())
- return true;
-
- const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>();
- if (!OPT)
- return false;
-
- if (ObjCInterfaceDecl *ID = OPT->getInterfaceDecl())
- if (ID->getIdentifier() != &C.Idents.get("NSObject"))
- return false;
-
- ObjCProtocolDecl* PNSCopying =
- S.LookupProtocol(&C.Idents.get("NSCopying"), SourceLocation());
- ObjCProtocolDecl* PNSObject =
- S.LookupProtocol(&C.Idents.get("NSObject"), SourceLocation());
-
- for (auto *Proto : OPT->quals()) {
- if ((PNSCopying && declaresSameEntity(Proto, PNSCopying)) ||
- (PNSObject && declaresSameEntity(Proto, PNSObject)))
- ;
- else
- return false;
- }
- return true;
-}
-
/// \brief Return the resulting type when the operands are both block pointers.
static QualType checkConditionalBlockPointerCompatibility(Sema &S,
ExprResult &LHS,
@@ -6303,7 +6273,10 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
// FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
// It could return the composite type.
- if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
+ if (!(compositeType =
+ Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) {
+ // Nothing more to do.
+ } else if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy;
} else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {
compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy;
@@ -6317,10 +6290,7 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
compositeType = Context.getObjCIdType();
} else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
compositeType = Context.getObjCIdType();
- } else if (!(compositeType =
- Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull())
- ;
- else {
+ } else {
Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
@@ -7008,9 +6978,9 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
}
// Only under strict condition T^ is compatible with an Objective-C pointer.
- if (RHSType->isBlockPointerType() &&
- isObjCPtrBlockCompatible(*this, Context, LHSType)) {
- maybeExtendBlockObject(*this, RHS);
+ if (RHSType->isBlockPointerType() &&
+ LHSType->isBlockCompatibleObjCPointerType(Context)) {
+ maybeExtendBlockObject(RHS);
Kind = CK_BlockPointerToObjCPointerCast;
return Compatible;
}
@@ -7937,9 +7907,19 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
// representable in the result type, so never warn for those.
llvm::APSInt Left;
if (LHS.get()->isValueDependent() ||
- !LHS.get()->isIntegerConstantExpr(Left, S.Context) ||
- LHSType->hasUnsignedIntegerRepresentation())
+ LHSType->hasUnsignedIntegerRepresentation() ||
+ !LHS.get()->EvaluateAsInt(Left, S.Context))
return;
+
+ // If LHS does not have a signed type and non-negative value
+ // then, the behavior is undefined. Warn about it.
+ if (Left.isNegative()) {
+ S.DiagRuntimeBehavior(Loc, LHS.get(),
+ S.PDiag(diag::warn_shift_lhs_negative)
+ << LHS.get()->getSourceRange());
+ return;
+ }
+
llvm::APInt ResultBits =
static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits();
if (LeftBits.uge(ResultBits))
@@ -8209,9 +8189,6 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
// Get the LHS object's interface type.
QualType InterfaceType = Type->getPointeeType();
- if (const ObjCObjectType *iQFaceTy =
- InterfaceType->getAsObjCQualifiedInterfaceType())
- InterfaceType = iQFaceTy->getBaseType();
// If the RHS isn't an Objective-C object, bail out.
if (!RHS->getType()->isObjCObjectPointerType())
@@ -12556,6 +12533,8 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
// By default, capture variables by reference.
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
+ if (S.getLangOpts().OpenMP && S.IsOpenMPCapturedVar(Var))
+ DeclRefType = DeclRefType.getUnqualifiedType();
CaptureType = S.Context.getLValueReferenceType(DeclRefType);
Expr *CopyExpr = nullptr;
if (BuildAndDiagnose) {
@@ -12789,6 +12768,7 @@ bool Sema::tryCaptureVariable(
if (RSI->CapRegionKind == CR_OpenMP) {
if (isOpenMPPrivateVar(Var, OpenMPLevel)) {
Nested = true;
+ DeclRefType = DeclRefType.getUnqualifiedType();
CaptureType = Context.getLValueReferenceType(DeclRefType);
break;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
index e421349..a9f1919 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
@@ -1378,7 +1378,8 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
}
ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr(
- IV, IV->getType(), MemberLoc, OpLoc, BaseExpr.get(), IsArrow);
+ IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(),
+ IsArrow);
if (S.getLangOpts().ObjCAutoRefCount) {
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
index c52b6f5..6cd0626 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -133,7 +133,7 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
ObjCInterfaceDecl::Create (Context,
Context.getTranslationUnitDecl(),
SourceLocation(), NSIdent,
- nullptr, SourceLocation());
+ nullptr, nullptr, SourceLocation());
Ty = Context.getObjCInterfaceType(NSStringIDecl);
Context.setObjCNSStringType(Ty);
}
@@ -208,7 +208,8 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
S.NSNumberDecl = ObjCInterfaceDecl::Create(CX,
CX.getTranslationUnitDecl(),
SourceLocation(), NSNumberId,
- nullptr, SourceLocation());
+ nullptr, nullptr,
+ SourceLocation());
} else {
// Otherwise, require a declaration of NSNumber.
S.Diag(Loc, diag::err_undeclared_nsnumber);
@@ -475,7 +476,8 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
NSStringDecl = ObjCInterfaceDecl::Create(Context, TU,
SourceLocation(),
NSStringId,
- nullptr, SourceLocation());
+ nullptr, nullptr,
+ SourceLocation());
} else {
Diag(SR.getBegin(), diag::err_undeclared_nsstring);
return ExprError();
@@ -591,7 +593,8 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
DeclContext *TU = Context.getTranslationUnitDecl();
NSValueDecl = ObjCInterfaceDecl::Create(Context, TU,
SourceLocation(), NSValueId,
- nullptr, SourceLocation());
+ nullptr, nullptr,
+ SourceLocation());
} else {
// Otherwise, require a declaration of NSValue.
Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
@@ -755,7 +758,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
Context.getTranslationUnitDecl(),
SourceLocation(),
NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
- nullptr, SourceLocation());
+ nullptr, nullptr, SourceLocation());
if (!NSArrayDecl) {
Diag(SR.getBegin(), diag::err_undeclared_nsarray);
@@ -870,7 +873,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
Context.getTranslationUnitDecl(),
SourceLocation(),
NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
- nullptr, SourceLocation());
+ nullptr, nullptr, SourceLocation());
if (!NSDictionaryDecl) {
Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
@@ -956,8 +959,11 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
QIDNSCopying =
- Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
- (ObjCProtocolDecl**) PQ,1);
+ Context.getObjCObjectType(Context.ObjCBuiltinIdTy, { },
+ llvm::makeArrayRef(
+ (ObjCProtocolDecl**) PQ,
+ 1),
+ false);
QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);
}
}
@@ -1276,7 +1282,7 @@ static QualType getBaseMessageSendResultType(Sema &S,
bool isSuperMessage) {
assert(Method && "Must have a method");
if (!Method->hasRelatedResultType())
- return Method->getSendResultType();
+ return Method->getSendResultType(ReceiverType);
ASTContext &Context = S.Context;
@@ -1284,7 +1290,8 @@ static QualType getBaseMessageSendResultType(Sema &S,
// result type to the returned result.
auto transferNullability = [&](QualType type) -> QualType {
// If the method's result type has nullability, extract it.
- if (auto nullability = Method->getSendResultType()->getNullability(Context)){
+ if (auto nullability = Method->getSendResultType(ReceiverType)
+ ->getNullability(Context)){
// Strip off any outer nullability sugar from the provided type.
(void)AttributedType::stripOuterNullability(type);
@@ -1303,7 +1310,8 @@ static QualType getBaseMessageSendResultType(Sema &S,
// was a class message send, T is the declared return type of the method
// found
if (Method->isInstanceMethod() && isClassMessage)
- return stripObjCInstanceType(Context, Method->getSendResultType());
+ return stripObjCInstanceType(Context,
+ Method->getSendResultType(ReceiverType));
// - if the receiver is super, T is a pointer to the class of the
// enclosing method definition
@@ -1317,14 +1325,14 @@ static QualType getBaseMessageSendResultType(Sema &S,
}
// - if the receiver is the name of a class U, T is a pointer to U
- if (ReceiverType->getAs<ObjCInterfaceType>() ||
- ReceiverType->isObjCQualifiedInterfaceType())
+ if (ReceiverType->getAsObjCInterfaceType())
return transferNullability(Context.getObjCObjectPointerType(ReceiverType));
// - if the receiver is of type Class or qualified Class type,
// T is the declared return type of the method.
if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType())
- return stripObjCInstanceType(Context, Method->getSendResultType());
+ return stripObjCInstanceType(Context,
+ Method->getSendResultType(ReceiverType));
// - if the receiver is id, qualified id, Class, or qualified Class, T
// is the receiver type, otherwise
@@ -1587,6 +1595,10 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
return false;
}
+ // Compute the set of type arguments to be substituted into each parameter
+ // type.
+ Optional<ArrayRef<QualType>> typeArgs
+ = ReceiverType->getObjCSubstitutions(Method->getDeclContext());
bool IsError = false;
for (unsigned i = 0; i < NumNamedArgs; i++) {
// We can't do any type-checking on a type-dependent argument.
@@ -1620,18 +1632,37 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
continue;
}
+ QualType origParamType = param->getType();
+ QualType paramType = param->getType();
+ if (typeArgs)
+ paramType = paramType.substObjCTypeArgs(
+ Context,
+ *typeArgs,
+ ObjCSubstitutionContext::Parameter);
+
if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
- param->getType(),
+ paramType,
diag::err_call_incomplete_argument, argExpr))
return true;
- InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
- param);
+ InitializedEntity Entity
+ = InitializedEntity::InitializeParameter(Context, param, paramType);
ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), argExpr);
if (ArgE.isInvalid())
IsError = true;
- else
+ else {
Args[i] = ArgE.getAs<Expr>();
+
+ // If we are type-erasing a block to a block-compatible
+ // Objective-C pointer type, we may need to extend the lifetime
+ // of the block object.
+ if (typeArgs && Args[i]->isRValue() && paramType->isBlockPointerType() &&
+ origParamType->isBlockCompatibleObjCPointerType(Context)) {
+ ExprResult arg = Args[i];
+ maybeExtendBlockObject(arg);
+ Args[i] = arg.get();
+ }
+ }
}
// Promote additional arguments to variadic methods.
@@ -1899,27 +1930,24 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr,
receiverNameLoc);
- bool IsSuper = false;
+ QualType SuperType;
if (!IFace) {
// If the "receiver" is 'super' in a method, handle it as an expression-like
// property reference.
if (receiverNamePtr->isStr("super")) {
- IsSuper = true;
-
if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) {
- if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) {
+ if (auto classDecl = CurMethod->getClassInterface()) {
+ SuperType = QualType(classDecl->getSuperClassType(), 0);
if (CurMethod->isInstanceMethod()) {
- ObjCInterfaceDecl *Super = Class->getSuperClass();
- if (!Super) {
+ if (SuperType.isNull()) {
// The current class does not have a superclass.
Diag(receiverNameLoc, diag::error_root_class_cannot_use_super)
- << Class->getIdentifier();
+ << CurMethod->getClassInterface()->getIdentifier();
return ExprError();
}
- QualType T = Context.getObjCInterfaceType(Super);
- T = Context.getObjCObjectPointerType(T);
+ QualType T = Context.getObjCObjectPointerType(SuperType);
- return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
+ return HandleExprPropertyRefExpr(T->castAs<ObjCObjectPointerType>(),
/*BaseExpr*/nullptr,
SourceLocation()/*OpLoc*/,
&propertyName,
@@ -1929,7 +1957,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
// Otherwise, if this is a class method, try dispatching to our
// superclass.
- IFace = Class->getSuperClass();
+ IFace = CurMethod->getClassInterface()->getSuperClass();
}
}
}
@@ -1959,7 +1987,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
// Look for the matching setter, in case it is needed.
Selector SetterSel =
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
- PP.getSelectorTable(),
+ PP.getSelectorTable(),
&propertyName);
ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
@@ -1976,11 +2004,11 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
return ExprError();
if (Getter || Setter) {
- if (IsSuper)
+ if (!SuperType.isNull())
return new (Context)
ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
OK_ObjCProperty, propertyNameLoc, receiverNameLoc,
- Context.getObjCInterfaceType(IFace));
+ SuperType);
return new (Context) ObjCPropertyRefExpr(
Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty,
@@ -2127,8 +2155,8 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
return ExprError();
}
- ObjCInterfaceDecl *Super = Class->getSuperClass();
- if (!Super) {
+ QualType SuperTy(Class->getSuperClassType(), 0);
+ if (SuperTy.isNull()) {
// The current class does not have a superclass.
Diag(SuperLoc, diag::error_root_class_cannot_use_super)
<< Class->getIdentifier();
@@ -2143,7 +2171,6 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
if (Method->isInstanceMethod()) {
// Since we are in an instance method, this is an instance
// message to the superclass instance.
- QualType SuperTy = Context.getObjCInterfaceType(Super);
SuperTy = Context.getObjCObjectPointerType(SuperTy);
return BuildInstanceMessage(nullptr, SuperTy, SuperLoc,
Sel, /*Method=*/nullptr,
@@ -2153,7 +2180,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
// Since we are in a class method, this is a class message to
// the superclass.
return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr,
- Context.getObjCInterfaceType(Super),
+ SuperTy,
SuperLoc, Sel, /*Method=*/nullptr,
LBracLoc, SelectorLocs, RBracLoc, Args);
}
@@ -2594,35 +2621,41 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// of the more detailed type-checking on the receiver.
if (!Method) {
- // Handle messages to id.
- bool receiverIsId = ReceiverType->isObjCIdType();
- if (receiverIsId || ReceiverType->isBlockPointerType() ||
+ // Handle messages to id and __kindof types (where we use the
+ // global method pool).
+ // FIXME: The type bound is currently ignored by lookup in the
+ // global pool.
+ const ObjCObjectType *typeBound = nullptr;
+ bool receiverIsIdLike = ReceiverType->isObjCIdOrObjectKindOfType(Context,
+ typeBound);
+ if (receiverIsIdLike || ReceiverType->isBlockPointerType() ||
(Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc),
- receiverIsId);
+ receiverIsIdLike);
if (!Method)
Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LBracLoc,RBracLoc),
- receiverIsId);
+ receiverIsIdLike);
if (Method) {
if (ObjCMethodDecl *BestMethod =
SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))
Method = BestMethod;
if (!AreMultipleMethodsInGlobalPool(Sel, Method,
SourceRange(LBracLoc, RBracLoc),
- receiverIsId)) {
+ receiverIsIdLike)) {
DiagnoseUseOfDecl(Method, SelLoc);
}
}
- } else if (ReceiverType->isObjCClassType() ||
+ } else if (ReceiverType->isObjCClassOrClassKindOfType() ||
ReceiverType->isObjCQualifiedClassType()) {
// Handle messages to Class.
// We allow sending a message to a qualified Class ("Class<foo>"), which
// is ok as long as one of the protocols implements the selector (if not,
// warn).
- if (const ObjCObjectPointerType *QClassTy
- = ReceiverType->getAsObjCQualifiedClassType()) {
+ if (!ReceiverType->isObjCClassOrClassKindOfType()) {
+ const ObjCObjectPointerType *QClassTy
+ = ReceiverType->getAsObjCQualifiedClassType();
// Search protocols for class methods.
Method = LookupMethodInQualifiedType(Sel, QClassTy, false);
if (!Method) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
index 0f88abc..f139c83 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -1157,7 +1157,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
CK_LValueToRValue, SelfExpr, nullptr,
VK_RValue);
Expr *IvarRefExpr =
- new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
+ new (Context) ObjCIvarRefExpr(Ivar,
+ Ivar->getUsageType(SelfDecl->getType()),
+ PropertyDiagLoc,
Ivar->getLocation(),
LoadSelfExpr, true, true);
ExprResult Res = PerformCopyInitialization(
@@ -1207,7 +1209,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
CK_LValueToRValue, SelfExpr, nullptr,
VK_RValue);
Expr *lhs =
- new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
+ new (Context) ObjCIvarRefExpr(Ivar,
+ Ivar->getUsageType(SelfDecl->getType()),
+ PropertyDiagLoc,
Ivar->getLocation(),
LoadSelfExpr, true, true);
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
index 867cb9f..4030d9e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
@@ -472,7 +473,10 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.1]
// Variables appearing in threadprivate directives are threadprivate.
- if (D->getTLSKind() != VarDecl::TLS_None ||
+ if ((D->getTLSKind() != VarDecl::TLS_None &&
+ !(D->hasAttr<OMPThreadPrivateDeclAttr>() &&
+ SemaRef.getLangOpts().OpenMPUseTLS &&
+ SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
(D->getStorageClass() == SC_Register && D->hasAttr<AsmLabelAttr>() &&
!D->isLocalVarDecl())) {
addDSA(D, buildDeclRefExpr(SemaRef, D, D->getType().getNonReferenceType(),
@@ -959,8 +963,12 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
continue;
}
- // Check if this is a TLS variable.
- if (VD->getTLSKind() != VarDecl::TLS_None ||
+ // Check if this is a TLS variable. If TLS is not being supported, produce
+ // the corresponding diagnostic.
+ if ((VD->getTLSKind() != VarDecl::TLS_None &&
+ !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
+ getLangOpts().OpenMPUseTLS &&
+ getASTContext().getTargetInfo().isTLSSupported())) ||
(VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
!VD->isLocalVarDecl())) {
Diag(ILoc, diag::err_omp_var_thread_local)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index a0fdcd7..31f581d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -2152,23 +2152,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
FromObjCPtr->getPointeeType()))
return false;
- // Check for compatible
- // Objective C++: We're able to convert between "id" or "Class" and a
- // pointer to any interface (in both directions).
- if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
- ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
- return true;
- }
- // Conversions with Objective-C's id<...>.
- if ((FromObjCPtr->isObjCQualifiedIdType() ||
- ToObjCPtr->isObjCQualifiedIdType()) &&
- Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType,
- /*compare=*/false)) {
- ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
- return true;
- }
- // Objective C++: We're able to convert from a pointer to an
- // interface to a pointer to a different interface.
+ // Conversion between Objective-C pointers.
if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) {
const ObjCInterfaceType* LHS = ToObjCPtr->getInterfaceType();
const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
index 3e465af..fec9748 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
@@ -689,15 +689,7 @@ ExprResult ObjCPropertyOpBuilder::buildGet() {
if (SyntacticRefExpr)
SyntacticRefExpr->setIsMessagingGetter();
- QualType receiverType;
- if (RefExpr->isClassReceiver()) {
- receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
- } else if (RefExpr->isSuperReceiver()) {
- receiverType = RefExpr->getSuperReceiverType();
- } else {
- assert(InstanceReceiver);
- receiverType = InstanceReceiver->getType();
- }
+ QualType receiverType = RefExpr->getReceiverType(S.Context);
if (!Getter->isImplicit())
S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true);
// Build a message-send.
@@ -730,21 +722,17 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
if (SyntacticRefExpr)
SyntacticRefExpr->setIsMessagingSetter();
- QualType receiverType;
- if (RefExpr->isClassReceiver()) {
- receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
- } else if (RefExpr->isSuperReceiver()) {
- receiverType = RefExpr->getSuperReceiverType();
- } else {
- assert(InstanceReceiver);
- receiverType = InstanceReceiver->getType();
- }
+ QualType receiverType = RefExpr->getReceiverType(S.Context);
// Use assignment constraints when possible; they give us better
// diagnostics. "When possible" basically means anything except a
// C++ class type.
if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
- QualType paramType = (*Setter->param_begin())->getType();
+ QualType paramType = (*Setter->param_begin())->getType()
+ .substObjCMemberType(
+ receiverType,
+ Setter->getDeclContext(),
+ ObjCSubstitutionContext::Parameter);
if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
ExprResult opResult = op;
Sema::AssignConvertType assignResult
@@ -819,7 +807,9 @@ ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
// As a special case, if the method returns 'id', try to get
// a better type from the property.
if (RefExpr->isExplicitProperty() && result.get()->isRValue()) {
- QualType propType = RefExpr->getExplicitProperty()->getType();
+ QualType receiverType = RefExpr->getReceiverType(S.Context);
+ QualType propType = RefExpr->getExplicitProperty()
+ ->getUsageType(receiverType);
if (result.get()->getType()->isObjCIdType()) {
if (const ObjCObjectPointerType *ptr
= propType->getAs<ObjCObjectPointerType>()) {
@@ -1119,9 +1109,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
if (const ObjCObjectPointerType *PTy =
BaseT->getAs<ObjCObjectPointerType>()) {
ResultType = PTy->getPointeeType();
- if (const ObjCObjectType *iQFaceTy =
- ResultType->getAsObjCQualifiedInterfaceType())
- ResultType = iQFaceTy->getBaseType();
}
Sema::ObjCSubscriptKind Res =
S.CheckSubscriptingKind(RefExpr->getKeyExpr());
@@ -1228,9 +1215,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
if (const ObjCObjectPointerType *PTy =
BaseT->getAs<ObjCObjectPointerType>()) {
ResultType = PTy->getPointeeType();
- if (const ObjCObjectType *iQFaceTy =
- ResultType->getAsObjCQualifiedInterfaceType())
- ResultType = iQFaceTy->getBaseType();
}
Sema::ObjCSubscriptKind Res =
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index 6fca974..c4f6fd8 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/StmtObjC.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
@@ -3649,6 +3650,10 @@ StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
else
Diag(TryLoc, diag::err_seh_try_outside_functions);
+ // Reject __try on unsupported targets.
+ if (!Context.getTargetInfo().isSEHTrySupported())
+ Diag(TryLoc, diag::err_seh_try_unsupported);
+
return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
index d19d881..8e3e89f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
@@ -254,17 +254,19 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
<< Info.getConstraintStr()
<< InputExpr->getSourceRange());
} else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
- llvm::APSInt Result;
- if (!InputExpr->EvaluateAsInt(Result, Context))
- return StmtError(
- Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
- << Info.getConstraintStr() << InputExpr->getSourceRange());
- if (Result.slt(Info.getImmConstantMin()) ||
- Result.sgt(Info.getImmConstantMax()))
- return StmtError(Diag(InputExpr->getLocStart(),
- diag::err_invalid_asm_value_for_constraint)
- << Result.toString(10) << Info.getConstraintStr()
- << InputExpr->getSourceRange());
+ if (!InputExpr->isValueDependent()) {
+ llvm::APSInt Result;
+ if (!InputExpr->EvaluateAsInt(Result, Context))
+ return StmtError(
+ Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
+ << Info.getConstraintStr() << InputExpr->getSourceRange());
+ if (Result.slt(Info.getImmConstantMin()) ||
+ Result.sgt(Info.getImmConstantMax()))
+ return StmtError(Diag(InputExpr->getLocStart(),
+ diag::err_invalid_asm_value_for_constraint)
+ << Result.toString(10) << Info.getConstraintStr()
+ << InputExpr->getSourceRange());
+ }
} else {
ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index f4740a5..035c37c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -893,6 +893,16 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
LookupQualifiedName(Previous, SemanticContext);
} else {
SemanticContext = CurContext;
+
+ // C++14 [class.mem]p14:
+ // If T is the name of a class, then each of the following shall have a
+ // name different from T:
+ // -- every member template of class T
+ if (TUK != TUK_Friend &&
+ DiagnoseClassNameShadow(SemanticContext,
+ DeclarationNameInfo(Name, NameLoc)))
+ return true;
+
LookupName(Previous, S);
}
@@ -947,8 +957,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Check that the chosen semantic context doesn't already contain a
// declaration of this name as a non-tag type.
- LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName,
- ForRedeclaration);
+ Previous.clear(LookupOrdinaryName);
DeclContext *LookupContext = SemanticContext;
while (LookupContext->isTransparentContext())
LookupContext = LookupContext->getLookupParent();
@@ -962,9 +971,25 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
}
} else if (PrevDecl &&
- !isDeclInScope(PrevDecl, SemanticContext, S, SS.isValid()))
+ !isDeclInScope(Previous.getRepresentativeDecl(), SemanticContext,
+ S, SS.isValid()))
PrevDecl = PrevClassTemplate = nullptr;
+ if (auto *Shadow = dyn_cast_or_null<UsingShadowDecl>(
+ PrevDecl ? Previous.getRepresentativeDecl() : nullptr)) {
+ if (SS.isEmpty() &&
+ !(PrevClassTemplate &&
+ PrevClassTemplate->getDeclContext()->getRedeclContext()->Equals(
+ SemanticContext->getRedeclContext()))) {
+ Diag(KWLoc, diag::err_using_decl_conflict_reverse);
+ Diag(Shadow->getTargetDecl()->getLocation(),
+ diag::note_using_decl_target);
+ Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ // Recover by ignoring the old declaration.
+ PrevDecl = PrevClassTemplate = nullptr;
+ }
+ }
+
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible. Skip this check
// for a friend in a dependent context: the template parameter list itself
@@ -983,7 +1008,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// template declaration (7.1.5.3).
RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl();
if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind,
- TUK == TUK_Definition, KWLoc, *Name)) {
+ TUK == TUK_Definition, KWLoc, Name)) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< Name
<< FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName());
@@ -2285,7 +2310,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
assert(Id && "templated class must have an identifier");
if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition,
- TagLoc, *Id)) {
+ TagLoc, Id)) {
Diag(TagLoc, diag::err_use_with_wrong_tag)
<< Result
<< FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName());
@@ -6174,7 +6199,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
assert(Kind != TTK_Enum && "Invalid enum tag in class template spec!");
if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
Kind, TUK == TUK_Definition, KWLoc,
- *ClassTemplate->getIdentifier())) {
+ ClassTemplate->getIdentifier())) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< ClassTemplate
<< FixItHint::CreateReplacement(KWLoc,
@@ -7210,7 +7235,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
Kind, /*isDefinition*/false, KWLoc,
- *ClassTemplate->getIdentifier())) {
+ ClassTemplate->getIdentifier())) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< ClassTemplate
<< FixItHint::CreateReplacement(KWLoc,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 7d58017..c1961e5 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -989,7 +989,7 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
if (Id && Keyword != ETK_None && Keyword != ETK_Typename) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, /*isDefinition*/false,
- TagLocation, *Id)) {
+ TagLocation, Id)) {
SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)
<< Id
<< FixItHint::CreateReplacement(SourceRange(TagLocation),
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index 8d76f69..02a31ef 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -643,6 +643,9 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
NULLABILITY_TYPE_ATTRS_CASELIST:
// Nullability specifiers cannot go after the declarator-id.
+
+ // Objective-C __kindof does not get distributed.
+ case AttributeList::AT_ObjCKindOf:
continue;
default:
@@ -738,6 +741,419 @@ 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<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;
+ }
+
+ // The class type must be parameterized.
+ ObjCInterfaceDecl *objcClass = objcObjectType->getInterface();
+ ObjCTypeParamList *typeParams = objcClass->getTypeParamList();
+ if (!typeParams) {
+ S.Diag(loc, diag::err_objc_type_args_non_parameterized_class)
+ << objcClass->getDeclName()
+ << FixItHint::CreateRemoval(typeArgsRange);
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+ }
+
+ // The type must not already be specialized.
+ if (objcObjectType->isSpecialized()) {
+ S.Diag(loc, diag::err_objc_type_args_specialized_class)
+ << type
+ << FixItHint::CreateRemoval(typeArgsRange);
+
+ 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 = typeArgs[i];
+ QualType typeArg = typeArgInfo->getType();
+
+ // Type arguments cannot explicitly specify nullability.
+ if (auto nullability = AttributedType::stripOuterNullability(typeArg)) {
+ SourceLocation nullabilityLoc
+ = typeArgInfo->getTypeLoc().findNullabilityLoc();
+ SourceLocation diagLoc = nullabilityLoc.isValid()? nullabilityLoc
+ : typeArgInfo->getTypeLoc().getLocStart();
+ S.Diag(diagLoc,
+ diag::err_type_arg_explicit_nullability)
+ << typeArg
+ << FixItHint::CreateRemoval(nullabilityLoc);
+ }
+
+ 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.
+ QualType bound = typeParam->getUnderlyingType();
+ const auto *boundObjC = bound->getAs<ObjCObjectPointerType>();
+
+ // Determine whether the type argument is substitutable for the bound.
+ if (typeArgObjC->isObjCIdType()) {
+ // When the type argument is 'id', the only acceptable type
+ // parameter bound is 'id'.
+ if (boundObjC->isObjCIdType())
+ continue;
+ } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) {
+ // Otherwise, we follow the assignability rules.
+ continue;
+ }
+
+ // Diagnose the mismatch.
+ S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
+ diag::err_objc_type_arg_does_not_match_bound)
+ << typeArg << bound << typeParam->getDeclName();
+ 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.
+ QualType bound = typeParam->getUnderlyingType();
+ if (bound->isBlockCompatibleObjCPointerType(S.Context))
+ continue;
+
+ // Diagnose the mismatch.
+ S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
+ diag::err_objc_type_arg_does_not_match_bound)
+ << typeArg << bound << typeParam->getDeclName();
+ S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
+ << typeParam->getDeclName();
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+ }
+
+ // Dependent types will be checked at instantiation time.
+ if (typeArg->isDependentType()) {
+ continue;
+ }
+
+ // Diagnose non-id-compatible type arguments.
+ S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
+ 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;
+ }
+
+ // Success. Form the specialized type.
+ return S.Context.getObjCObjectType(type, finalTypeArgs, { }, false);
+}
+
+/// Apply Objective-C protocol qualifiers to the given type.
+static QualType applyObjCProtocolQualifiers(
+ Sema &S, SourceLocation loc, SourceRange range, QualType type,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ 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
+ // known to conform.
+
+ return ctx.getObjCObjectType(objT->getBaseType(),
+ objT->getTypeArgsAsWritten(),
+ protocols,
+ objT->isKindOfTypeAsWritten());
+ }
+
+ if (type->isObjCObjectType()) {
+ // Silently overwrite any existing protocol qualifiers.
+ // TODO: determine whether that's the right thing to do.
+
+ // FIXME: Check for protocols to which the class type is already
+ // known to conform.
+ return ctx.getObjCObjectType(type, { }, protocols, false);
+ }
+
+ // id<protocol-list>
+ if (type->isObjCIdType()) {
+ const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ type = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, protocols,
+ objPtr->isKindOfType());
+ return ctx.getObjCObjectPointerType(type);
+ }
+
+ // Class<protocol-list>
+ if (type->isObjCClassType()) {
+ const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ type = ctx.getObjCObjectType(ctx.ObjCBuiltinClassTy, { }, protocols,
+ objPtr->isKindOfType());
+ return ctx.getObjCObjectPointerType(type);
+ }
+
+ 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()),
+ false);
+ 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 * const *)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
@@ -801,15 +1217,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,
- (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
@@ -967,37 +1374,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
Result = S.GetTypeFromParser(DS.getRepAsType());
- if (Result.isNull())
+ if (Result.isNull()) {
declarator.setInvalidType(true);
- else if (DeclSpec::ProtocolQualifierListTy PQ
- = DS.getProtocolQualifiers()) {
- if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
- // Silently drop any existing protocol qualifiers.
- // TODO: determine whether that's the right thing to do.
- if (ObjT->getNumProtocols())
- Result = ObjT->getBaseType();
-
- if (DS.getNumProtocolQualifiers())
- Result = Context.getObjCObjectType(Result,
- (ObjCProtocolDecl*const*) PQ,
- DS.getNumProtocolQualifiers());
- } else if (Result->isObjCIdType()) {
- // id<protocol-list>
- Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
- (ObjCProtocolDecl*const*) PQ,
- DS.getNumProtocolQualifiers());
- Result = Context.getObjCObjectPointerType(Result);
- } else if (Result->isObjCClassType()) {
- // Class<protocol-list>
- Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy,
- (ObjCProtocolDecl*const*) PQ,
- DS.getNumProtocolQualifiers());
- Result = Context.getObjCObjectPointerType(Result);
- } else {
- S.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
- << DS.getSourceRange();
- declarator.setInvalidType(true);
- }
} else if (S.getLangOpts().OpenCL) {
if (const AtomicType *AT = Result->getAs<AtomicType>()) {
const BuiltinType *BT = AT->getValueType()->getAs<BuiltinType>();
@@ -3097,6 +3475,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
spliceAttrIntoList(*nullabilityAttr, attrs);
+ if (inferNullabilityCS) {
+ state.getDeclarator().getMutableDeclSpec().getObjCQualifiers()
+ ->setObjCDeclQualifier(ObjCDeclSpec::DQ_CSNullability);
+ }
+
if (inferNullabilityInnerOnly)
inferNullabilityInnerOnlyComplete = true;
return nullabilityAttr;
@@ -3116,7 +3499,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case CAMN_Yes:
checkNullabilityConsistency(state, pointerKind, pointerLoc);
}
-
return nullptr;
};
@@ -4058,6 +4440,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
return AttributeList::AT_TypeNullable;
case AttributedType::attr_null_unspecified:
return AttributeList::AT_TypeNullUnspecified;
+ case AttributedType::attr_objc_kindof:
+ return AttributeList::AT_ObjCKindOf;
}
llvm_unreachable("unexpected attribute kind!");
}
@@ -4129,32 +4513,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());
- }
-
- // Protocol qualifiers.
- if (DS.getProtocolQualifiers()) {
- assert(TL.getNumProtocols() > 0);
- assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
- TL.setLAngleLoc(DS.getProtocolLAngleLoc());
- TL.setRAngleLoc(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.setLAngleLoc(SourceLocation());
- TL.setRAngleLoc(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;
@@ -5160,6 +5526,44 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
return false;
}
+bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
+ // Find out if it's an Objective-C object or object pointer type;
+ const ObjCObjectPointerType *ptrType = type->getAs<ObjCObjectPointerType>();
+ const ObjCObjectType *objType = ptrType ? ptrType->getObjectType()
+ : type->getAs<ObjCObjectType>();
+
+ // If not, we can't apply __kindof.
+ if (!objType) {
+ // FIXME: Handle dependent types that aren't yet object types.
+ Diag(loc, diag::err_objc_kindof_nonobject)
+ << type;
+ return true;
+ }
+
+ // Rebuild the "equivalent" type, which pushes __kindof down into
+ // the object type.
+ QualType equivType = Context.getObjCObjectType(objType->getBaseType(),
+ objType->getTypeArgsAsWritten(),
+ objType->getProtocols(),
+ /*isKindOf=*/true);
+
+ // If we started with an object pointer type, rebuild it.
+ if (ptrType) {
+ equivType = Context.getObjCObjectPointerType(equivType);
+ if (auto nullability = type->getNullability(Context)) {
+ auto attrKind = AttributedType::getNullabilityAttrKind(*nullability);
+ equivType = Context.getAttributedType(attrKind, equivType, equivType);
+ }
+ }
+
+ // Build the attributed type to record where __kindof occurred.
+ type = Context.getAttributedType(AttributedType::attr_objc_kindof,
+ type,
+ equivType);
+
+ return false;
+}
+
/// Map a nullability attribute kind to a nullability kind.
static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) {
switch (kind) {
@@ -5770,6 +6174,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
attr.setUsedAsTypeAttr();
break;
+
NULLABILITY_TYPE_ATTRS_CASELIST:
// Either add nullability here or try to distribute it. We
// don't want to distribute the nullability specifier past any
@@ -5788,6 +6193,28 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
}
break;
+ case AttributeList::AT_ObjCKindOf:
+ // '__kindof' must be part of the decl-specifiers.
+ switch (TAL) {
+ case TAL_DeclSpec:
+ break;
+
+ case TAL_DeclChunk:
+ case TAL_DeclName:
+ state.getSema().Diag(attr.getLoc(),
+ diag::err_objc_kindof_wrong_position)
+ << FixItHint::CreateRemoval(attr.getLoc())
+ << FixItHint::CreateInsertion(
+ state.getDeclarator().getDeclSpec().getLocStart(), "__kindof ");
+ break;
+ }
+
+ // Apply it regardless.
+ if (state.getSema().checkObjCKindOfType(type, attr.getLoc()))
+ attr.setInvalid();
+ attr.setUsedAsTypeAttr();
+ break;
+
case AttributeList::AT_NSReturnsRetained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
break;
@@ -5942,7 +6369,12 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
/// \param D The definition of the entity.
/// \param Suggested Filled in with the declaration that should be made visible
/// in order to provide a definition of this entity.
-bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested) {
+/// \param OnlyNeedComplete If \c true, we only need the type to be complete,
+/// not defined. This only matters for enums with a fixed underlying
+/// type, since in all other cases, a type is complete if and only if it
+/// is defined.
+bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
+ bool OnlyNeedComplete) {
// Easy case: if we don't have modules, all declarations are visible.
if (!getLangOpts().Modules && !getLangOpts().ModulesLocalVisibility)
return true;
@@ -5960,11 +6392,13 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested) {
} else if (auto *ED = dyn_cast<EnumDecl>(D)) {
while (auto *NewED = ED->getInstantiatedFromMemberEnum())
ED = NewED;
- if (ED->isFixed()) {
- // If the enum has a fixed underlying type, any declaration of it will do.
+ if (OnlyNeedComplete && ED->isFixed()) {
+ // If the enum has a fixed underlying type, and we're only looking for a
+ // complete type (not a definition), any visible declaration of it will
+ // do.
*Suggested = nullptr;
for (auto *Redecl : ED->redecls()) {
- if (LookupResult::isVisible(*this, Redecl))
+ if (isVisible(Redecl))
return true;
if (Redecl->isThisDeclarationADefinition() ||
(Redecl->isCanonicalDecl() && !*Suggested))
@@ -5977,14 +6411,14 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested) {
assert(D && "missing definition for pattern of instantiated definition");
*Suggested = D;
- if (LookupResult::isVisible(*this, D))
+ if (isVisible(D))
return true;
// The external source may have additional definitions of this type that are
// visible, so complete the redeclaration chain now and ask again.
if (auto *Source = Context.getExternalSource()) {
Source->CompleteRedeclChain(D);
- return LookupResult::isVisible(*this, D);
+ return isVisible(D);
}
return false;
@@ -6038,7 +6472,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// If we know about the definition but it is not visible, complain.
NamedDecl *SuggestedDef = nullptr;
if (!Diagnoser.Suppressed && Def &&
- !hasVisibleDefinition(Def, &SuggestedDef))
+ !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true))
diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true);
// We lock in the inheritance model once somebody has asked us to ensure
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index 80896be..6e193a3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/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.
@@ -989,7 +1010,7 @@ public:
}
if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, /*isDefinition*/false,
- IdLoc, *Id)) {
+ IdLoc, Id)) {
SemaRef.Diag(KeywordLoc, diag::err_use_with_wrong_tag) << Id;
SemaRef.Diag(Tag->getLocation(), diag::note_previous_use);
return QualType();
@@ -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