summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp226
1 files changed, 153 insertions, 73 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index 9ad5aa5..2ad595f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -1031,6 +1031,11 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc);
}
+ // C++14 [expr.type.conv]p2: The expression T(), where T is a
+ // simple-type-specifier or typename-specifier for a non-array complete
+ // object type or the (possibly cv-qualified) void type, creates a prvalue
+ // of the specified type, whose value is that produced by value-initializing
+ // an object of type T.
QualType ElemTy = Ty;
if (Ty->isArrayType()) {
if (!ListInitialization)
@@ -1039,6 +1044,10 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
ElemTy = Context.getBaseElementType(Ty);
}
+ if (!ListInitialization && Ty->isFunctionType())
+ return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_function_type)
+ << FullRange);
+
if (!Ty->isVoidType() &&
RequireCompleteType(TyBeginLoc, ElemTy,
diag::err_invalid_incomplete_type_use, FullRange))
@@ -2256,6 +2265,9 @@ FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc,
"found an unexpected usual deallocation function");
}
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads)
+ EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches);
+
assert(Matches.size() == 1 &&
"unexpectedly have multiple usual deallocation functions");
return Matches.front();
@@ -2287,6 +2299,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
Matches.push_back(F.getPair());
}
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads)
+ EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches);
+
// There's exactly one suitable operator; pick it.
if (Matches.size() == 1) {
Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl());
@@ -2702,6 +2717,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return ExprError(Diag(StartLoc, diag::err_delete_operand)
<< Type << Ex.get()->getSourceRange());
} else if (!Pointee->isDependentType()) {
+ // FIXME: This can result in errors if the definition was imported from a
+ // module but is hidden.
if (!RequireCompleteType(StartLoc, Pointee,
diag::warn_delete_incomplete, Ex.get())) {
if (const RecordType *RT = PointeeElem->getAs<RecordType>())
@@ -2712,7 +2729,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (Pointee->isArrayType() && !ArrayForm) {
Diag(StartLoc, diag::warn_delete_array_type)
<< Type << Ex.get()->getSourceRange()
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]");
+ << FixItHint::CreateInsertion(getLocForEndOfToken(StartLoc), "[]");
ArrayForm = true;
}
@@ -2777,7 +2794,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (!OperatorDelete)
// Look for a global declaration.
OperatorDelete = FindUsualDeallocationFunction(
- StartLoc, !RequireCompleteType(StartLoc, Pointee, 0) &&
+ StartLoc, isCompleteType(StartLoc, Pointee) &&
(!ArrayForm || UsualArrayDeleteWantsSize ||
Pointee.isDestructedType()),
DeleteName);
@@ -3103,6 +3120,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
ToType = ToAtomic->getValueType();
}
+ QualType InitialFromType = FromType;
// Perform the first implicit conversion.
switch (SCS.First) {
case ICK_Identity:
@@ -3293,8 +3311,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// We may not have been able to figure out what this member pointer resolved
// to up until this exact point. Attempt to lock-in it's inheritance model.
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- RequireCompleteType(From->getExprLoc(), From->getType(), 0);
- RequireCompleteType(From->getExprLoc(), ToType, 0);
+ (void)isCompleteType(From->getExprLoc(), From->getType());
+ (void)isCompleteType(From->getExprLoc(), ToType);
}
From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
@@ -3432,6 +3450,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_Function_To_Pointer:
case ICK_Qualification:
case ICK_Num_Conversion_Kinds:
+ case ICK_C_Only_Conversion:
llvm_unreachable("Improper second standard conversion");
}
@@ -3472,6 +3491,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
VK_RValue, nullptr, CCK).get();
}
+ // If this conversion sequence succeeded and involved implicitly converting a
+ // _Nullable type to a _Nonnull one, complain.
+ if (CCK == CCK_ImplicitConversion)
+ diagnoseNullableToNonnullConversion(ToType, InitialFromType,
+ From->getLocStart());
+
return From;
}
@@ -3534,27 +3559,43 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsVolatile:
case UTT_IsSigned:
case UTT_IsUnsigned:
+
+ // This type trait always returns false, checking the type is moot.
+ case UTT_IsInterfaceClass:
+ return true;
+
+ // C++14 [meta.unary.prop]:
+ // If T is a non-union class type, T shall be a complete type.
+ case UTT_IsEmpty:
+ case UTT_IsPolymorphic:
+ case UTT_IsAbstract:
+ if (const auto *RD = ArgTy->getAsCXXRecordDecl())
+ if (!RD->isUnion())
+ return !S.RequireCompleteType(
+ Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
+ return true;
+
+ // C++14 [meta.unary.prop]:
+ // If T is a class type, T shall be a complete type.
+ case UTT_IsFinal:
+ case UTT_IsSealed:
+ if (ArgTy->getAsCXXRecordDecl())
+ return !S.RequireCompleteType(
+ Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
return true;
- // C++0x [meta.unary.prop] Table 49 requires the following traits to be
- // applied to a complete type.
+ // C++0x [meta.unary.prop] Table 49 requires the following traits to be
+ // applied to a complete type.
case UTT_IsTrivial:
case UTT_IsTriviallyCopyable:
case UTT_IsStandardLayout:
case UTT_IsPOD:
case UTT_IsLiteral:
- case UTT_IsEmpty:
- case UTT_IsPolymorphic:
- case UTT_IsAbstract:
- case UTT_IsInterfaceClass:
+
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
// Fall-through
- // These traits require a complete type.
- case UTT_IsFinal:
- case UTT_IsSealed:
-
// These trait expressions are designed to help implement predicates in
// [meta.unary.prop] despite not being named the same. They are specified
// by both GCC and the Embarcadero C++ compiler, and require the complete
@@ -3698,39 +3739,36 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
case UTT_IsVolatile:
return T.isVolatileQualified();
case UTT_IsTrivial:
- return T.isTrivialType(Self.Context);
+ return T.isTrivialType(C);
case UTT_IsTriviallyCopyable:
- return T.isTriviallyCopyableType(Self.Context);
+ return T.isTriviallyCopyableType(C);
case UTT_IsStandardLayout:
return T->isStandardLayoutType();
case UTT_IsPOD:
- return T.isPODType(Self.Context);
+ return T.isPODType(C);
case UTT_IsLiteral:
- return T->isLiteralType(Self.Context);
+ return T->isLiteralType(C);
case UTT_IsEmpty:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return !RD->isUnion() && RD->isEmpty();
return false;
case UTT_IsPolymorphic:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->isPolymorphic();
+ return !RD->isUnion() && RD->isPolymorphic();
return false;
case UTT_IsAbstract:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->isAbstract();
+ return !RD->isUnion() && RD->isAbstract();
return false;
+ // __is_interface_class only returns true when CL is invoked in /CLR mode and
+ // even then only when it is used with the 'interface struct ...' syntax
+ // Clang doesn't support /CLR which makes this type trait moot.
case UTT_IsInterfaceClass:
- if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->isInterface();
return false;
case UTT_IsFinal:
- if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->hasAttr<FinalAttr>();
- return false;
case UTT_IsSealed:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- if (FinalAttr *FA = RD->getAttr<FinalAttr>())
- return FA->isSpelledAsSealed();
+ return RD->hasAttr<FinalAttr>();
return false;
case UTT_IsSigned:
return T->isSignedIntegerType();
@@ -3757,7 +3795,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// If __is_pod (type) is true then the trait is true, else if type is
// a cv class or union type (or array thereof) with a trivial default
// constructor ([class.ctor]) then the trait is true, else it is false.
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialDefaultConstructor() &&
@@ -3767,7 +3805,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically this is used as the logic
// behind std::is_trivially_move_constructible (20.9.4.3).
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor();
@@ -3778,7 +3816,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// the trait is true, else if type is a cv class or union type
// with a trivial copy constructor ([class.copy]) then the trait
// is true, else it is false.
- if (T.isPODType(Self.Context) || T->isReferenceType())
+ if (T.isPODType(C) || T->isReferenceType())
return true;
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return RD->hasTrivialCopyConstructor() &&
@@ -3788,7 +3826,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically it is used as the logic
// behind std::is_trivially_move_assignable (20.9.4.3)
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment();
@@ -3808,7 +3846,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
if (T.isConstQualified())
return false;
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return RD->hasTrivialCopyAssignment() &&
@@ -3816,8 +3854,47 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
- // FIXME: Implement UTT_IsDestructible and UTT_IsNothrowDestructible.
- // For now, let's fall through.
+ // C++14 [meta.unary.prop]:
+ // For reference types, is_destructible<T>::value is true.
+ if (T->isReferenceType())
+ return true;
+
+ // Objective-C++ ARC: autorelease types don't require destruction.
+ if (T->isObjCLifetimeType() &&
+ T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing)
+ return true;
+
+ // C++14 [meta.unary.prop]:
+ // For incomplete types and function types, is_destructible<T>::value is
+ // false.
+ if (T->isIncompleteType() || T->isFunctionType())
+ return false;
+
+ // C++14 [meta.unary.prop]:
+ // For object types and given U equal to remove_all_extents_t<T>, if the
+ // expression std::declval<U&>().~U() is well-formed when treated as an
+ // unevaluated operand (Clause 5), then is_destructible<T>::value is true
+ if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) {
+ CXXDestructorDecl *Destructor = Self.LookupDestructor(RD);
+ if (!Destructor)
+ return false;
+ // C++14 [dcl.fct.def.delete]p2:
+ // A program that refers to a deleted function implicitly or
+ // explicitly, other than to declare it, is ill-formed.
+ if (Destructor->isDeleted())
+ return false;
+ if (C.getLangOpts().AccessControl && Destructor->getAccess() != AS_public)
+ return false;
+ if (UTT == UTT_IsNothrowDestructible) {
+ const FunctionProtoType *CPT =
+ Destructor->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT || !CPT->isNothrow(C))
+ return false;
+ }
+ }
+ return true;
+
case UTT_HasTrivialDestructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// If __is_pod (type) is true or type is a reference type
@@ -3825,7 +3902,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// type (or array thereof) with a trivial destructor
// ([class.dtor]) then the trait is true, else it is
// false.
- if (T.isPODType(Self.Context) || T->isReferenceType())
+ if (T.isPODType(C) || T->isReferenceType())
return true;
// Objective-C++ ARC: autorelease types don't require destruction.
@@ -3849,7 +3926,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
if (T->isReferenceType())
return false;
- if (T.isPODType(Self.Context) || T->isObjCLifetimeType())
+ if (T.isPODType(C) || T->isObjCLifetimeType())
return true;
if (const RecordType *RT = T->getAs<RecordType>())
@@ -3862,7 +3939,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically this is used as the logic
// behind std::is_nothrow_move_assignable (20.9.4.3).
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>())
@@ -3886,15 +3963,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
bool FoundConstructor = false;
unsigned FoundTQs;
- DeclContext::lookup_result R = Self.LookupConstructors(RD);
- for (DeclContext::lookup_iterator Con = R.begin(),
- ConEnd = R.end(); Con != ConEnd; ++Con) {
+ for (const auto *ND : Self.LookupConstructors(RD)) {
// A template constructor is never a copy constructor.
// FIXME: However, it may actually be selected at the actual overload
// resolution point.
- if (isa<FunctionTemplateDecl>(*Con))
+ if (isa<FunctionTemplateDecl>(ND))
continue;
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND);
if (Constructor->isCopyConstructor(FoundTQs)) {
FoundConstructor = true;
const FunctionProtoType *CPT
@@ -3904,7 +3979,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 1)
+ if (!CPT->isNothrow(C) || CPT->getNumParams() > 1)
return false;
}
}
@@ -3926,13 +4001,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return true;
bool FoundConstructor = false;
- DeclContext::lookup_result R = Self.LookupConstructors(RD);
- for (DeclContext::lookup_iterator Con = R.begin(),
- ConEnd = R.end(); Con != ConEnd; ++Con) {
+ for (const auto *ND : Self.LookupConstructors(RD)) {
// FIXME: In C++0x, a constructor template can be a default constructor.
- if (isa<FunctionTemplateDecl>(*Con))
+ if (isa<FunctionTemplateDecl>(ND))
continue;
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND);
if (Constructor->isDefaultConstructor()) {
FoundConstructor = true;
const FunctionProtoType *CPT
@@ -3942,7 +4015,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// FIXME: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 0)
+ if (!CPT->isNothrow(C) || CPT->getNumParams() > 0)
return false;
}
}
@@ -4023,8 +4096,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
// Precondition: T and all types in the parameter pack Args shall be
// complete types, (possibly cv-qualified) void, or arrays of
// unknown bound.
- for (unsigned I = 0, N = Args.size(); I != N; ++I) {
- QualType ArgTy = Args[I]->getType();
+ for (const auto *TSI : Args) {
+ QualType ArgTy = TSI->getType();
if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType())
continue;
@@ -4033,12 +4106,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
return false;
}
- // Make sure the first argument is a complete type.
- if (Args[0]->getType()->isIncompleteType())
+ // Make sure the first argument is not incomplete nor a function type.
+ QualType T = Args[0]->getType();
+ if (T->isIncompleteType() || T->isFunctionType())
return false;
// Make sure the first argument is not an abstract type.
- CXXRecordDecl *RD = Args[0]->getType()->getAsCXXRecordDecl();
+ CXXRecordDecl *RD = T->getAsCXXRecordDecl();
if (RD && RD->isAbstract())
return false;
@@ -4046,13 +4120,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
SmallVector<Expr *, 2> ArgExprs;
ArgExprs.reserve(Args.size() - 1);
for (unsigned I = 1, N = Args.size(); I != N; ++I) {
- QualType T = Args[I]->getType();
- if (T->isObjectType() || T->isFunctionType())
- T = S.Context.getRValueReferenceType(T);
+ QualType ArgTy = Args[I]->getType();
+ if (ArgTy->isObjectType() || ArgTy->isFunctionType())
+ ArgTy = S.Context.getRValueReferenceType(ArgTy);
OpaqueArgExprs.push_back(
- OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(),
- T.getNonLValueExprType(S.Context),
- Expr::getValueKindForType(T)));
+ OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(),
+ ArgTy.getNonLValueExprType(S.Context),
+ Expr::getValueKindForType(ArgTy)));
}
for (Expr &E : OpaqueArgExprs)
ArgExprs.push_back(&E);
@@ -4083,7 +4157,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
// Under Objective-C ARC, if the destination has non-trivial Objective-C
// lifetime, this is a non-trivial construction.
if (S.getLangOpts().ObjCAutoRefCount &&
- hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType()))
+ hasNontrivialObjCLifetime(T.getNonReferenceType()))
return false;
// The initialization succeeded; now make sure there are no non-trivial
@@ -4219,8 +4293,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
return LhsT->isVoidType();
// A function definition requires a complete, non-abstract return type.
- if (Self.RequireCompleteType(KeyLoc, RhsT, 0) ||
- Self.RequireNonAbstractType(KeyLoc, RhsT, 0))
+ if (!Self.isCompleteType(KeyLoc, RhsT) || Self.isAbstractType(KeyLoc, RhsT))
return false;
// Compute the result of add_rvalue_reference.
@@ -4506,7 +4579,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
return QualType();
}
- if (!IsDerivedFrom(LHSType, Class)) {
+ if (!IsDerivedFrom(Loc, LHSType, Class)) {
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
<< (int)isIndirect << LHS.get()->getType();
return QualType();
@@ -4634,9 +4707,9 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
const RecordType *FRec = FTy->getAs<RecordType>();
const RecordType *TRec = TTy->getAs<RecordType>();
bool FDerivedFromT = FRec && TRec && FRec != TRec &&
- Self.IsDerivedFrom(FTy, TTy);
- if (FRec && TRec &&
- (FRec == TRec || FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) {
+ Self.IsDerivedFrom(QuestionLoc, FTy, TTy);
+ if (FRec && TRec && (FRec == TRec || FDerivedFromT ||
+ Self.IsDerivedFrom(QuestionLoc, TTy, FTy))) {
// E1 can be converted to match E2 if the class of T2 is the
// same type as, or a base class of, the class of T1, and
// [cv2 > cv1].
@@ -5671,9 +5744,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
//
// This also indicates that we could be parsing a pseudo-destructor-name.
// Note that Objective-C class and object types can be pseudo-destructor
- // expressions or normal member (ivar or property) access expressions.
+ // expressions or normal member (ivar or property) access expressions, and
+ // it's legal for the type to be incomplete if this is a pseudo-destructor
+ // call. We'll do more incomplete-type checks later in the lookup process,
+ // so just skip this check for ObjC types.
if (BaseType->isObjCObjectOrInterfaceType()) {
+ ObjectType = ParsedType::make(BaseType);
MayBePseudoDestructor = true;
+ return Base;
} else if (!BaseType->isRecordType()) {
ObjectType = ParsedType();
MayBePseudoDestructor = true;
@@ -6331,7 +6409,7 @@ static ExprResult attemptRecovery(Sema &SemaRef,
else if (SS && !TC.WillReplaceSpecifier())
NewSS = *SS;
- if (auto *ND = TC.getCorrectionDecl()) {
+ if (auto *ND = TC.getFoundDecl()) {
R.setLookupName(ND->getDeclName());
R.addDecl(ND);
if (ND->isCXXClassMember()) {
@@ -6364,7 +6442,7 @@ static ExprResult attemptRecovery(Sema &SemaRef,
if (MightBeImplicitMember)
return SemaRef.BuildPossibleImplicitMemberExpr(
NewSS, /*TemplateKWLoc*/ SourceLocation(), R,
- /*TemplateArgs*/ nullptr);
+ /*TemplateArgs*/ nullptr, /*S*/ nullptr);
} else if (auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
return SemaRef.LookupInObjCMethod(R, Consumer.getScope(),
Ivar->getIdentifier());
@@ -6452,9 +6530,9 @@ class TransformTypos : public TreeTransform<TransformTypos> {
if (!E)
return nullptr;
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
- return DRE->getDecl();
+ return DRE->getFoundDecl();
if (auto *ME = dyn_cast<MemberExpr>(E))
- return ME->getMemberDecl();
+ return ME->getFoundDecl();
// FIXME: Add any other expr types that could be be seen by the delayed typo
// correction TreeTransform for which the corresponding TypoCorrection could
// contain multiple decls.
@@ -6494,6 +6572,8 @@ public:
ExprResult TransformLambdaExpr(LambdaExpr *E) { return Owned(E); }
+ ExprResult TransformBlockExpr(BlockExpr *E) { return Owned(E); }
+
ExprResult Transform(Expr *E) {
ExprResult Res;
while (true) {
@@ -6557,7 +6637,7 @@ public:
// For the first TypoExpr and an uncached TypoExpr, find the next likely
// typo correction and return it.
while (TypoCorrection TC = State.Consumer->getNextCorrection()) {
- if (InitDecl && TC.getCorrectionDecl() == InitDecl)
+ if (InitDecl && TC.getFoundDecl() == InitDecl)
continue;
ExprResult NE = State.RecoveryHandler ?
State.RecoveryHandler(SemaRef, E, TC) :
OpenPOWER on IntegriCloud