diff options
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 542 |
1 files changed, 418 insertions, 124 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 38fbea18d790..2cd00f8218a6 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -113,7 +113,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, bool LookInScope = false; if (SS.isInvalid()) - return ParsedType(); + return nullptr; // If we have an object type, it's because we are in a // pseudo-destructor-expression or a member access expression, and @@ -198,7 +198,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, // FIXME: Should we be suppressing ambiguities here? if (Found.isAmbiguous()) - return ParsedType(); + return nullptr; if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) { QualType T = Context.getTypeDeclType(Type); @@ -320,12 +320,12 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, } } - return ParsedType(); + return nullptr; } ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) { if (DS.getTypeSpecType() == DeclSpec::TST_error || !ObjectType) - return ParsedType(); + return nullptr; assert(DS.getTypeSpecType() == DeclSpec::TST_decltype && "only get destructor types from declspecs"); QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); @@ -336,7 +336,7 @@ ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) { Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_expr_type_mismatch) << T << SearchType; - return ParsedType(); + return nullptr; } bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, @@ -508,23 +508,60 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); } +/// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to +/// a single GUID. +static void +getUuidAttrOfType(Sema &SemaRef, QualType QT, + llvm::SmallSetVector<const UuidAttr *, 1> &UuidAttrs) { + // Optionally remove one level of pointer, reference or array indirection. + const Type *Ty = QT.getTypePtr(); + if (QT->isPointerType() || QT->isReferenceType()) + Ty = QT->getPointeeType().getTypePtr(); + else if (QT->isArrayType()) + Ty = Ty->getBaseElementTypeUnsafe(); + + const auto *RD = Ty->getAsCXXRecordDecl(); + if (!RD) + return; + + if (const auto *Uuid = RD->getMostRecentDecl()->getAttr<UuidAttr>()) { + UuidAttrs.insert(Uuid); + return; + } + + // __uuidof can grab UUIDs from template arguments. + if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { + const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); + for (const TemplateArgument &TA : TAL.asArray()) { + const UuidAttr *UuidForTA = nullptr; + if (TA.getKind() == TemplateArgument::Type) + getUuidAttrOfType(SemaRef, TA.getAsType(), UuidAttrs); + else if (TA.getKind() == TemplateArgument::Declaration) + getUuidAttrOfType(SemaRef, TA.getAsDecl()->getType(), UuidAttrs); + + if (UuidForTA) + UuidAttrs.insert(UuidForTA); + } + } +} + /// \brief Build a Microsoft __uuidof expression with a type operand. ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, SourceLocation RParenLoc) { + StringRef UuidStr; if (!Operand->getType()->isDependentType()) { - bool HasMultipleGUIDs = false; - if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType(), - &HasMultipleGUIDs)) { - if (HasMultipleGUIDs) - return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); - else - return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); - } + llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs; + getUuidAttrOfType(*this, Operand->getType(), UuidAttrs); + if (UuidAttrs.empty()) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + if (UuidAttrs.size() > 1) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); + UuidStr = UuidAttrs.back()->getGuid(); } - return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, + return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UuidStr, SourceRange(TypeidLoc, RParenLoc)); } @@ -533,18 +570,22 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *E, SourceLocation RParenLoc) { + StringRef UuidStr; if (!E->getType()->isDependentType()) { - bool HasMultipleGUIDs = false; - if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType(), &HasMultipleGUIDs) && - !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - if (HasMultipleGUIDs) - return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); - else + if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + UuidStr = "00000000-0000-0000-0000-000000000000"; + } else { + llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs; + getUuidAttrOfType(*this, E->getType(), UuidAttrs); + if (UuidAttrs.empty()) return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + if (UuidAttrs.size() > 1) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); + UuidStr = UuidAttrs.back()->getGuid(); } } - return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E, + return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E, UuidStr, SourceRange(TypeidLoc, RParenLoc)); } @@ -831,6 +872,92 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, return false; } +static QualType adjustCVQualifiersForCXXThisWithinLambda( + ArrayRef<FunctionScopeInfo *> FunctionScopes, QualType ThisTy, + DeclContext *CurSemaContext, ASTContext &ASTCtx) { + + QualType ClassType = ThisTy->getPointeeType(); + LambdaScopeInfo *CurLSI = nullptr; + DeclContext *CurDC = CurSemaContext; + + // Iterate through the stack of lambdas starting from the innermost lambda to + // the outermost lambda, checking if '*this' is ever captured by copy - since + // that could change the cv-qualifiers of the '*this' object. + // The object referred to by '*this' starts out with the cv-qualifiers of its + // member function. We then start with the innermost lambda and iterate + // outward checking to see if any lambda performs a by-copy capture of '*this' + // - and if so, any nested lambda must respect the 'constness' of that + // capturing lamdbda's call operator. + // + + // The issue is that we cannot rely entirely on the FunctionScopeInfo stack + // since ScopeInfos are pushed on during parsing and treetransforming. But + // since a generic lambda's call operator can be instantiated anywhere (even + // end of the TU) we need to be able to examine its enclosing lambdas and so + // we use the DeclContext to get a hold of the closure-class and query it for + // capture information. The reason we don't just resort to always using the + // DeclContext chain is that it is only mature for lambda expressions + // enclosing generic lambda's call operators that are being instantiated. + + for (int I = FunctionScopes.size(); + I-- && isa<LambdaScopeInfo>(FunctionScopes[I]); + CurDC = getLambdaAwareParentOfDeclContext(CurDC)) { + CurLSI = cast<LambdaScopeInfo>(FunctionScopes[I]); + + if (!CurLSI->isCXXThisCaptured()) + continue; + + auto C = CurLSI->getCXXThisCapture(); + + if (C.isCopyCapture()) { + ClassType.removeLocalCVRQualifiers(Qualifiers::CVRMask); + if (CurLSI->CallOperator->isConst()) + ClassType.addConst(); + return ASTCtx.getPointerType(ClassType); + } + } + // We've run out of ScopeInfos but check if CurDC is a lambda (which can + // happen during instantiation of generic lambdas) + if (isLambdaCallOperator(CurDC)) { + assert(CurLSI); + assert(isGenericLambdaCallOperatorSpecialization(CurLSI->CallOperator)); + assert(CurDC == getLambdaAwareParentOfDeclContext(CurLSI->CallOperator)); + + auto IsThisCaptured = + [](CXXRecordDecl *Closure, bool &IsByCopy, bool &IsConst) { + IsConst = false; + IsByCopy = false; + for (auto &&C : Closure->captures()) { + if (C.capturesThis()) { + if (C.getCaptureKind() == LCK_StarThis) + IsByCopy = true; + if (Closure->getLambdaCallOperator()->isConst()) + IsConst = true; + return true; + } + } + return false; + }; + + bool IsByCopyCapture = false; + bool IsConstCapture = false; + CXXRecordDecl *Closure = cast<CXXRecordDecl>(CurDC->getParent()); + while (Closure && + IsThisCaptured(Closure, IsByCopyCapture, IsConstCapture)) { + if (IsByCopyCapture) { + ClassType.removeLocalCVRQualifiers(Qualifiers::CVRMask); + if (IsConstCapture) + ClassType.addConst(); + return ASTCtx.getPointerType(ClassType); + } + Closure = isLambdaCallOperator(Closure->getParent()) + ? cast<CXXRecordDecl>(Closure->getParent()->getParent()) + : nullptr; + } + } + return ASTCtx.getPointerType(ClassType); +} + QualType Sema::getCurrentThisType() { DeclContext *DC = getFunctionLevelDeclContext(); QualType ThisTy = CXXThisTypeOverride; @@ -845,13 +972,29 @@ QualType Sema::getCurrentThisType() { // within a default initializer - so use the enclosing class as 'this'. // There is no enclosing member function to retrieve the 'this' pointer // from. + + // FIXME: This looks wrong. If we're in a lambda within a lambda within a + // default member initializer, we need to recurse up more parents to find + // the right context. Looks like we should be walking up to the parent of + // the closure type, checking whether that is itself a lambda, and if so, + // recursing, until we reach a class or a function that isn't a lambda + // call operator. And we should accumulate the constness of *this on the + // way. + QualType ClassTy = Context.getTypeDeclType( cast<CXXRecordDecl>(CurContext->getParent()->getParent())); // There are no cv-qualifiers for 'this' within default initializers, // per [expr.prim.general]p4. - return Context.getPointerType(ClassTy); + ThisTy = Context.getPointerType(ClassTy); } } + + // If we are within a lambda's call operator, the cv-qualifiers of 'this' + // might need to be adjusted if the lambda or any of its enclosing lambda's + // captures '*this' by copy. + if (!ThisTy.isNull() && isLambdaCallOperator(CurContext)) + return adjustCVQualifiersForCXXThisWithinLambda(FunctionScopes, ThisTy, + CurContext, Context); return ThisTy; } @@ -870,6 +1013,8 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, else Record = cast<CXXRecordDecl>(ContextDecl); + // We care only for CVR qualifiers here, so cut everything else. + CXXThisTypeQuals &= Qualifiers::FastMask; S.CXXThisTypeOverride = S.Context.getPointerType( S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals)); @@ -884,28 +1029,84 @@ Sema::CXXThisScopeRAII::~CXXThisScopeRAII() { } } -static Expr *captureThis(ASTContext &Context, RecordDecl *RD, - QualType ThisTy, SourceLocation Loc) { - FieldDecl *Field - = FieldDecl::Create(Context, RD, Loc, Loc, nullptr, ThisTy, - Context.getTrivialTypeSourceInfo(ThisTy, Loc), - nullptr, false, ICIS_NoInit); +static Expr *captureThis(Sema &S, ASTContext &Context, RecordDecl *RD, + QualType ThisTy, SourceLocation Loc, + const bool ByCopy) { + + QualType AdjustedThisTy = ThisTy; + // The type of the corresponding data member (not a 'this' pointer if 'by + // copy'). + QualType CaptureThisFieldTy = ThisTy; + if (ByCopy) { + // If we are capturing the object referred to by '*this' by copy, ignore any + // cv qualifiers inherited from the type of the member function for the type + // of the closure-type's corresponding data member and any use of 'this'. + CaptureThisFieldTy = ThisTy->getPointeeType(); + CaptureThisFieldTy.removeLocalCVRQualifiers(Qualifiers::CVRMask); + AdjustedThisTy = Context.getPointerType(CaptureThisFieldTy); + } + + FieldDecl *Field = FieldDecl::Create( + Context, RD, Loc, Loc, nullptr, CaptureThisFieldTy, + Context.getTrivialTypeSourceInfo(CaptureThisFieldTy, Loc), nullptr, false, + ICIS_NoInit); + Field->setImplicit(true); Field->setAccess(AS_private); RD->addDecl(Field); - return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/true); + Expr *This = + new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/ true); + if (ByCopy) { + Expr *StarThis = S.CreateBuiltinUnaryOp(Loc, + UO_Deref, + This).get(); + InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture( + nullptr, CaptureThisFieldTy, Loc); + InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); + InitializationSequence Init(S, Entity, InitKind, StarThis); + ExprResult ER = Init.Perform(S, Entity, InitKind, StarThis); + if (ER.isInvalid()) return nullptr; + return ER.get(); + } + return This; } -bool Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit, - bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt) { +bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, + bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt, + const bool ByCopy) { // We don't need to capture this in an unevaluated context. if (isUnevaluatedContext() && !Explicit) return true; + + assert((!ByCopy || Explicit) && "cannot implicitly capture *this by value"); const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ? - *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1; - // Otherwise, check that we can capture 'this'. - unsigned NumClosures = 0; + *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1; + + // Check that we can capture the *enclosing object* (referred to by '*this') + // by the capturing-entity/closure (lambda/block/etc) at + // MaxFunctionScopesIndex-deep on the FunctionScopes stack. + + // Note: The *enclosing object* can only be captured by-value by a + // closure that is a lambda, using the explicit notation: + // [*this] { ... }. + // Every other capture of the *enclosing object* results in its by-reference + // capture. + + // For a closure 'L' (at MaxFunctionScopesIndex in the FunctionScopes + // stack), we can capture the *enclosing object* only if: + // - 'L' has an explicit byref or byval capture of the *enclosing object* + // - or, 'L' has an implicit capture. + // AND + // -- there is no enclosing closure + // -- or, there is some enclosing closure 'E' that has already captured the + // *enclosing object*, and every intervening closure (if any) between 'E' + // and 'L' can implicitly capture the *enclosing object*. + // -- or, every enclosing closure can implicitly capture the + // *enclosing object* + + + unsigned NumCapturingClosures = 0; for (unsigned idx = MaxFunctionScopesIndex; idx != 0; idx--) { if (CapturingScopeInfo *CSI = dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) { @@ -917,44 +1118,69 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit, if (LSI && isGenericLambdaCallOperatorSpecialization(LSI->CallOperator)) { // This context can't implicitly capture 'this'; fail out. if (BuildAndDiagnose) - Diag(Loc, diag::err_this_capture) << Explicit; + Diag(Loc, diag::err_this_capture) + << (Explicit && idx == MaxFunctionScopesIndex); return true; } if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref || CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval || CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block || CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_CapturedRegion || - Explicit) { + (Explicit && idx == MaxFunctionScopesIndex)) { + // Regarding (Explicit && idx == MaxFunctionScopesIndex): only the first + // iteration through can be an explicit capture, all enclosing closures, + // if any, must perform implicit captures. + // This closure can capture 'this'; continue looking upwards. - NumClosures++; - Explicit = false; + NumCapturingClosures++; continue; } // This context can't implicitly capture 'this'; fail out. if (BuildAndDiagnose) - Diag(Loc, diag::err_this_capture) << Explicit; + Diag(Loc, diag::err_this_capture) + << (Explicit && idx == MaxFunctionScopesIndex); return true; } break; } if (!BuildAndDiagnose) return false; - // Mark that we're implicitly capturing 'this' in all the scopes we skipped. + + // If we got here, then the closure at MaxFunctionScopesIndex on the + // FunctionScopes stack, can capture the *enclosing object*, so capture it + // (including implicit by-reference captures in any enclosing closures). + + // In the loop below, respect the ByCopy flag only for the closure requesting + // the capture (i.e. first iteration through the loop below). Ignore it for + // all enclosing closure's upto NumCapturingClosures (since they must be + // implicitly capturing the *enclosing object* by reference (see loop + // above)). + assert((!ByCopy || + dyn_cast<LambdaScopeInfo>(FunctionScopes[MaxFunctionScopesIndex])) && + "Only a lambda can capture the enclosing object (referred to by " + "*this) by copy"); // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated // contexts. - for (unsigned idx = MaxFunctionScopesIndex; NumClosures; - --idx, --NumClosures) { + QualType ThisTy = getCurrentThisType(); + for (unsigned idx = MaxFunctionScopesIndex; NumCapturingClosures; + --idx, --NumCapturingClosures) { CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]); Expr *ThisExpr = nullptr; - QualType ThisTy = getCurrentThisType(); - if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI)) - // For lambda expressions, build a field and an initializing expression. - ThisExpr = captureThis(Context, LSI->Lambda, ThisTy, Loc); - else if (CapturedRegionScopeInfo *RSI + + if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI)) { + // For lambda expressions, build a field and an initializing expression, + // and capture the *enclosing object* by copy only if this is the first + // iteration. + ThisExpr = captureThis(*this, Context, LSI->Lambda, ThisTy, Loc, + ByCopy && idx == MaxFunctionScopesIndex); + + } else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(FunctionScopes[idx])) - ThisExpr = captureThis(Context, RSI->TheRecordDecl, ThisTy, Loc); + ThisExpr = + captureThis(*this, Context, RSI->TheRecordDecl, ThisTy, Loc, + false/*ByCopy*/); - bool isNested = NumClosures > 1; - CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr); + bool isNested = NumCapturingClosures > 1; + CSI->addThisCapture(isNested, Loc, ThisExpr, ByCopy); } return false; } @@ -996,7 +1222,14 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation()); - return BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); + auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); + // Avoid creating a non-type-dependent expression that contains typos. + // Non-type-dependent expressions are liable to be discarded without + // checking for embedded typos. + if (!Result.isInvalid() && Result.get()->isInstantiationDependent() && + !Result.get()->isTypeDependent()) + Result = CorrectDelayedTyposInExpr(Result.get()); + return Result; } /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. @@ -1551,7 +1784,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // new. if (PlacementArgs.empty() && OperatorNew && (OperatorNew->isImplicit() || - getSourceManager().isInSystemHeader(OperatorNew->getLocStart()))) { + (OperatorNew->getLocStart().isValid() && + getSourceManager().isInSystemHeader(OperatorNew->getLocStart())))) { if (unsigned Align = Context.getPreferredTypeAlign(AllocType.getTypePtr())){ unsigned SuitableAlign = Context.getTargetInfo().getSuitableAlign(); if (Align > SuitableAlign) @@ -2113,14 +2347,13 @@ void Sema::DeclareGlobalNewDelete() { QualType VoidPtr = Context.getPointerType(Context.VoidTy); QualType SizeT = Context.getSizeType(); - bool AssumeSaneOperatorNew = getLangOpts().AssumeSaneOperatorNew; DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_New), - VoidPtr, SizeT, QualType(), AssumeSaneOperatorNew); + VoidPtr, SizeT, QualType()); DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_Array_New), - VoidPtr, SizeT, QualType(), AssumeSaneOperatorNew); + VoidPtr, SizeT, QualType()); DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_Delete), Context.VoidTy, VoidPtr); @@ -2141,8 +2374,7 @@ void Sema::DeclareGlobalNewDelete() { /// allocation function if it doesn't already exist. void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, - QualType Param1, QualType Param2, - bool AddRestrictAttr) { + QualType Param1, QualType Param2) { DeclContext *GlobalCtx = Context.getTranslationUnitDecl(); unsigned NumParams = Param2.isNull() ? 1 : 2; @@ -2165,9 +2397,6 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // FIXME: Do we need to check for default arguments here? if (InitialParam1Type == Param1 && (NumParams == 1 || InitialParam2Type == Param2)) { - if (AddRestrictAttr && !Func->hasAttr<RestrictAttr>()) - Func->addAttr(RestrictAttr::CreateImplicit( - Context, RestrictAttr::GNU_malloc)); // Make the function visible to name lookup, even if we found it in // an unimported module. It either is an implicitly-declared global // allocation function, or is suppressing that function. @@ -2210,10 +2439,6 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Alloc->addAttr(VisibilityAttr::CreateImplicit(Context, VisibilityAttr::Default)); - if (AddRestrictAttr) - Alloc->addAttr( - RestrictAttr::CreateImplicit(Context, RestrictAttr::GNU_malloc)); - ParmVarDecl *ParamDecls[2]; for (unsigned I = 0; I != NumParams; ++I) { ParamDecls[I] = ParmVarDecl::Create(Context, Alloc, SourceLocation(), @@ -2265,7 +2490,7 @@ FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc, "found an unexpected usual deallocation function"); } - if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads) + if (getLangOpts().CUDA) EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches); assert(Matches.size() == 1 && @@ -2299,7 +2524,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, Matches.push_back(F.getPair()); } - if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads) + if (getLangOpts().CUDA) EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches); // There's exactly one suitable operator; pick it. @@ -2765,30 +2990,10 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return ExprError(); } - // C++ [expr.delete]p3: - // In the first alternative (delete object), if the static type of the - // object to be deleted is different from its dynamic type, the static - // type shall be a base class of the dynamic type of the object to be - // deleted and the static type shall have a virtual destructor or the - // behavior is undefined. - // - // Note: a final class cannot be derived from, no issue there - if (PointeeRD->isPolymorphic() && !PointeeRD->hasAttr<FinalAttr>()) { - CXXDestructorDecl *dtor = PointeeRD->getDestructor(); - if (dtor && !dtor->isVirtual()) { - if (PointeeRD->isAbstract()) { - // If the class is abstract, we warn by default, because we're - // sure the code has undefined behavior. - Diag(StartLoc, diag::warn_delete_abstract_non_virtual_dtor) - << PointeeElem; - } else if (!ArrayForm) { - // Otherwise, if this is not an array delete, it's a bit suspect, - // but not necessarily wrong. - Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem; - } - } - } - + CheckVirtualDtorCall(PointeeRD->getDestructor(), StartLoc, + /*IsDelete=*/true, /*CallCanBeVirtual=*/true, + /*WarnOnNonAbstractTypes=*/!ArrayForm, + SourceLocation()); } if (!OperatorDelete) @@ -2817,11 +3022,61 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return Result; } +void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc, + bool IsDelete, bool CallCanBeVirtual, + bool WarnOnNonAbstractTypes, + SourceLocation DtorLoc) { + if (!dtor || dtor->isVirtual() || !CallCanBeVirtual) + return; + + // C++ [expr.delete]p3: + // In the first alternative (delete object), if the static type of the + // object to be deleted is different from its dynamic type, the static + // type shall be a base class of the dynamic type of the object to be + // deleted and the static type shall have a virtual destructor or the + // behavior is undefined. + // + const CXXRecordDecl *PointeeRD = dtor->getParent(); + // Note: a final class cannot be derived from, no issue there + if (!PointeeRD->isPolymorphic() || PointeeRD->hasAttr<FinalAttr>()) + return; + + QualType ClassType = dtor->getThisType(Context)->getPointeeType(); + if (PointeeRD->isAbstract()) { + // If the class is abstract, we warn by default, because we're + // sure the code has undefined behavior. + Diag(Loc, diag::warn_delete_abstract_non_virtual_dtor) << (IsDelete ? 0 : 1) + << ClassType; + } else if (WarnOnNonAbstractTypes) { + // Otherwise, if this is not an array delete, it's a bit suspect, + // but not necessarily wrong. + Diag(Loc, diag::warn_delete_non_virtual_dtor) << (IsDelete ? 0 : 1) + << ClassType; + } + if (!IsDelete) { + std::string TypeStr; + ClassType.getAsStringInternal(TypeStr, getPrintingPolicy()); + Diag(DtorLoc, diag::note_delete_non_virtual) + << FixItHint::CreateInsertion(DtorLoc, TypeStr + "::"); + } +} + +Sema::ConditionResult Sema::ActOnConditionVariable(Decl *ConditionVar, + SourceLocation StmtLoc, + ConditionKind CK) { + ExprResult E = + CheckConditionVariable(cast<VarDecl>(ConditionVar), StmtLoc, CK); + if (E.isInvalid()) + return ConditionError(); + return ConditionResult(*this, ConditionVar, MakeFullExpr(E.get(), StmtLoc), + CK == ConditionKind::ConstexprIf); +} + /// \brief Check the use of the given variable as a C++ condition in an if, /// while, do-while, or switch statement. ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, SourceLocation StmtLoc, - bool ConvertToBoolean) { + ConditionKind CK) { if (ConditionVar->isInvalidDecl()) return ExprError(); @@ -2845,17 +3100,22 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, MarkDeclRefReferenced(cast<DeclRefExpr>(Condition.get())); - if (ConvertToBoolean) { - Condition = CheckBooleanCondition(Condition.get(), StmtLoc); - if (Condition.isInvalid()) - return ExprError(); + switch (CK) { + case ConditionKind::Boolean: + return CheckBooleanCondition(StmtLoc, Condition.get()); + + case ConditionKind::ConstexprIf: + return CheckBooleanCondition(StmtLoc, Condition.get(), true); + + case ConditionKind::Switch: + return CheckSwitchCondition(StmtLoc, Condition.get()); } - return Condition; + llvm_unreachable("unexpected condition kind"); } /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. -ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr) { +ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr) { // C++ 6.4p4: // The value of a condition that is an initialized declaration in a statement // other than a switch statement is the value of the declared variable @@ -2864,7 +3124,12 @@ ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr) { // The value of a condition that is an expression is the value of the // expression, implicitly converted to bool. // - return PerformContextuallyConvertToBool(CondExpr); + // FIXME: Return this value to the caller so they don't need to recompute it. + llvm::APSInt Value(/*BitWidth*/1); + return (IsConstexpr && !CondExpr->isValueDependent()) + ? CheckConvertedConstantExpression(CondExpr, Context.BoolTy, Value, + CCEK_ConstexprIf) + : PerformContextuallyConvertToBool(CondExpr); } /// Helper function to determine whether this is the (deprecated) C++ @@ -2898,7 +3163,8 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { return (ToPointeeType->getKind() == BuiltinType::Char_U || ToPointeeType->getKind() == BuiltinType::Char_S); case StringLiteral::Wide: - return ToPointeeType->isWideCharType(); + return Context.typesAreCompatible(Context.getWideCharType(), + QualType(ToPointeeType, 0)); } } } @@ -2927,14 +3193,13 @@ static ExprResult BuildCXXCastArgument(Sema &S, if (S.CompleteConstructorCall(Constructor, From, CastLoc, ConstructorArgs)) return ExprError(); - S.CheckConstructorAccess(CastLoc, Constructor, - InitializedEntity::InitializeTemporary(Ty), - Constructor->getAccess()); + S.CheckConstructorAccess(CastLoc, Constructor, FoundDecl, + InitializedEntity::InitializeTemporary(Ty)); if (S.DiagnoseUseOfDecl(Method, CastLoc)) return ExprError(); ExprResult Result = S.BuildCXXConstructExpr( - CastLoc, Ty, cast<CXXConstructorDecl>(Method), + CastLoc, Ty, FoundDecl, cast<CXXConstructorDecl>(Method), ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -3085,13 +3350,15 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, ConstructorArgs)) return ExprError(); return BuildCXXConstructExpr( - /*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor, + /*FIXME:ConstructLoc*/ SourceLocation(), ToType, + SCS.FoundCopyConstructor, SCS.CopyConstructor, ConstructorArgs, /*HadMultipleCandidates*/ false, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); } return BuildCXXConstructExpr( - /*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor, + /*FIXME:ConstructLoc*/ SourceLocation(), ToType, + SCS.FoundCopyConstructor, SCS.CopyConstructor, From, /*HadMultipleCandidates*/ false, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -4314,6 +4581,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); } + case BTT_IsAssignable: case BTT_IsNothrowAssignable: case BTT_IsTriviallyAssignable: { // C++11 [meta.unary.prop]p3: @@ -4361,6 +4629,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, if (Result.isInvalid() || SFINAE.hasErrorOccurred()) return false; + if (BTT == BTT_IsAssignable) + return true; + if (BTT == BTT_IsNothrowAssignable) return Self.canThrow(Result.get()) == CT_Cannot; @@ -4652,7 +4923,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, return Result; } -/// \brief Try to convert a type to another according to C++0x 5.16p3. +/// \brief Try to convert a type to another according to C++11 5.16p3. /// /// This is part of the parameter validation for the ? operator. If either /// value operand is a class type, the two operands are attempted to be @@ -4668,17 +4939,21 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, InitializationKind Kind = InitializationKind::CreateCopy(To->getLocStart(), SourceLocation()); - // C++0x 5.16p3 + // C++11 5.16p3 // The process for determining whether an operand expression E1 of type T1 // can be converted to match an operand expression E2 of type T2 is defined // as follows: - // -- If E2 is an lvalue: - bool ToIsLvalue = To->isLValue(); - if (ToIsLvalue) { - // E1 can be converted to match E2 if E1 can be implicitly converted to - // type "lvalue reference to T2", subject to the constraint that in the - // conversion the reference must bind directly to E1. - QualType T = Self.Context.getLValueReferenceType(ToType); + // -- If E2 is an lvalue: E1 can be converted to match E2 if E1 can be + // implicitly converted to type "lvalue reference to T2", subject to the + // constraint that in the conversion the reference must bind directly to + // an lvalue. + // -- If E2 is an xvalue: E1 can be converted to match E2 if E1 can be + // implicitly conveted to the type "rvalue reference to R2", subject to + // the constraint that the reference must bind directly. + if (To->isLValue() || To->isXValue()) { + QualType T = To->isLValue() ? Self.Context.getLValueReferenceType(ToType) + : Self.Context.getRValueReferenceType(ToType); + InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); InitializationSequence InitSeq(Self, Entity, Kind, From); @@ -5029,6 +5304,12 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, QualType ResTy = UsualArithmeticConversions(LHS, RHS); if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); + if (ResTy.isNull()) { + Diag(QuestionLoc, + diag::err_typecheck_cond_incompatible_operands) << LTy << RTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy)); RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy)); @@ -5390,7 +5671,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { if (!ReturnsRetained && E->getType()->isObjCARCImplicitlyUnretainedType()) return E; - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject : CK_ARCReclaimReturnedObject); @@ -5443,7 +5724,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { return E; // We need a cleanup, but we don't need to remember the temporary. - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); } CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor); @@ -5470,14 +5751,16 @@ Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) { unsigned FirstCleanup = ExprEvalContexts.back().NumCleanupObjects; assert(ExprCleanupObjects.size() >= FirstCleanup); - assert(ExprNeedsCleanups || ExprCleanupObjects.size() == FirstCleanup); - if (!ExprNeedsCleanups) + assert(Cleanup.exprNeedsCleanups() || + ExprCleanupObjects.size() == FirstCleanup); + if (!Cleanup.exprNeedsCleanups()) return SubExpr; auto Cleanups = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup, ExprCleanupObjects.size() - FirstCleanup); - Expr *E = ExprWithCleanups::Create(Context, SubExpr, Cleanups); + auto *E = ExprWithCleanups::Create( + Context, SubExpr, Cleanup.cleanupsHaveSideEffects(), Cleanups); DiscardCleanupsInEvaluationContext(); return E; @@ -5488,7 +5771,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { CleanupVarDeclMarking(); - if (!ExprNeedsCleanups) + if (!Cleanup.exprNeedsCleanups()) return SubStmt; // FIXME: In order to attach the temporaries, wrap the statement into @@ -5594,7 +5877,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { return ExprError(); // We need a cleanup, but we don't need to remember the temporary. - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); } // Possibly strip off the top CXXBindTemporaryExpr. @@ -5746,7 +6029,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, MayBePseudoDestructor = true; return Base; } else if (!BaseType->isRecordType()) { - ObjectType = ParsedType(); + ObjectType = nullptr; MayBePseudoDestructor = true; return Base; } @@ -5789,7 +6072,7 @@ static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) { ObjectType = Ptr->getPointeeType(); } else if (!Base->isTypeDependent()) { - // The user wrote "p->" when she probably meant "p."; fix it. + // The user wrote "p->" when they probably meant "p."; fix it. S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) << ObjectType << true << FixItHint::CreateReplacement(OpLoc, "."); @@ -6082,9 +6365,12 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, // follows the normal lifetime rules for block literals instead of being // autoreleased. DiagnosticErrorTrap Trap(Diags); + PushExpressionEvaluationContext(PotentiallyEvaluated); ExprResult Exp = BuildBlockForLambdaConversion(E->getExprLoc(), E->getExprLoc(), Method, E); + PopExpressionEvaluationContext(); + if (Exp.isInvalid()) Diag(E->getExprLoc(), diag::note_lambda_to_block_conv); return Exp; @@ -6390,7 +6676,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures( static ExprResult attemptRecovery(Sema &SemaRef, const TypoCorrectionConsumer &Consumer, - TypoCorrection TC) { + const TypoCorrection &TC) { LookupResult R(SemaRef, Consumer.getLookupResult().getLookupNameInfo(), Consumer.getLookupResult().getLookupKind()); const CXXScopeSpec *SS = Consumer.getSS(); @@ -6567,6 +6853,14 @@ public: ExprResult TransformBlockExpr(BlockExpr *E) { return Owned(E); } + ExprResult TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { + return Owned(E); + } + + ExprResult TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) { + return Owned(E); + } + ExprResult Transform(Expr *E) { ExprResult Res; while (true) { |