summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r--lib/Sema/SemaExprCXX.cpp542
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) {