diff options
| author | 2019-01-27 16:42:12 +0000 | |
|---|---|---|
| committer | 2019-01-27 16:42:12 +0000 | |
| commit | b773203fb58f3ef282fb69c832d8710cab5bc82d (patch) | |
| tree | e75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/clang/lib/Sema/SemaExpr.cpp | |
| parent | tweak errno in previous (diff) | |
| download | wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip | |
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Sema/SemaExpr.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Sema/SemaExpr.cpp | 1587 |
1 files changed, 1005 insertions, 582 deletions
diff --git a/gnu/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/gnu/llvm/tools/clang/lib/Sema/SemaExpr.cpp index a6e43765e10..3dc6fb151cb 100644 --- a/gnu/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/gnu/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -37,6 +37,7 @@ #include "clang/Sema/Designator.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Overload.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" @@ -47,7 +48,7 @@ using namespace clang; using namespace sema; -/// \brief Determine whether the use of this declaration is valid, without +/// Determine whether the use of this declaration is valid, without /// emitting diagnostics. bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) { // See if this is an auto-typed variable whose initializer we are parsing. @@ -88,7 +89,7 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { } } -/// \brief Emit a note explaining that this function is deleted. +/// Emit a note explaining that this function is deleted. void Sema::NoteDeletedFunction(FunctionDecl *Decl) { assert(Decl->isDeleted()); @@ -116,7 +117,7 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) { << Decl << true; } -/// \brief Determine whether a FunctionDecl was ever declared with an +/// Determine whether a FunctionDecl was ever declared with an /// explicit storage class. static bool hasAnyExplicitStorageClass(const FunctionDecl *D) { for (auto I : D->redecls()) { @@ -126,7 +127,7 @@ static bool hasAnyExplicitStorageClass(const FunctionDecl *D) { return false; } -/// \brief Check whether we're in an extern inline function and referring to a +/// Check whether we're in an extern inline function and referring to a /// variable or function with internal linkage (C11 6.7.4p3). /// /// This is only a warning because we used to silently accept this code, but @@ -189,7 +190,7 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) { } } -/// \brief Determine whether the use of this declaration is valid, and +/// Determine whether the use of this declaration is valid, and /// emit any corresponding diagnostics. /// /// This routine diagnoses various problems with referencing @@ -201,10 +202,11 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) { /// \returns true if there was an error (this declaration cannot be /// referenced), false otherwise. /// -bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, +bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass, bool ObjCPropertyAccess, bool AvoidPartialAvailabilityChecks) { + SourceLocation Loc = Locs.front(); if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) { // If there were any diagnostics suppressed by template argument deduction, // emit them now. @@ -246,7 +248,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, Diag(Loc, diag::err_deleted_inherited_ctor_use) << Ctor->getParent() << Ctor->getInheritedConstructor().getConstructor()->getParent(); - else + else Diag(Loc, diag::err_deleted_function_use); NoteDeletedFunction(FD); return true; @@ -288,7 +290,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, return true; } - DiagnoseAvailabilityOfDecl(D, Loc, UnknownObjCClass, ObjCPropertyAccess, + DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess, AvoidPartialAvailabilityChecks); DiagnoseUnusedOfDecl(*this, D, Loc); @@ -298,7 +300,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, return false; } -/// \brief Retrieve the message suffix that should be added to a +/// Retrieve the message suffix that should be added to a /// diagnostic complaining about the given function being deleted or /// unavailable. std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) { @@ -399,7 +401,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, if (MissingNilLoc.isInvalid()) Diag(Loc, diag::warn_missing_sentinel) << int(calleeType); else - Diag(MissingNilLoc, diag::warn_missing_sentinel) + Diag(MissingNilLoc, diag::warn_missing_sentinel) << int(calleeType) << FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue); Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType); @@ -421,7 +423,7 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) { if (result.isInvalid()) return ExprError(); E = result.get(); } - + QualType Ty = E->getType(); assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type"); @@ -477,12 +479,12 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE, const ObjCIvarDecl *IV = OIRE->getDecl(); if (!IV) return; - + DeclarationName MemberName = IV->getDeclName(); IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); if (!Member || !Member->isStr("isa")) return; - + const Expr *Base = OIRE->getBase(); QualType BaseType = Base->getType(); if (OIRE->isArrow()) @@ -534,7 +536,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { if (result.isInvalid()) return ExprError(); E = result.get(); } - + // C++ [conv.lval]p1: // A glvalue of a non-function, non-array type T can be // converted to a prvalue. @@ -602,8 +604,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { (void)isCompleteType(E->getExprLoc(), T); UpdateMarkingForLValueToRValue(E); - - // Loading a __weak object implicitly retains the value, so we need a cleanup to + + // Loading a __weak object implicitly retains the value, so we need a cleanup to // balance that. if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) Cleanup.setExprNeedsCleanups(true); @@ -612,14 +614,14 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { nullptr, VK_RValue); // C11 6.3.2.1p2: - // ... if the lvalue has atomic type, the value has the non-atomic version + // ... if the lvalue has atomic type, the value has the non-atomic version // of the type of the lvalue ... if (const AtomicType *Atomic = T->getAs<AtomicType>()) { T = Atomic->getValueType().getUnqualifiedType(); Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(), nullptr, VK_RValue); } - + return Res; } @@ -776,6 +778,9 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) { return VAK_Valid; } + if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct) + return VAK_Invalid; + if (Ty.isCXX98PODType(Context)) return VAK_Valid; @@ -837,7 +842,10 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) { break; case VAK_Invalid: - if (Ty->isObjCObjectType()) + if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct) + Diag(E->getLocStart(), + diag::err_cannot_pass_non_trivial_c_struct_to_vararg) << Ty << CT; + else if (Ty->isObjCObjectType()) DiagRuntimeBehavior( E->getLocStart(), nullptr, PDiag(diag::err_cannot_pass_objc_interface_to_vararg) @@ -868,7 +876,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, E = ExprRes.get(); } } - + ExprResult ExprRes = DefaultArgumentPromotion(E); if (ExprRes.isInvalid()) return ExprError(); @@ -909,7 +917,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, return E; } -/// \brief Converts an integer to complex float type. Helper function of +/// Converts an integer to complex float type. Helper function of /// UsualArithmeticConversions() /// /// \return false if the integer expression is an integer type and is @@ -934,7 +942,7 @@ static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr, return false; } -/// \brief Handle arithmetic conversion with complex types. Helper function of +/// Handle arithmetic conversion with complex types. Helper function of /// UsualArithmeticConversions() static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS, ExprResult &RHS, QualType LHSType, @@ -990,7 +998,7 @@ static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS, return ResultType; } -/// \brief Handle arithmetic conversion from integer to float. Helper function +/// Handle arithmetic conversion from integer to float. Helper function /// of UsualArithmeticConversions() static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr, ExprResult &IntExpr, @@ -1003,7 +1011,7 @@ static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr, CK_IntegralToFloating); return FloatTy; } - + // Convert both sides to the appropriate complex float. assert(IntTy->isComplexIntegerType()); QualType result = S.Context.getComplexType(FloatTy); @@ -1021,7 +1029,7 @@ static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr, return result; } -/// \brief Handle arithmethic conversion with floating point types. Helper +/// Handle arithmethic conversion with floating point types. Helper /// function of UsualArithmeticConversions() static QualType handleFloatConversion(Sema &S, ExprResult &LHS, ExprResult &RHS, QualType LHSType, @@ -1059,7 +1067,7 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS, /*convertFloat=*/!IsCompAssign); } -/// \brief Diagnose attempts to convert between __float128 and long double if +/// Diagnose attempts to convert between __float128 and long double if /// there is no support for such conversion. Helper function of /// UsualArithmeticConversions(). static bool unsupportedTypeConversion(const Sema &S, QualType LHSType, @@ -1092,13 +1100,12 @@ static bool unsupportedTypeConversion(const Sema &S, QualType LHSType, Float128AndLongDouble |= (LHSElemType == S.Context.LongDoubleTy && RHSElemType == S.Context.Float128Ty); - /* We've handled the situation where __float128 and long double have the same - representation. The only other allowable conversion is if long double is - really just double. - */ + // We've handled the situation where __float128 and long double have the same + // representation. We allow all conversions for all possible long double types + // except PPC's double double. return Float128AndLongDouble && - (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) != - &llvm::APFloat::IEEEdouble()); + (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) == + &llvm::APFloat::PPCDoubleDouble()); } typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType); @@ -1116,7 +1123,7 @@ ExprResult doComplexIntegralCast(Sema &S, Expr *op, QualType toType) { } } -/// \brief Handle integer arithmetic conversions. Helper function of +/// Handle integer arithmetic conversions. Helper function of /// UsualArithmeticConversions() template <PerformCastFn doLHSCast, PerformCastFn doRHSCast> static QualType handleIntegerConversion(Sema &S, ExprResult &LHS, @@ -1167,7 +1174,7 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS, } } -/// \brief Handle conversions with GCC complex int extension. Helper function +/// Handle conversions with GCC complex int extension. Helper function /// of UsualArithmeticConversions() static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS, ExprResult &RHS, QualType LHSType, @@ -1194,7 +1201,7 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS, QualType ComplexType = S.Context.getComplexType(ScalarType); RHS = S.ImpCastExprToType(RHS.get(), ComplexType, CK_IntegralRealToComplex); - + return ComplexType; } @@ -1205,7 +1212,7 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS, handleIntegerConversion<doIntegralCast, doComplexIntegralCast> (S, LHS, RHS, LHSType, RHSEltType, IsCompAssign); QualType ComplexType = S.Context.getComplexType(ScalarType); - + if (!IsCompAssign) LHS = S.ImpCastExprToType(LHS.get(), ComplexType, CK_IntegralRealToComplex); @@ -1529,6 +1536,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { CharTy = Context.getWideCharType(); Kind = StringLiteral::Wide; } else if (Literal.isUTF8()) { + if (getLangOpts().Char8) + CharTy = Context.Char8Ty; Kind = StringLiteral::UTF8; } else if (Literal.isUTF16()) { CharTy = Context.Char16Ty; @@ -1545,17 +1554,14 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) CharTyConst.addConst(); + CharTyConst = Context.adjustStringLiteralBaseType(CharTyConst); + // Get an array type for the string, according to C99 6.4.5. This includes // the nul terminator character as well as the string length for pascal // strings. - QualType StrTy = Context.getConstantArrayType(CharTyConst, - llvm::APInt(32, Literal.GetNumStringChars()+1), - ArrayType::Normal, 0); - - // OpenCL v1.1 s6.5.3: a string literal is in the constant address space. - if (getLangOpts().OpenCL) { - StrTy = Context.getAddrSpaceQualType(StrTy, LangAS::opencl_constant); - } + QualType StrTy = Context.getConstantArrayType( + CharTyConst, llvm::APInt(32, Literal.GetNumStringChars() + 1), + ArrayType::Normal, 0); // Pass &StringTokLocs[0], StringTokLocs.size() to factory! StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(), @@ -1674,9 +1680,9 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, MarkDeclRefReferenced(E); if (getLangOpts().ObjCWeak && isa<VarDecl>(D) && - Ty.getObjCLifetime() == Qualifiers::OCL_Weak && + Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) - recordUseOfEvaluatedWeak(E); + getCurFunction()->recordUseOfWeak(E); FieldDecl *FD = dyn_cast<FieldDecl>(D); if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(D)) @@ -2074,16 +2080,17 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, (Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam) ? LookupObjCImplicitSelfParam : LookupOrdinaryName); - if (TemplateArgs) { + if (TemplateKWLoc.isValid() || TemplateArgs) { // Lookup the template name again to correctly establish the context in // which it was found. This is really unfortunate as we already did the // lookup to determine that it was a template name in the first place. If // this becomes a performance hit, we can work harder to preserve those // results until we get here but it's likely not worth it. bool MemberOfUnknownSpecialization; - LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false, - MemberOfUnknownSpecialization); - + if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false, + MemberOfUnknownSpecialization, TemplateKWLoc)) + return ExprError(); + if (MemberOfUnknownSpecialization || (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, @@ -2092,7 +2099,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl(); LookupParsedName(R, S, &SS, !IvarLookupFollowUp); - // If the result might be in a dependent base class, this is a dependent + // If the result might be in a dependent base class, this is a dependent // id-expression. if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, @@ -2149,6 +2156,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, if (SS.isValid()) CCC->setTypoNNS(SS.getScopeRep()); } + // FIXME: DiagnoseEmptyLookup produces bad diagnostics if we're looking for + // a template name, but we happen to have always already looked up the name + // before we get here if it must be a template name. if (DiagnoseEmptyLookup(S, SS, R, CCC ? std::move(CCC) : std::move(DefaultValidator), nullptr, None, &TE)) { @@ -2347,7 +2357,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, IdentifierInfo *II, bool AllowBuiltinCreation) { SourceLocation Loc = Lookup.getNameLoc(); ObjCMethodDecl *CurMethod = getCurMethodDecl(); - + // Check for error condition which is already reported. if (!CurMethod) return ExprError(); @@ -2426,15 +2436,16 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, IV->getLocation(), SelfExpr.get(), true, true); if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { - if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) - recordUseOfEvaluatedWeak(Result); + if (!isUnevaluatedContext() && + !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) + getCurFunction()->recordUseOfWeak(Result); } if (getLangOpts().ObjCAutoRefCount) { if (CurContext->isClosure()) Diag(Loc, diag::warn_implicitly_retains_self) << FixItHint::CreateInsertion(Loc, "self->"); } - + return Result; } } else if (CurMethod->isInstanceMethod()) { @@ -2471,7 +2482,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, return ExprResult((Expr *)nullptr); } -/// \brief Cast a base object to a member's actual type. +/// Cast a base object to a member's actual type. /// /// Logically this happens in three phases: /// @@ -2717,12 +2728,23 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { return false; } +// Certain multiversion types should be treated as overloaded even when there is +// only one result. +static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) { + assert(R.isSingleResult() && "Expected only a single result"); + const auto *FD = dyn_cast<FunctionDecl>(R.getFoundDecl()); + return FD && + (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion()); +} + ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl) { // If this is a single, fully-resolved result and we don't need ADL, // just build an ordinary singleton decl ref. - if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>()) + if (!NeedsADL && R.isSingleResult() && + !R.getAsSingle<FunctionTemplateDecl>() && + !ShouldLookupResultBeMultiVersionOverload(R)) return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(), R.getRepresentativeDecl(), nullptr, AcceptInvalidDecl); @@ -2730,7 +2752,7 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // We only need to check the declaration if there's exactly one // result, because in the overloaded case the results can only be // functions and function templates. - if (R.isSingleResult() && + if (R.isSingleResult() && !ShouldLookupResultBeMultiVersionOverload(R) && CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) return ExprError(); @@ -2753,7 +2775,7 @@ static void diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, ValueDecl *var, DeclContext *DC); -/// \brief Complete semantic analysis for a reference to the given declaration. +/// Complete semantic analysis for a reference to the given declaration. ExprResult Sema::BuildDeclarationNameExpr( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, @@ -2769,9 +2791,7 @@ ExprResult Sema::BuildDeclarationNameExpr( if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) { // Specifically diagnose references to class templates that are missing // a template argument list. - Diag(Loc, diag::err_template_decl_ref) << (isa<VarTemplateDecl>(D) ? 1 : 0) - << Template << SS.getRange(); - Diag(Template->getLocation(), diag::note_template_decl_here); + diagnoseMissingTemplateArguments(TemplateName(Template), Loc); return ExprError(); } @@ -2898,7 +2918,7 @@ ExprResult Sema::BuildDeclarationNameExpr( if (!CapturedType.isNull()) type = CapturedType; } - + break; } @@ -2914,7 +2934,7 @@ ExprResult Sema::BuildDeclarationNameExpr( diagnoseUncapturableValueReference(*this, Loc, BD, CurContext); break; } - + case Decl::Function: { if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) { if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) { @@ -2939,7 +2959,7 @@ ExprResult Sema::BuildDeclarationNameExpr( valueKind = VK_LValue; break; } - + // C99 DR 316 says that, if a function type comes from a // function definition (without a prototype), that type is only // used for checking compatibility. Therefore, when referencing @@ -3034,8 +3054,9 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, unsigned Length = Str.length(); llvm::APInt LengthI(32, Length + 1); - if (IT == PredefinedExpr::LFunction) { - ResTy = Context.WideCharTy.withConst(); + if (IT == PredefinedExpr::LFunction || IT == PredefinedExpr::LFuncSig) { + ResTy = + Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst()); SmallString<32> RawChars; ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(), Str, RawChars); @@ -3044,7 +3065,7 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide, /*Pascal*/ false, ResTy, Loc); } else { - ResTy = Context.CharTy.withConst(); + ResTy = Context.adjustStringLiteralBaseType(Context.CharTy.withConst()); ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, /*IndexTypeQuals*/ 0); SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii, @@ -3064,7 +3085,8 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break; case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS] case tok::kw___FUNCSIG__: IT = PredefinedExpr::FuncSig; break; // [MS] - case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; + case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; // [MS] + case tok::kw_L__FUNCSIG__: IT = PredefinedExpr::LFuncSig; break; // [MS] case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break; } @@ -3086,6 +3108,8 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { QualType Ty; if (Literal.isWide()) Ty = Context.WideCharTy; // L'x' -> wchar_t in C and C++. + else if (Literal.isUTF8() && getLangOpts().Char8) + Ty = Context.Char8Ty; // u8'x' -> char8_t when it exists. else if (Literal.isUTF16()) Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11. else if (Literal.isUTF32()) @@ -3281,8 +3305,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // operator "" X ("n") unsigned Length = Literal.getUDSuffixOffset(); QualType StrTy = Context.getConstantArrayType( - Context.CharTy.withConst(), llvm::APInt(32, Length + 1), - ArrayType::Normal, 0); + Context.adjustStringLiteralBaseType(Context.CharTy.withConst()), + llvm::APInt(32, Length + 1), ArrayType::Normal, 0); Expr *Lit = StringLiteral::Create( Context, StringRef(TokSpelling.data(), Length), StringLiteral::Ascii, /*Pascal*/false, StrTy, &TokLoc, 1); @@ -3314,7 +3338,52 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { Expr *Res; - if (Literal.isFloatingLiteral()) { + if (Literal.isFixedPointLiteral()) { + QualType Ty; + + if (Literal.isAccum) { + if (Literal.isHalf) { + Ty = Context.ShortAccumTy; + } else if (Literal.isLong) { + Ty = Context.LongAccumTy; + } else { + Ty = Context.AccumTy; + } + } else if (Literal.isFract) { + if (Literal.isHalf) { + Ty = Context.ShortFractTy; + } else if (Literal.isLong) { + Ty = Context.LongFractTy; + } else { + Ty = Context.FractTy; + } + } + + if (Literal.isUnsigned) Ty = Context.getCorrespondingUnsignedType(Ty); + + bool isSigned = !Literal.isUnsigned; + unsigned scale = Context.getFixedPointScale(Ty); + unsigned ibits = Context.getFixedPointIBits(Ty); + unsigned bit_width = Context.getTypeInfo(Ty).Width; + + llvm::APInt Val(bit_width, 0, isSigned); + bool Overflowed = Literal.GetFixedPointValue(Val, scale); + + // Do not use bit_width since some types may have padding like _Fract or + // unsigned _Accums if PaddingOnUnsignedFixedPoint is set. + auto MaxVal = llvm::APInt::getMaxValue(ibits + scale).zextOrSelf(bit_width); + if (Literal.isFract && Val == MaxVal + 1) + // Clause 6.4.4 - The value of a constant shall be in the range of + // representable values for its type, with exception for constants of a + // fract type with a value of exactly 1; such a constant shall denote + // the maximal value for the type. + --Val; + else if (Val.ugt(MaxVal) || Overflowed) + Diag(Tok.getLocation(), diag::err_too_large_for_fixed_point); + + Res = FixedPointLiteral::CreateFromRawInt(Context, Val, Ty, + Tok.getLocation(), scale); + } else if (Literal.isFloatingLiteral()) { QualType Ty; if (Literal.isHalf){ if (getOpenCLOptions().isEnabled("cl_khr_fp16")) @@ -3554,7 +3623,7 @@ static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T, return false; } -/// \brief Check whether E is a pointer from a decayed array type (the decayed +/// Check whether E is a pointer from a decayed array type (the decayed /// pointer type is equal to T) and emit a warning if it is. static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T, Expr *E) { @@ -3572,7 +3641,7 @@ static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T, << ICE->getSubExpr()->getType(); } -/// \brief Check the constraints on expression operands to unary type expression +/// Check the constraints on expression operands to unary type expression /// and type traits. /// /// Completes any types necessary and validates the constraints on the operand @@ -3656,7 +3725,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, return false; } -/// \brief Check the constraints on operands to unary expression and type +/// Check the constraints on operands to unary expression and type /// traits. /// /// This will complete any types necessary, and validate the various constraints @@ -3910,7 +3979,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, } while (!T.isNull() && T->isVariablyModifiedType()); } -/// \brief Build a sizeof or alignof expression given a type operand. +/// Build a sizeof or alignof expression given a type operand. ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, SourceLocation OpLoc, @@ -3954,17 +4023,17 @@ Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd()); } -/// \brief Build a sizeof or alignof expression given an expression +/// Build a sizeof or alignof expression given an expression /// operand. ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind) { ExprResult PE = CheckPlaceholderExpr(E); - if (PE.isInvalid()) + if (PE.isInvalid()) return ExprError(); E = PE.get(); - + // Verify that the operand is valid. bool isInvalid = false; if (E->isTypeDependent()) { @@ -4072,7 +4141,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, return BuildUnaryOp(S, OpLoc, Opc, Input); } -/// \brief Diagnose if arithmetic on the given ObjC pointer is illegal. +/// Diagnose if arithmetic on the given ObjC pointer is illegal. /// /// \return true on error static bool checkArithmeticOnObjCPointer(Sema &S, @@ -4328,10 +4397,13 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // Per C++ core issue 1213, the result is an xvalue if either operand is // a non-lvalue array, and an lvalue otherwise. - if (getLangOpts().CPlusPlus11 && - ((LHSExp->getType()->isArrayType() && !LHSExp->isLValue()) || - (RHSExp->getType()->isArrayType() && !RHSExp->isLValue()))) - VK = VK_XValue; + if (getLangOpts().CPlusPlus11) { + for (auto *Op : {LHSExp, RHSExp}) { + Op = Op->IgnoreImplicit(); + if (Op->getType()->isArrayType() && !Op->isLValue()) + VK = VK_XValue; + } + } // Perform default conversions. if (!LHSExp->getType()->getAs<VectorType>()) { @@ -4392,12 +4464,24 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, } else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) { BaseExpr = LHSExp; // vectors: V[123] IndexExpr = RHSExp; + // We apply C++ DR1213 to vector subscripting too. + if (getLangOpts().CPlusPlus11 && LHSExp->getValueKind() == VK_RValue) { + ExprResult Materialized = TemporaryMaterializationConversion(LHSExp); + if (Materialized.isInvalid()) + return ExprError(); + LHSExp = Materialized.get(); + } VK = LHSExp->getValueKind(); if (VK != VK_RValue) OK = OK_VectorComponent; - // FIXME: need to deal with const... ResultType = VTy->getElementType(); + QualType BaseType = BaseExpr->getType(); + Qualifiers BaseQuals = BaseType.getQualifiers(); + Qualifiers MemberQuals = ResultType.getQualifiers(); + Qualifiers Combined = BaseQuals + MemberQuals; + if (Combined != MemberQuals) + ResultType = Context.getQualifiedType(ResultType, Combined); } else if (LHSTy->isArrayType()) { // If we see an array that wasn't promoted by // DefaultFunctionArrayLvalueConversion, it must be an array that @@ -4478,7 +4562,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, diag::note_default_argument_declared_here); return true; } - + if (Param->hasUninstantiatedDefaultArg()) { Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); @@ -4580,7 +4664,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, "default argument expression has capturing blocks?"); } - // We already type-checked the argument, so we know it works. + // We already type-checked the argument, so we know it works. // Just mark all of the declarations in this potentially-evaluated expression // as being "referenced". MarkDeclarationsReferencedInExpr(Param->getDefaultArg(), @@ -4777,7 +4861,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig) Diag(FDecl->getLocStart(), diag::note_callee_decl) << FDecl; - + // This deletes the extra arguments. Call->setNumArgs(Context, NumParams); return true; @@ -4785,7 +4869,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, } SmallVector<Expr *, 8> AllArgs; VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn); - + Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl, Proto, 0, Args, AllArgs, CallType); if (Invalid) @@ -4831,6 +4915,10 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, (!Param || !Param->hasAttr<CFConsumedAttr>())) CFAudited = true; + if (Proto->getExtParameterInfo(i).isNoEscape()) + if (auto *BE = dyn_cast<BlockExpr>(Arg->IgnoreParenNoopCasts(Context))) + BE->getBlockDecl()->setDoesNotEscape(); + InitializedEntity Entity = Param ? InitializedEntity::InitializeParameter(Context, Param, ProtoArgType) @@ -5187,11 +5275,11 @@ tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs( // Check if the naming class in which the unresolved members were found is // related (same as or is a base of) to the enclosing class. - + if (!enclosingClassIsRelatedToClassInWhichMembersWereFound(UME, S)) return; - - + + DeclContext *EnclosingFunctionCtx = S.CurContext->getParent()->getParent(); // If the enclosing function is not dependent, then this lambda is // capture ready, so if we can capture this, do so. @@ -5496,7 +5584,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // CUDA: Kernel calls must be to global functions if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>()) return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function) - << FDecl->getName() << Fn->getSourceRange()); + << FDecl << Fn->getSourceRange()); // CUDA: Kernel function must have 'void' return type if (!FuncT->getReturnType()->isVoidType()) @@ -5506,7 +5594,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // CUDA: Calls to global functions must be configured if (FDecl && FDecl->hasAttr<CUDAGlobalAttr>()) return ExprError(Diag(LParenLoc, diag::err_global_call_not_config) - << FDecl->getName() << Fn->getSourceRange()); + << FDecl << Fn->getSourceRange()); } } @@ -5537,7 +5625,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments) << (Args.size() > Def->param_size()) << FDecl << Fn->getSourceRange(); } - + // If the function we're calling isn't a function prototype, but we have // a function prototype from a prior declaratiom, use that prototype. if (!FDecl->hasPrototype()) @@ -5555,7 +5643,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, PerformCopyInitialization(Entity, SourceLocation(), Arg); if (ArgE.isInvalid()) return true; - + Arg = ArgE.getAs<Expr>(); } else { @@ -5566,7 +5654,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, Arg = ArgE.getAs<Expr>(); } - + if (RequireCompleteType(Arg->getLocStart(), Arg->getType(), diag::err_call_incomplete_argument, Arg)) @@ -5640,7 +5728,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, InitializedEntity Entity = InitializedEntity::InitializeCompoundLiteralInit(TInfo); InitializationKind Kind - = InitializationKind::CreateCStyleCast(LParenLoc, + = InitializationKind::CreateCStyleCast(LParenLoc, SourceRange(LParenLoc, RParenLoc), /*InitList=*/true); InitializationSequence InitSeq(*this, Entity, Kind, LiteralExpr); @@ -5705,7 +5793,7 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, } // Semantic analysis for initializers is done by ActOnDeclarator() and - // CheckInitializer() - it requires knowledge of the object being intialized. + // CheckInitializer() - it requires knowledge of the object being initialized. InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitArgList, RBraceLoc); @@ -5919,11 +6007,11 @@ static bool breakDownVectorType(QualType type, uint64_t &len, assert(eltType->isScalarType()); return true; } - + // We allow lax conversion to and from non-vector types, but only if // they're real types (i.e. non-complex, non-pointer scalar types). if (!type->isRealType()) return false; - + len = 1; eltType = type; return true; @@ -5938,7 +6026,7 @@ static bool breakDownVectorType(QualType type, uint64_t &len, /// vector nor a real type. bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) { assert(destTy->isVectorType() || srcTy->isVectorType()); - + // Disallow lax conversions between scalars and ExtVectors (these // conversions are allowed for other vector types because common headers // depend on them). Most scalar OP ExtVector cases are handled by the @@ -5951,13 +6039,13 @@ bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) { QualType srcEltTy, destEltTy; if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false; if (!breakDownVectorType(destTy, destLen, destEltTy)) return false; - + // ASTContext::getTypeSize will return the size rounded up to a // power of 2, so instead of using that, we need to use the raw // element size multiplied by the element count. uint64_t srcEltSize = Context.getTypeSize(srcEltTy); uint64_t destEltSize = Context.getTypeSize(destEltTy); - + return (srcLen * srcEltSize == destLen * destEltSize); } @@ -5965,7 +6053,7 @@ bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) { /// known to be a vector type? bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) { assert(destTy->isVectorType() || srcTy->isVectorType()); - + if (!Context.getLangOpts().LaxVectorConversions) return false; return areLaxCompatibleVectorTypes(srcTy, destTy); @@ -6123,9 +6211,9 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, if (getLangOpts().CPlusPlus && !castType->isVoidType() && !getSourceManager().isInSystemMacro(LParenLoc)) Diag(LParenLoc, diag::warn_old_style_cast) << CastExpr->getSourceRange(); - + CheckTollFreeBridgeCast(castType, CastExpr); - + CheckObjCBridgeRelatedCast(castType, CastExpr); DiscardMisalignedMemberAddress(castType.getTypePtr(), CastExpr); @@ -6162,7 +6250,7 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, SmallVector<Expr *, 8> initExprs; const VectorType *VTy = Ty->getAs<VectorType>(); unsigned numElems = Ty->getAs<VectorType>()->getNumElements(); - + // '(...)' form of vector initialization in AltiVec: the number of // initializers must be one or must match the size of the vector. // If a single value is specified in the initializer then it will be @@ -6202,7 +6290,7 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, PrepareScalarCast(Literal, ElemTy)); return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.get()); } - + initExprs.append(exprs, exprs + numExprs); } // FIXME: This means that pretty-printing the final AST will produce curly @@ -6239,7 +6327,7 @@ ExprResult Sema::ActOnParenListExpr(SourceLocation L, return expr; } -/// \brief Emit a specialized diagnostic when one expression is a null pointer +/// Emit a specialized diagnostic when one expression is a null pointer /// constant and the other is not a pointer. Returns true if a diagnostic is /// emitted. bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr, @@ -6280,7 +6368,7 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr, return true; } -/// \brief Return false if the condition expression is valid, true otherwise. +/// Return false if the condition expression is valid, true otherwise. static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) { QualType CondTy = Cond->getType(); @@ -6299,7 +6387,7 @@ static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) { return true; } -/// \brief Handle when one or both operands are void type. +/// Handle when one or both operands are void type. static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS, ExprResult &RHS) { Expr *LHSExpr = LHS.get(); @@ -6316,7 +6404,7 @@ static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS, return S.Context.VoidTy; } -/// \brief Return false if the NullExpr can be promoted to PointerTy, +/// Return false if the NullExpr can be promoted to PointerTy, /// true otherwise. static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr, QualType PointerTy) { @@ -6329,7 +6417,7 @@ static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr, return false; } -/// \brief Checks compatibility between two pointers and return the resulting +/// Checks compatibility between two pointers and return the resulting /// type. static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, ExprResult &RHS, @@ -6463,7 +6551,7 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, return ResultTy; } -/// \brief Return the resulting type when the operands are both block pointers. +/// Return the resulting type when the operands are both block pointers. static QualType checkConditionalBlockPointerCompatibility(Sema &S, ExprResult &LHS, ExprResult &RHS, @@ -6488,7 +6576,7 @@ static QualType checkConditionalBlockPointerCompatibility(Sema &S, return checkConditionalPointerCompatibility(S, LHS, RHS, Loc); } -/// \brief Return the resulting type when the operands are both pointers. +/// Return the resulting type when the operands are both pointers. static QualType checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS, ExprResult &RHS, @@ -6527,7 +6615,7 @@ checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS, return checkConditionalPointerCompatibility(S, LHS, RHS, Loc); } -/// \brief Return false if the first expression is not an integer and the second +/// Return false if the first expression is not an integer and the second /// expression is not a pointer, true otherwise. static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int, Expr* PointerExpr, SourceLocation Loc, @@ -6547,7 +6635,7 @@ static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int, return true; } -/// \brief Simple conversion between integer and floating point types. +/// Simple conversion between integer and floating point types. /// /// Used when handling the OpenCL conditional operator where the /// condition is a vector while the other operands are scalar. @@ -6602,7 +6690,7 @@ static QualType OpenCLArithmeticConversions(Sema &S, ExprResult &LHS, (S, LHS, RHS, LHSType, RHSType, /*IsCompAssign = */ false); } -/// \brief Convert scalar operands to a vector that matches the +/// Convert scalar operands to a vector that matches the /// condition in length. /// /// Used when handling the OpenCL conditional operator where the @@ -6647,7 +6735,7 @@ OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS, ExprResult &RHS, return VectorTy; } -/// \brief Return false if this is a valid OpenCL condition vector +/// Return false if this is a valid OpenCL condition vector static bool checkOpenCLConditionVector(Sema &S, Expr *Cond, SourceLocation QuestionLoc) { // OpenCL v1.1 s6.11.6 says the elements of the vector must be of @@ -6662,7 +6750,7 @@ static bool checkOpenCLConditionVector(Sema &S, Expr *Cond, return true; } -/// \brief Return false if the vector condition type and the vector +/// Return false if the vector condition type and the vector /// result type are compatible. /// /// OpenCL v1.1 s6.11.6 requires that both vector types have the same @@ -6692,14 +6780,14 @@ static bool checkVectorResult(Sema &S, QualType CondTy, QualType VecResTy, return false; } -/// \brief Return the resulting type for the conditional operator in +/// Return the resulting type for the conditional operator in /// OpenCL (aka "ternary selection operator", OpenCL v1.1 /// s6.3.i) when the condition is a vector type. static QualType OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, SourceLocation QuestionLoc) { - Cond = S.DefaultFunctionArrayLvalueConversion(Cond.get()); + Cond = S.DefaultFunctionArrayLvalueConversion(Cond.get()); if (Cond.isInvalid()) return QualType(); QualType CondTy = Cond.get()->getType(); @@ -6727,7 +6815,7 @@ OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond, return OpenCLConvertScalarsToVectors(S, LHS, RHS, CondTy, QuestionLoc); } -/// \brief Return true if the Expr is block type +/// Return true if the Expr is block type static bool checkBlockType(Sema &S, const Expr *E) { if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { QualType Ty = CE->getCallee()->getType(); @@ -7050,6 +7138,10 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, E = E->IgnoreImpCasts(); E = E->IgnoreConversionOperator(); E = E->IgnoreImpCasts(); + if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) { + E = MTE->GetTemporaryExpr(); + E = E->IgnoreImpCasts(); + } // Built-in binary operator. if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) { @@ -7097,6 +7189,8 @@ static bool ExprLooksBoolean(Expr *E) { return OP->getOpcode() == UO_LNot; if (E->getType()->isPointerType()) return true; + // FIXME: What about overloaded operator calls returning "unspecified boolean + // type"s (commonly pointer-to-members)? return false; } @@ -7265,7 +7359,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; ExprResult Cond = CondExpr, LHS = LHSExpr, RHS = RHSExpr; - QualType result = CheckConditionalOperands(Cond, LHS, RHS, + QualType result = CheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc); if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() || RHS.isInvalid()) @@ -7337,7 +7431,7 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) { // Treat lifetime mismatches as fatal. else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) ConvTy = Sema::IncompatiblePointerDiscardsQualifiers; - + // For GCC/MS compatibility, other qualifier mismatches are treated // as still compatible in C. else ConvTy = Sema::CompatiblePointerDiscardsQualifiers; @@ -7684,7 +7778,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // - conversions from 'Class' to the redefinition type if (RHSType->isObjCClassType() && - Context.hasSameType(LHSType, + Context.hasSameType(LHSType, Context.getObjCClassRedefinitionType())) { Kind = CK_BitCast; return Compatible; @@ -7751,10 +7845,10 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // A* -> B* if (RHSType->isObjCObjectPointerType()) { Kind = CK_BitCast; - Sema::AssignConvertType result = + Sema::AssignConvertType result = checkObjCPointerTypesForAssignment(*this, LHSType, RHSType); if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - result == Compatible && + result == Compatible && !CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType)) result = IncompatibleObjCWeakRef; return result; @@ -7778,7 +7872,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // - conversions to 'Class' from its redefinition type if (LHSType->isObjCClassType() && - Context.hasSameType(RHSType, + Context.hasSameType(RHSType, Context.getObjCClassRedefinitionType())) { return Compatible; } @@ -7787,7 +7881,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, } // Only under strict condition T^ is compatible with an Objective-C pointer. - if (RHSType->isBlockPointerType() && + if (RHSType->isBlockPointerType() && LHSType->isBlockCompatibleObjCPointerType(Context)) { if (ConvertRHS) maybeExtendBlockObject(RHS); @@ -7848,7 +7942,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, return Incompatible; } -/// \brief Constructs a transparent union from an expression that is +/// Constructs a transparent union from an expression that is /// used to initialize the transparent union. static void ConstructTransparentUnion(Sema &S, ASTContext &C, ExprResult &EResult, QualType UnionType, @@ -8015,11 +8109,11 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, if (Diagnose && isa<ObjCProtocolExpr>(PRE)) { ObjCProtocolDecl *PDecl = cast<ObjCProtocolExpr>(PRE)->getProtocol(); if (PDecl && !PDecl->hasDefinition()) { - Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl->getName(); + Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl; Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl; } } - + CastKind Kind; Sema::AssignConvertType result = CheckAssignmentConstraints(LHSType, RHS, Kind, ConvertRHS); @@ -8054,18 +8148,57 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, RHS = E; return Compatible; } - + if (ConvertRHS) RHS = ImpCastExprToType(E, Ty, Kind); } return result; } +namespace { +/// The original operand to an operator, prior to the application of the usual +/// arithmetic conversions and converting the arguments of a builtin operator +/// candidate. +struct OriginalOperand { + explicit OriginalOperand(Expr *Op) : Orig(Op), Conversion(nullptr) { + if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Op)) + Op = MTE->GetTemporaryExpr(); + if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Op)) + Op = BTE->getSubExpr(); + if (auto *ICE = dyn_cast<ImplicitCastExpr>(Op)) { + Orig = ICE->getSubExprAsWritten(); + Conversion = ICE->getConversionFunction(); + } + } + + QualType getType() const { return Orig->getType(); } + + Expr *Orig; + NamedDecl *Conversion; +}; +} + QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, ExprResult &RHS) { + OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get()); + Diag(Loc, diag::err_typecheck_invalid_operands) - << LHS.get()->getType() << RHS.get()->getType() + << OrigLHS.getType() << OrigRHS.getType() << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + + // If a user-defined conversion was applied to either of the operands prior + // to applying the built-in operator rules, tell the user about it. + if (OrigLHS.Conversion) { + Diag(OrigLHS.Conversion->getLocation(), + diag::note_typecheck_invalid_operands_converted) + << 0 << LHS.get()->getType(); + } + if (OrigRHS.Conversion) { + Diag(OrigRHS.Conversion->getLocation(), + diag::note_typecheck_invalid_operands_converted) + << 1 << RHS.get()->getType(); + } + return QualType(); } @@ -8116,7 +8249,7 @@ static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar, // The conversion to apply to the scalar before splatting it, // if necessary. CastKind scalarCast = CK_NoOp; - + if (vectorEltTy->isIntegralType(S.Context)) { if (S.getLangOpts().OpenCL && (scalarTy->isRealFloatingType() || (scalarTy->isIntegerType() && @@ -8216,7 +8349,7 @@ static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int, QualType IntTy = Int->get()->getType().getUnqualifiedType(); // Determine if the integer constant can be expressed as a floating point - // number of the appropiate type. + // number of the appropriate type. llvm::APSInt Result; bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); uint64_t Bits = 0; @@ -8576,7 +8709,7 @@ QualType Sema::CheckRemainderOperands( if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) { - if (LHS.get()->getType()->hasIntegerRepresentation() && + if (LHS.get()->getType()->hasIntegerRepresentation() && RHS.get()->getType()->hasIntegerRepresentation()) return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign, /*AllowBothBool*/getLangOpts().AltiVec, @@ -8594,7 +8727,7 @@ QualType Sema::CheckRemainderOperands( return compType; } -/// \brief Diagnose invalid arithmetic on two void pointers. +/// Diagnose invalid arithmetic on two void pointers. static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc, Expr *LHSExpr, Expr *RHSExpr) { S.Diag(Loc, S.getLangOpts().CPlusPlus @@ -8604,7 +8737,7 @@ static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc, << RHSExpr->getSourceRange(); } -/// \brief Diagnose invalid arithmetic on a void pointer. +/// Diagnose invalid arithmetic on a void pointer. static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc, Expr *Pointer) { S.Diag(Loc, S.getLangOpts().CPlusPlus @@ -8613,7 +8746,7 @@ static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc, << 0 /* one pointer */ << Pointer->getSourceRange(); } -/// \brief Diagnose invalid arithmetic on a null pointer. +/// Diagnose invalid arithmetic on a null pointer. /// /// If \p IsGNUIdiom is true, the operation is using the 'p = (i8*)nullptr + n' /// idiom, which we recognize as a GNU extension. @@ -8628,7 +8761,7 @@ static void diagnoseArithmeticOnNullPointer(Sema &S, SourceLocation Loc, << S.getLangOpts().CPlusPlus << Pointer->getSourceRange(); } -/// \brief Diagnose invalid arithmetic on two function pointers. +/// Diagnose invalid arithmetic on two function pointers. static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc, Expr *LHS, Expr *RHS) { assert(LHS->getType()->isAnyPointerType()); @@ -8644,7 +8777,7 @@ static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc, << LHS->getSourceRange() << RHS->getSourceRange(); } -/// \brief Diagnose invalid arithmetic on a function pointer. +/// Diagnose invalid arithmetic on a function pointer. static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc, Expr *Pointer) { assert(Pointer->getType()->isAnyPointerType()); @@ -8656,7 +8789,7 @@ static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc, << Pointer->getSourceRange(); } -/// \brief Emit error if Operand is incomplete pointer type +/// Emit error if Operand is incomplete pointer type /// /// \returns True if pointer has incomplete type static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, @@ -8672,7 +8805,7 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, PointeeTy, Operand->getSourceRange()); } -/// \brief Check the validity of an arithmetic pointer operand. +/// Check the validity of an arithmetic pointer operand. /// /// If the operand has pointer type, this code will check for pointer types /// which are invalid in arithmetic operations. These will be diagnosed @@ -8703,7 +8836,7 @@ static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc, return true; } -/// \brief Check the validity of a binary arithmetic operation w.r.t. pointer +/// Check the validity of a binary arithmetic operation w.r.t. pointer /// operands. /// /// This routine will diagnose any invalid arithmetic on pointer operands much @@ -8805,7 +8938,7 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc, Self.Diag(OpLoc, diag::note_string_plus_scalar_silence); } -/// \brief Emit a warning when adding a char literal to a string. +/// Emit a warning when adding a char literal to a string. static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc, Expr *LHSExpr, Expr *RHSExpr) { const Expr *StringRefExpr = LHSExpr; @@ -8856,7 +8989,7 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc, } } -/// \brief Emit error when two pointers are incompatible. +/// Emit error when two pointers are incompatible. static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc, Expr *LHSExpr, Expr *RHSExpr) { assert(LHSExpr->getType()->isAnyPointerType()); @@ -8928,7 +9061,7 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS, // In C++ adding zero to a null pointer is defined. llvm::APSInt KnownVal; if (!getLangOpts().CPlusPlus || - (!IExp->isValueDependent() && + (!IExp->isValueDependent() && (!IExp->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) { // Check the conditions to see if this is the 'p = nullptr + n' idiom. bool IsGNUIdiom = BinaryOperator::isNullPointerArithmeticExtension( @@ -9005,7 +9138,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, Expr::NPC_ValueDependentIsNotNull)) { // In C++ adding zero to a null pointer is defined. llvm::APSInt KnownVal; - if (!getLangOpts().CPlusPlus || + if (!getLangOpts().CPlusPlus || (!RHS.get()->isValueDependent() && (!RHS.get()->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) { diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false); @@ -9154,7 +9287,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, << RHS.get()->getSourceRange(); } -/// \brief Return the resulting type when a vector is shifted +/// Return the resulting type when a vector is shifted /// by a scalar or vector shift amount. static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) { @@ -9300,16 +9433,6 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS, return LHSType; } -static bool IsWithinTemplateSpecialization(Decl *D) { - if (DeclContext *DC = D->getDeclContext()) { - if (isa<ClassTemplateSpecializationDecl>(DC)) - return true; - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) - return FD->isFunctionTemplateSpecialization(); - } - return false; -} - /// If two different enums are compared, raise a warning. static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS, Expr *RHS) { @@ -9339,7 +9462,7 @@ static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS, << LHS->getSourceRange() << RHS->getSourceRange(); } -/// \brief Diagnose bad pointer comparisons. +/// Diagnose bad pointer comparisons. static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc, ExprResult &LHS, ExprResult &RHS, bool IsError) { @@ -9349,7 +9472,7 @@ static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc, << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); } -/// \brief Returns false if the pointers are converted to a composite type, +/// Returns false if the pointers are converted to a composite type, /// true otherwise. static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc, ExprResult &LHS, ExprResult &RHS) { @@ -9587,137 +9710,368 @@ static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS, // Get the decl for a simple expression: a reference to a variable, // an implicit C++ field reference, or an implicit ObjC ivar reference. static ValueDecl *getCompareDecl(Expr *E) { - if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) + if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) return DR->getDecl(); - if (ObjCIvarRefExpr* Ivar = dyn_cast<ObjCIvarRefExpr>(E)) { + if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E)) { if (Ivar->isFreeIvar()) return Ivar->getDecl(); } - if (MemberExpr* Mem = dyn_cast<MemberExpr>(E)) { + if (MemberExpr *Mem = dyn_cast<MemberExpr>(E)) { if (Mem->isImplicitAccess()) return Mem->getMemberDecl(); } return nullptr; } -// C99 6.5.8, C++ [expr.rel] -QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, BinaryOperatorKind Opc, - bool IsRelational) { - checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true); +/// Diagnose some forms of syntactically-obvious tautological comparison. +static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, + Expr *LHS, Expr *RHS, + BinaryOperatorKind Opc) { + Expr *LHSStripped = LHS->IgnoreParenImpCasts(); + Expr *RHSStripped = RHS->IgnoreParenImpCasts(); + + QualType LHSType = LHS->getType(); + QualType RHSType = RHS->getType(); + if (LHSType->hasFloatingRepresentation() || + (LHSType->isBlockPointerType() && !BinaryOperator::isEqualityOp(Opc)) || + LHS->getLocStart().isMacroID() || RHS->getLocStart().isMacroID() || + S.inTemplateInstantiation()) + return; - // Handle vector comparisons separately. - if (LHS.get()->getType()->isVectorType() || - RHS.get()->getType()->isVectorType()) - return CheckVectorCompareOperands(LHS, RHS, Loc, IsRelational); + // Comparisons between two array types are ill-formed for operator<=>, so + // we shouldn't emit any additional warnings about it. + if (Opc == BO_Cmp && LHSType->isArrayType() && RHSType->isArrayType()) + return; + + // For non-floating point types, check for self-comparisons of the form + // x == x, x != x, x < x, etc. These always evaluate to a constant, and + // often indicate logic errors in the program. + // + // NOTE: Don't warn about comparison expressions resulting from macro + // expansion. Also don't warn about comparisons which are only self + // comparisons within a template instantiation. The warnings should catch + // obvious cases in the definition of the template anyways. The idea is to + // warn when the typed comparison operator will always evaluate to the same + // result. + ValueDecl *DL = getCompareDecl(LHSStripped); + ValueDecl *DR = getCompareDecl(RHSStripped); + if (DL && DR && declaresSameEntity(DL, DR)) { + StringRef Result; + switch (Opc) { + case BO_EQ: case BO_LE: case BO_GE: + Result = "true"; + break; + case BO_NE: case BO_LT: case BO_GT: + Result = "false"; + break; + case BO_Cmp: + Result = "'std::strong_ordering::equal'"; + break; + default: + break; + } + S.DiagRuntimeBehavior(Loc, nullptr, + S.PDiag(diag::warn_comparison_always) + << 0 /*self-comparison*/ << !Result.empty() + << Result); + } else if (DL && DR && + DL->getType()->isArrayType() && DR->getType()->isArrayType() && + !DL->isWeak() && !DR->isWeak()) { + // What is it always going to evaluate to? + StringRef Result; + switch(Opc) { + case BO_EQ: // e.g. array1 == array2 + Result = "false"; + break; + case BO_NE: // e.g. array1 != array2 + Result = "true"; + break; + default: // e.g. array1 <= array2 + // The best we can say is 'a constant' + break; + } + S.DiagRuntimeBehavior(Loc, nullptr, + S.PDiag(diag::warn_comparison_always) + << 1 /*array comparison*/ + << !Result.empty() << Result); + } + + if (isa<CastExpr>(LHSStripped)) + LHSStripped = LHSStripped->IgnoreParenCasts(); + if (isa<CastExpr>(RHSStripped)) + RHSStripped = RHSStripped->IgnoreParenCasts(); + + // Warn about comparisons against a string constant (unless the other + // operand is null); the user probably wants strcmp. + Expr *LiteralString = nullptr; + Expr *LiteralStringStripped = nullptr; + if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) && + !RHSStripped->isNullPointerConstant(S.Context, + Expr::NPC_ValueDependentIsNull)) { + LiteralString = LHS; + LiteralStringStripped = LHSStripped; + } else if ((isa<StringLiteral>(RHSStripped) || + isa<ObjCEncodeExpr>(RHSStripped)) && + !LHSStripped->isNullPointerConstant(S.Context, + Expr::NPC_ValueDependentIsNull)) { + LiteralString = RHS; + LiteralStringStripped = RHSStripped; + } + + if (LiteralString) { + S.DiagRuntimeBehavior(Loc, nullptr, + S.PDiag(diag::warn_stringcompare) + << isa<ObjCEncodeExpr>(LiteralStringStripped) + << LiteralString->getSourceRange()); + } +} + +static ImplicitConversionKind castKindToImplicitConversionKind(CastKind CK) { + switch (CK) { + default: { +#ifndef NDEBUG + llvm::errs() << "unhandled cast kind: " << CastExpr::getCastKindName(CK) + << "\n"; +#endif + llvm_unreachable("unhandled cast kind"); + } + case CK_UserDefinedConversion: + return ICK_Identity; + case CK_LValueToRValue: + return ICK_Lvalue_To_Rvalue; + case CK_ArrayToPointerDecay: + return ICK_Array_To_Pointer; + case CK_FunctionToPointerDecay: + return ICK_Function_To_Pointer; + case CK_IntegralCast: + return ICK_Integral_Conversion; + case CK_FloatingCast: + return ICK_Floating_Conversion; + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + return ICK_Floating_Integral; + case CK_IntegralComplexCast: + case CK_FloatingComplexCast: + case CK_FloatingComplexToIntegralComplex: + case CK_IntegralComplexToFloatingComplex: + return ICK_Complex_Conversion; + case CK_FloatingComplexToReal: + case CK_FloatingRealToComplex: + case CK_IntegralComplexToReal: + case CK_IntegralRealToComplex: + return ICK_Complex_Real; + } +} + +static bool checkThreeWayNarrowingConversion(Sema &S, QualType ToType, Expr *E, + QualType FromType, + SourceLocation Loc) { + // Check for a narrowing implicit conversion. + StandardConversionSequence SCS; + SCS.setAsIdentityConversion(); + SCS.setToType(0, FromType); + SCS.setToType(1, ToType); + if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) + SCS.Second = castKindToImplicitConversionKind(ICE->getCastKind()); + + APValue PreNarrowingValue; + QualType PreNarrowingType; + switch (SCS.getNarrowingKind(S.Context, E, PreNarrowingValue, + PreNarrowingType, + /*IgnoreFloatToIntegralConversion*/ true)) { + case NK_Dependent_Narrowing: + // Implicit conversion to a narrower type, but the expression is + // value-dependent so we can't tell whether it's actually narrowing. + case NK_Not_Narrowing: + return false; + + case NK_Constant_Narrowing: + // Implicit conversion to a narrower type, and the value is not a constant + // expression. + S.Diag(E->getLocStart(), diag::err_spaceship_argument_narrowing) + << /*Constant*/ 1 + << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << ToType; + return true; + + case NK_Variable_Narrowing: + // Implicit conversion to a narrower type, and the value is not a constant + // expression. + case NK_Type_Narrowing: + S.Diag(E->getLocStart(), diag::err_spaceship_argument_narrowing) + << /*Constant*/ 0 << FromType << ToType; + // TODO: It's not a constant expression, but what if the user intended it + // to be? Can we produce notes to help them figure out why it isn't? + return true; + } + llvm_unreachable("unhandled case in switch"); +} + +static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S, + ExprResult &LHS, + ExprResult &RHS, + SourceLocation Loc) { + using CCT = ComparisonCategoryType; QualType LHSType = LHS.get()->getType(); QualType RHSType = RHS.get()->getType(); + // Dig out the original argument type and expression before implicit casts + // were applied. These are the types/expressions we need to check the + // [expr.spaceship] requirements against. + ExprResult LHSStripped = LHS.get()->IgnoreParenImpCasts(); + ExprResult RHSStripped = RHS.get()->IgnoreParenImpCasts(); + QualType LHSStrippedType = LHSStripped.get()->getType(); + QualType RHSStrippedType = RHSStripped.get()->getType(); + + // C++2a [expr.spaceship]p3: If one of the operands is of type bool and the + // other is not, the program is ill-formed. + if (LHSStrippedType->isBooleanType() != RHSStrippedType->isBooleanType()) { + S.InvalidOperands(Loc, LHSStripped, RHSStripped); + return QualType(); + } - Expr *LHSStripped = LHS.get()->IgnoreParenImpCasts(); - Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts(); + int NumEnumArgs = (int)LHSStrippedType->isEnumeralType() + + RHSStrippedType->isEnumeralType(); + if (NumEnumArgs == 1) { + bool LHSIsEnum = LHSStrippedType->isEnumeralType(); + QualType OtherTy = LHSIsEnum ? RHSStrippedType : LHSStrippedType; + if (OtherTy->hasFloatingRepresentation()) { + S.InvalidOperands(Loc, LHSStripped, RHSStripped); + return QualType(); + } + } + if (NumEnumArgs == 2) { + // C++2a [expr.spaceship]p5: If both operands have the same enumeration + // type E, the operator yields the result of converting the operands + // to the underlying type of E and applying <=> to the converted operands. + if (!S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) { + S.InvalidOperands(Loc, LHS, RHS); + return QualType(); + } + QualType IntType = + LHSStrippedType->getAs<EnumType>()->getDecl()->getIntegerType(); + assert(IntType->isArithmeticType()); - checkEnumComparison(*this, Loc, LHS.get(), RHS.get()); - diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc); + // We can't use `CK_IntegralCast` when the underlying type is 'bool', so we + // promote the boolean type, and all other promotable integer types, to + // avoid this. + if (IntType->isPromotableIntegerType()) + IntType = S.Context.getPromotedIntegerType(IntType); - if (!LHSType->hasFloatingRepresentation() && - !(LHSType->isBlockPointerType() && IsRelational) && - !LHS.get()->getLocStart().isMacroID() && - !RHS.get()->getLocStart().isMacroID() && - !inTemplateInstantiation()) { - // For non-floating point types, check for self-comparisons of the form - // x == x, x != x, x < x, etc. These always evaluate to a constant, and - // often indicate logic errors in the program. - // - // NOTE: Don't warn about comparison expressions resulting from macro - // expansion. Also don't warn about comparisons which are only self - // comparisons within a template specialization. The warnings should catch - // obvious cases in the definition of the template anyways. The idea is to - // warn when the typed comparison operator will always evaluate to the same - // result. - ValueDecl *DL = getCompareDecl(LHSStripped); - ValueDecl *DR = getCompareDecl(RHSStripped); - if (DL && DR && DL == DR && !IsWithinTemplateSpecialization(DL)) { - DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always) - << 0 // self- - << (Opc == BO_EQ - || Opc == BO_LE - || Opc == BO_GE)); - } else if (DL && DR && LHSType->isArrayType() && RHSType->isArrayType() && - !DL->getType()->isReferenceType() && - !DR->getType()->isReferenceType()) { - // what is it always going to eval to? - char always_evals_to; - switch(Opc) { - case BO_EQ: // e.g. array1 == array2 - always_evals_to = 0; // false - break; - case BO_NE: // e.g. array1 != array2 - always_evals_to = 1; // true - break; - default: - // best we can say is 'a constant' - always_evals_to = 2; // e.g. array1 <= array2 - break; - } - DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always) - << 1 // array - << always_evals_to); - } + LHS = S.ImpCastExprToType(LHS.get(), IntType, CK_IntegralCast); + RHS = S.ImpCastExprToType(RHS.get(), IntType, CK_IntegralCast); + LHSType = RHSType = IntType; + } - if (isa<CastExpr>(LHSStripped)) - LHSStripped = LHSStripped->IgnoreParenCasts(); - if (isa<CastExpr>(RHSStripped)) - RHSStripped = RHSStripped->IgnoreParenCasts(); + // C++2a [expr.spaceship]p4: If both operands have arithmetic types, the + // usual arithmetic conversions are applied to the operands. + QualType Type = S.UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + if (Type.isNull()) + return S.InvalidOperands(Loc, LHS, RHS); + assert(Type->isArithmeticType() || Type->isEnumeralType()); + + bool HasNarrowing = checkThreeWayNarrowingConversion( + S, Type, LHS.get(), LHSType, LHS.get()->getLocStart()); + HasNarrowing |= checkThreeWayNarrowingConversion( + S, Type, RHS.get(), RHSType, RHS.get()->getLocStart()); + if (HasNarrowing) + return QualType(); - // Warn about comparisons against a string constant (unless the other - // operand is null), the user probably wants strcmp. - Expr *literalString = nullptr; - Expr *literalStringStripped = nullptr; - if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) && - !RHSStripped->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNull)) { - literalString = LHS.get(); - literalStringStripped = LHSStripped; - } else if ((isa<StringLiteral>(RHSStripped) || - isa<ObjCEncodeExpr>(RHSStripped)) && - !LHSStripped->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNull)) { - literalString = RHS.get(); - literalStringStripped = RHSStripped; - } + assert(!Type.isNull() && "composite type for <=> has not been set"); - if (literalString) { - DiagRuntimeBehavior(Loc, nullptr, - PDiag(diag::warn_stringcompare) - << isa<ObjCEncodeExpr>(literalStringStripped) - << literalString->getSourceRange()); + auto TypeKind = [&]() { + if (const ComplexType *CT = Type->getAs<ComplexType>()) { + if (CT->getElementType()->hasFloatingRepresentation()) + return CCT::WeakEquality; + return CCT::StrongEquality; } - } + if (Type->isIntegralOrEnumerationType()) + return CCT::StrongOrdering; + if (Type->hasFloatingRepresentation()) + return CCT::PartialOrdering; + llvm_unreachable("other types are unimplemented"); + }(); + + return S.CheckComparisonCategoryType(TypeKind, Loc); +} + +static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS, + ExprResult &RHS, + SourceLocation Loc, + BinaryOperatorKind Opc) { + if (Opc == BO_Cmp) + return checkArithmeticOrEnumeralThreeWayCompare(S, LHS, RHS, Loc); // C99 6.5.8p3 / C99 6.5.9p4 - UsualArithmeticConversions(LHS, RHS); + QualType Type = S.UsualArithmeticConversions(LHS, RHS); if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); + if (Type.isNull()) + return S.InvalidOperands(Loc, LHS, RHS); + assert(Type->isArithmeticType() || Type->isEnumeralType()); + + checkEnumComparison(S, Loc, LHS.get(), RHS.get()); - LHSType = LHS.get()->getType(); - RHSType = RHS.get()->getType(); + if (Type->isAnyComplexType() && BinaryOperator::isRelationalOp(Opc)) + return S.InvalidOperands(Loc, LHS, RHS); + + // Check for comparisons of floating point operands using != and ==. + if (Type->hasFloatingRepresentation() && BinaryOperator::isEqualityOp(Opc)) + S.CheckFloatComparison(Loc, LHS.get(), RHS.get()); // The result of comparisons is 'bool' in C++, 'int' in C. - QualType ResultTy = Context.getLogicalOperationType(); + return S.Context.getLogicalOperationType(); +} - if (IsRelational) { - if (LHSType->isRealType() && RHSType->isRealType()) - return ResultTy; - } else { - // Check for comparisons of floating point operands using != and ==. - if (LHSType->hasFloatingRepresentation()) - CheckFloatComparison(Loc, LHS.get(), RHS.get()); +// C99 6.5.8, C++ [expr.rel] +QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, + BinaryOperatorKind Opc) { + bool IsRelational = BinaryOperator::isRelationalOp(Opc); + bool IsThreeWay = Opc == BO_Cmp; + auto IsAnyPointerType = [](ExprResult E) { + QualType Ty = E.get()->getType(); + return Ty->isPointerType() || Ty->isMemberPointerType(); + }; - if (LHSType->isArithmeticType() && RHSType->isArithmeticType()) - return ResultTy; + // C++2a [expr.spaceship]p6: If at least one of the operands is of pointer + // type, array-to-pointer, ..., conversions are performed on both operands to + // bring them to their composite type. + // Otherwise, all comparisons expect an rvalue, so convert to rvalue before + // any type-related checks. + if (!IsThreeWay || IsAnyPointerType(LHS) || IsAnyPointerType(RHS)) { + LHS = DefaultFunctionArrayLvalueConversion(LHS.get()); + if (LHS.isInvalid()) + return QualType(); + RHS = DefaultFunctionArrayLvalueConversion(RHS.get()); + if (RHS.isInvalid()) + return QualType(); + } else { + LHS = DefaultLvalueConversion(LHS.get()); + if (LHS.isInvalid()) + return QualType(); + RHS = DefaultLvalueConversion(RHS.get()); + if (RHS.isInvalid()) + return QualType(); } + checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true); + + // Handle vector comparisons separately. + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) + return CheckVectorCompareOperands(LHS, RHS, Loc, Opc); + + diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc); + diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc); + + QualType LHSType = LHS.get()->getType(); + QualType RHSType = RHS.get()->getType(); + if ((LHSType->isArithmeticType() || LHSType->isEnumeralType()) && + (RHSType->isArithmeticType() || RHSType->isEnumeralType())) + return checkArithmeticOrEnumeralCompare(*this, LHS, RHS, Loc, Opc); + const Expr::NullPointerConstantKind LHSNullKind = LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); const Expr::NullPointerConstantKind RHSNullKind = @@ -9725,6 +10079,44 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, bool LHSIsNull = LHSNullKind != Expr::NPCK_NotNull; bool RHSIsNull = RHSNullKind != Expr::NPCK_NotNull; + auto computeResultTy = [&]() { + if (Opc != BO_Cmp) + return Context.getLogicalOperationType(); + assert(getLangOpts().CPlusPlus); + assert(Context.hasSameType(LHS.get()->getType(), RHS.get()->getType())); + + QualType CompositeTy = LHS.get()->getType(); + assert(!CompositeTy->isReferenceType()); + + auto buildResultTy = [&](ComparisonCategoryType Kind) { + return CheckComparisonCategoryType(Kind, Loc); + }; + + // C++2a [expr.spaceship]p7: If the composite pointer type is a function + // pointer type, a pointer-to-member type, or std::nullptr_t, the + // result is of type std::strong_equality + if (CompositeTy->isFunctionPointerType() || + CompositeTy->isMemberPointerType() || CompositeTy->isNullPtrType()) + // FIXME: consider making the function pointer case produce + // strong_ordering not strong_equality, per P0946R0-Jax18 discussion + // and direction polls + return buildResultTy(ComparisonCategoryType::StrongEquality); + + // C++2a [expr.spaceship]p8: If the composite pointer type is an object + // pointer type, p <=> q is of type std::strong_ordering. + if (CompositeTy->isPointerType()) { + // P0946R0: Comparisons between a null pointer constant and an object + // pointer result in std::strong_equality + if (LHSIsNull != RHSIsNull) + return buildResultTy(ComparisonCategoryType::StrongEquality); + return buildResultTy(ComparisonCategoryType::StrongOrdering); + } + // C++2a [expr.spaceship]p9: Otherwise, the program is ill-formed. + // TODO: Extend support for operator<=> to ObjC types. + return InvalidOperands(Loc, LHS, RHS); + }; + + if (!IsRelational && LHSIsNull != RHSIsNull) { bool IsEquality = Opc == BO_EQ; if (RHSIsNull) @@ -9752,29 +10144,30 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, // conformance with the C++ standard. diagnoseFunctionPointerToVoidComparison( *this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext()); - + if (isSFINAEContext()) return QualType(); - + RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast); - return ResultTy; + return computeResultTy(); } // C++ [expr.eq]p2: // If at least one operand is a pointer [...] bring them to their // composite pointer type. + // C++ [expr.spaceship]p6 + // If at least one of the operands is of pointer type, [...] bring them + // to their composite pointer type. // C++ [expr.rel]p2: // If both operands are pointers, [...] bring them to their composite // pointer type. if ((int)LHSType->isPointerType() + (int)RHSType->isPointerType() >= (IsRelational ? 2 : 1) && - (!LangOpts.ObjCAutoRefCount || - !(LHSType->isObjCObjectPointerType() || - RHSType->isObjCObjectPointerType()))) { + (!LangOpts.ObjCAutoRefCount || !(LHSType->isObjCObjectPointerType() || + RHSType->isObjCObjectPointerType()))) { if (convertPointersToCompositeType(*this, Loc, LHS, RHS)) return QualType(); - else - return ResultTy; + return computeResultTy(); } } else if (LHSType->isPointerType() && RHSType->isPointerType()) { // C99 6.5.8p2 @@ -9825,7 +10218,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, else RHS = ImpCastExprToType(RHS.get(), LHSType, Kind); } - return ResultTy; + return computeResultTy(); } if (getLangOpts().CPlusPlus) { @@ -9835,11 +10228,11 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, if (!IsRelational && LHSIsNull && RHSIsNull) { if (LHSType->isNullPtrType()) { RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer); - return ResultTy; + return computeResultTy(); } if (RHSType->isNullPtrType()) { LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer); - return ResultTy; + return computeResultTy(); } } @@ -9848,12 +10241,12 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, if (!IsRelational && RHSType->isNullPtrType() && (LHSType->isObjCObjectPointerType() || LHSType->isBlockPointerType())) { RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer); - return ResultTy; + return computeResultTy(); } if (!IsRelational && LHSType->isNullPtrType() && (RHSType->isObjCObjectPointerType() || RHSType->isBlockPointerType())) { LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer); - return ResultTy; + return computeResultTy(); } if (IsRelational && @@ -9876,7 +10269,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer); else LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer); - return ResultTy; + return computeResultTy(); } } } @@ -9889,15 +10282,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, if (convertPointersToCompositeType(*this, Loc, LHS, RHS)) return QualType(); else - return ResultTy; + return computeResultTy(); } - - // Handle scoped enumeration types specifically, since they don't promote - // to integers. - if (LHS.get()->getType()->isEnumeralType() && - Context.hasSameUnqualifiedType(LHS.get()->getType(), - RHS.get()->getType())) - return ResultTy; } // Handle block pointer types. @@ -9913,7 +10299,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, << RHS.get()->getSourceRange(); } RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast); - return ResultTy; + return computeResultTy(); } // Allow block pointers to be compared with null pointer constants. @@ -9937,7 +10323,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, RHS = ImpCastExprToType(RHS.get(), LHSType, LHSType->isPointerType() ? CK_BitCast : CK_AnyPointerToBlockPointerCast); - return ResultTy; + return computeResultTy(); } if (LHSType->isObjCObjectPointerType() || @@ -9970,7 +10356,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, RHS = ImpCastExprToType(E, LHSType, LPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } - return ResultTy; + return computeResultTy(); } if (LHSType->isObjCObjectPointerType() && RHSType->isObjCObjectPointerType()) { @@ -9984,7 +10370,20 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, LHS = ImpCastExprToType(LHS.get(), RHSType, CK_BitCast); else RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast); - return ResultTy; + return computeResultTy(); + } + + if (!IsRelational && LHSType->isBlockPointerType() && + RHSType->isBlockCompatibleObjCPointerType(Context)) { + LHS = ImpCastExprToType(LHS.get(), RHSType, + CK_BlockPointerToObjCPointerCast); + return computeResultTy(); + } else if (!IsRelational && + LHSType->isBlockCompatibleObjCPointerType(Context) && + RHSType->isBlockPointerType()) { + RHS = ImpCastExprToType(RHS.get(), LHSType, + CK_BlockPointerToObjCPointerCast); + return computeResultTy(); } } if ((LHSType->isAnyPointerType() && RHSType->isIntegerType()) || @@ -10017,37 +10416,37 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, if (isError) return QualType(); } - + if (LHSType->isIntegerType()) LHS = ImpCastExprToType(LHS.get(), RHSType, LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); else RHS = ImpCastExprToType(RHS.get(), LHSType, RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); - return ResultTy; + return computeResultTy(); } - + // Handle block pointers. if (!IsRelational && RHSIsNull && LHSType->isBlockPointerType() && RHSType->isIntegerType()) { RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer); - return ResultTy; + return computeResultTy(); } if (!IsRelational && LHSIsNull && LHSType->isIntegerType() && RHSType->isBlockPointerType()) { LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer); - return ResultTy; + return computeResultTy(); } if (getLangOpts().OpenCLVersion >= 200) { if (LHSIsNull && RHSType->isQueueT()) { LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer); - return ResultTy; + return computeResultTy(); } if (LHSType->isQueueT() && RHSIsNull) { RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer); - return ResultTy; + return computeResultTy(); } } @@ -10101,7 +10500,7 @@ QualType Sema::GetSignedVectorType(QualType V) { /// types. QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - bool IsRelational) { + BinaryOperatorKind Opc) { // Check to make sure we're operating on vectors of the same type and width, // Allowing one side to be a scalar of element type. QualType vType = CheckVectorOperands(LHS, RHS, Loc, /*isCompAssign*/false, @@ -10121,22 +10520,12 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. - if (!LHSType->hasFloatingRepresentation() && !inTemplateInstantiation()) { - if (DeclRefExpr* DRL - = dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParenImpCasts())) - if (DeclRefExpr* DRR - = dyn_cast<DeclRefExpr>(RHS.get()->IgnoreParenImpCasts())) - if (DRL->getDecl() == DRR->getDecl()) - DiagRuntimeBehavior(Loc, nullptr, - PDiag(diag::warn_comparison_always) - << 0 // self- - << 2 // "a constant" - ); - } + diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc); // Check for comparisons of floating point operands using != and ==. - if (!IsRelational && LHSType->hasFloatingRepresentation()) { - assert (RHS.get()->getType()->hasFloatingRepresentation()); + if (BinaryOperator::isEqualityOp(Opc) && + LHSType->hasFloatingRepresentation()) { + assert(RHS.get()->getType()->hasFloatingRepresentation()); CheckFloatComparison(Loc, LHS.get(), RHS.get()); } @@ -10207,7 +10596,7 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS, // Check vector operands differently. if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) return CheckVectorLogicalOperands(LHS, RHS, Loc); - + // Diagnose cases where the user write a logical and/or but probably meant a // bitwise one. We do this when the LHS is a non-bool integer and the RHS // is a constant. @@ -10418,8 +10807,16 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E, // Static fields do not inherit constness from parents. break; } - break; - } // End MemberExpr + break; // End MemberExpr + } else if (const ArraySubscriptExpr *ASE = + dyn_cast<ArraySubscriptExpr>(E)) { + E = ASE->getBase()->IgnoreParenImpCasts(); + continue; + } else if (const ExtVectorElementExpr *EVE = + dyn_cast<ExtVectorElementExpr>(E)) { + E = EVE->getBase()->IgnoreParenImpCasts(); + continue; + } break; } @@ -10660,12 +11057,34 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { static void CheckIdentityFieldAssignment(Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc, Sema &Sema) { + if (Sema.inTemplateInstantiation()) + return; + if (Sema.isUnevaluatedContext()) + return; + if (Loc.isInvalid() || Loc.isMacroID()) + return; + if (LHSExpr->getExprLoc().isMacroID() || RHSExpr->getExprLoc().isMacroID()) + return; + // C / C++ fields MemberExpr *ML = dyn_cast<MemberExpr>(LHSExpr); MemberExpr *MR = dyn_cast<MemberExpr>(RHSExpr); - if (ML && MR && ML->getMemberDecl() == MR->getMemberDecl()) { - if (isa<CXXThisExpr>(ML->getBase()) && isa<CXXThisExpr>(MR->getBase())) - Sema.Diag(Loc, diag::warn_identity_field_assign) << 0; + if (ML && MR) { + if (!(isa<CXXThisExpr>(ML->getBase()) && isa<CXXThisExpr>(MR->getBase()))) + return; + const ValueDecl *LHSDecl = + cast<ValueDecl>(ML->getMemberDecl()->getCanonicalDecl()); + const ValueDecl *RHSDecl = + cast<ValueDecl>(MR->getMemberDecl()->getCanonicalDecl()); + if (LHSDecl != RHSDecl) + return; + if (LHSDecl->getType().isVolatileQualified()) + return; + if (const ReferenceType *RefTy = LHSDecl->getType()->getAs<ReferenceType>()) + if (RefTy->getPointeeType().isVolatileQualified()) + return; + + Sema.Diag(Loc, diag::warn_identity_field_assign) << 0; } // Objective-C instance variables @@ -10701,7 +11120,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, << LHSType.getUnqualifiedType(); return QualType(); } - + AssignConvertType ConvTy; if (CompoundType.isNull()) { Expr *RHSCheck = RHS.get(); @@ -10938,7 +11357,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, // Otherwise, we just need a complete type. if (checkArithmeticIncompletePointerType(S, OpLoc, Op) || checkArithmeticOnObjCPointer(S, OpLoc, Op)) - return QualType(); + return QualType(); } else if (ResType->isAnyComplexType()) { // C99 does not support ++/-- on complex types, we allow as an extension. S.Diag(OpLoc, diag::ext_integer_increment_complex) @@ -10978,7 +11397,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, return ResType.getUnqualifiedType(); } } - + /// getPrimaryDecl - Helper function for CheckAddressOfOperand(). /// This routine allows us to typecheck complex/recursive expressions @@ -11046,7 +11465,7 @@ namespace { AO_No_Error = 4 }; } -/// \brief Diagnose invalid operand for address of operations. +/// Diagnose invalid operand for address of operations. /// /// \param Type The type of operand which cannot have its address taken. static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc, @@ -11138,7 +11557,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { Expr::LValueClassification lval = op->ClassifyLValue(Context); unsigned AddressOfError = AO_No_Error; - if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) { + if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) { bool sfinae = (bool)isSFINAEContext(); Diag(OpLoc, isSFINAEContext() ? diag::err_typecheck_addrof_temporary : diag::ext_typecheck_addrof_temporary) @@ -11353,7 +11772,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, // ...except that certain expressions are never l-values in C. if (!S.getLangOpts().CPlusPlus && Result.isCForbiddenLValueType()) VK = VK_RValue; - + return Result; } @@ -11419,12 +11838,13 @@ static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode( } /// DiagnoseSelfAssignment - Emits a warning if a value is assigned to itself. -/// This warning is only emitted for builtin assignment operations. It is also -/// suppressed in the event of macro expansions. +/// This warning suppressed in the event of macro expansions. static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr, - SourceLocation OpLoc) { + SourceLocation OpLoc, bool IsBuiltin) { if (S.inTemplateInstantiation()) return; + if (S.isUnevaluatedContext()) + return; if (OpLoc.isInvalid() || OpLoc.isMacroID()) return; LHSExpr = LHSExpr->IgnoreParenImpCasts(); @@ -11447,9 +11867,10 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr, if (RefTy->getPointeeType().isVolatileQualified()) return; - S.Diag(OpLoc, diag::warn_self_assignment) - << LHSDeclRef->getType() - << LHSExpr->getSourceRange() << RHSExpr->getSourceRange(); + S.Diag(OpLoc, IsBuiltin ? diag::warn_self_assignment_builtin + : diag::warn_self_assignment_overloaded) + << LHSDeclRef->getType() << LHSExpr->getSourceRange() + << RHSExpr->getSourceRange(); } /// Check if a bitwise-& is performed on an Objective-C pointer. This @@ -11489,7 +11910,7 @@ static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R, if (SelArg0.startswith("performSelector")) Diag = diag::warn_objc_pointer_masking_performSelector; } - + S.Diag(OpLoc, Diag) << ObjCPointerExpr->getSourceRange(); } @@ -11584,8 +12005,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, // C++11 5.17p9: // The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning // of x = {} is x = T(). - InitializationKind Kind = - InitializationKind::CreateDirectList(RHSExpr->getLocStart()); + InitializationKind Kind = InitializationKind::CreateDirectList( + RHSExpr->getLocStart(), RHSExpr->getLocStart(), RHSExpr->getLocEnd()); InitializedEntity Entity = InitializedEntity::InitializeTemporary(LHSExpr->getType()); InitializationSequence InitSeq(*this, Entity, Kind, RHSExpr); @@ -11642,7 +12063,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, OK = LHS.get()->getObjectKind(); } if (!ResultTy.isNull()) { - DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc); + DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true); DiagnoseSelfMove(LHS.get(), RHS.get(), OpLoc); } RecordModifiableNonNullParam(*this, LHS.get()); @@ -11678,19 +12099,17 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, case BO_GE: case BO_GT: ConvertHalfVec = true; - ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true); + ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc); break; case BO_EQ: case BO_NE: ConvertHalfVec = true; - ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, false); + ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc); break; case BO_Cmp: - // FIXME: Implement proper semantic checking of '<=>'. ConvertHalfVec = true; - ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true); - if (!ResultTy.isNull()) - ResultTy = Context.VoidTy; + ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc); + assert(ResultTy.isNull() || ResultTy->getAsCXXRecordDecl()); break; case BO_And: checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc); @@ -11740,7 +12159,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, break; case BO_AndAssign: case BO_OrAssign: // fallthrough - DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc); + DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true); LLVM_FALLTHROUGH; case BO_XorAssign: CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc); @@ -11790,7 +12209,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, else if (const ObjCIvarRefExpr *OIRE = dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts())) DiagnoseDirectIsaAccess(*this, OIRE, OpLoc, RHS.get()); - + // Opc is not a compound assignment if CompResultTy is null. if (CompResultTy.isNull()) { if (ConvertHalfVec) @@ -11858,7 +12277,7 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, ParensRange); } -/// \brief It accepts a '&&' expr that is inside a '||' one. +/// It accepts a '&&' expr that is inside a '||' one. /// Emit a diagnostic together with a fixit hint that wraps the '&&' expression /// in parentheses. static void @@ -11873,7 +12292,7 @@ EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc, Bop->getSourceRange()); } -/// \brief Returns true if the given expression can be evaluated as a constant +/// Returns true if the given expression can be evaluated as a constant /// 'true'. static bool EvaluatesAsTrue(Sema &S, Expr *E) { bool Res; @@ -11881,7 +12300,7 @@ static bool EvaluatesAsTrue(Sema &S, Expr *E) { E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res; } -/// \brief Returns true if the given expression can be evaluated as a constant +/// Returns true if the given expression can be evaluated as a constant /// 'false'. static bool EvaluatesAsFalse(Sema &S, Expr *E) { bool Res; @@ -11889,7 +12308,7 @@ static bool EvaluatesAsFalse(Sema &S, Expr *E) { E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res; } -/// \brief Look for '&&' in the left hand of a '||' expr. +/// Look for '&&' in the left hand of a '||' expr. static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc, Expr *LHSExpr, Expr *RHSExpr) { if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(LHSExpr)) { @@ -11911,7 +12330,7 @@ static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc, } } -/// \brief Look for '&&' in the right hand of a '||' expr. +/// Look for '&&' in the right hand of a '||' expr. static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc, Expr *LHSExpr, Expr *RHSExpr) { if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(RHSExpr)) { @@ -11926,7 +12345,7 @@ static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc, } } -/// \brief Look for bitwise op in the left or right hand of a bitwise op with +/// Look for bitwise op in the left or right hand of a bitwise op with /// lower precedence and emit a diagnostic together with a fixit hint that wraps /// the '&' expression in parentheses. static void DiagnoseBitwiseOpInBitwiseOp(Sema &S, BinaryOperatorKind Opc, @@ -12039,6 +12458,21 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHS, Expr *RHS) { + switch (Opc) { + case BO_Assign: + case BO_DivAssign: + case BO_RemAssign: + case BO_SubAssign: + case BO_AndAssign: + case BO_OrAssign: + case BO_XorAssign: + DiagnoseSelfAssignment(S, LHS, RHS, OpLoc, false); + CheckIdentityFieldAssignment(LHS, RHS, OpLoc, S); + break; + default: + break; + } + // Find all of the overloaded operators visible from this // point. We perform both an operator-name lookup from the local // scope and an argument-dependent lookup based on the types of @@ -12115,7 +12549,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, return ExprError(); } } - + ExprResult LHS = CheckPlaceholderExpr(LHSExpr); if (LHS.isInvalid()) return ExprError(); LHSExpr = LHS.get(); @@ -12161,6 +12595,16 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr); } +static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) { + if (T.isNull() || T->isDependentType()) + return false; + + if (!T->isPromotableIntegerType()) + return true; + + return Ctx.getIntWidth(T) >= Ctx.getIntWidth(Ctx.IntTy); +} + ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr) { @@ -12168,6 +12612,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; QualType resultType; + bool CanOverflow = false; + bool ConvertHalfVec = false; if (getLangOpts().OpenCL) { QualType Ty = InputExpr->getType(); @@ -12193,6 +12639,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, Opc == UO_PostInc, Opc == UO_PreInc || Opc == UO_PreDec); + CanOverflow = isOverflowingIntegerType(Context, resultType); break; case UO_AddrOf: resultType = CheckAddressOfOperand(Input, OpLoc); @@ -12206,6 +12653,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, } case UO_Plus: case UO_Minus: + CanOverflow = Opc == UO_Minus && + isOverflowingIntegerType(Context, Input.get()->getType()); Input = UsualUnaryConversions(Input.get()); if (Input.isInvalid()) return ExprError(); // Unary plus and minus require promoting an operand of half vector to a @@ -12242,6 +12691,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, if (Input.isInvalid()) return ExprError(); resultType = Input.get()->getType(); + if (resultType->isDependentType()) break; // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. @@ -12312,7 +12762,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); } - + // LNot always has type int. C99 6.5.3.3p5. // In C++, it's bool. C++ 5.3.1p8 resultType = Context.getLogicalOperationType(); @@ -12338,7 +12788,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, OK = Input.get()->getObjectKind(); break; case UO_Coawait: - // It's unnessesary to represent the pass-through operator co_await in the + // It's unnecessary to represent the pass-through operator co_await in the // AST; just return the input expression instead. assert(!Input.get()->getType()->isDependentType() && "the co_await expression must be non-dependant before " @@ -12356,37 +12806,37 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, CheckArrayAccess(Input.get()); auto *UO = new (Context) - UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc); + UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc, CanOverflow); // Convert the result back to a half vector. if (ConvertHalfVec) return convertVector(UO, Context.HalfTy, *this); return UO; } -/// \brief Determine whether the given expression is a qualified member +/// Determine whether the given expression is a qualified member /// access expression, of a form that could be turned into a pointer to member /// with the address-of operator. -static bool isQualifiedMemberAccess(Expr *E) { +bool Sema::isQualifiedMemberAccess(Expr *E) { if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { if (!DRE->getQualifier()) return false; - + ValueDecl *VD = DRE->getDecl(); if (!VD->isCXXClassMember()) return false; - + if (isa<FieldDecl>(VD) || isa<IndirectFieldDecl>(VD)) return true; if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(VD)) return Method->isInstance(); - + return false; } - + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { if (!ULE->getQualifier()) return false; - + for (NamedDecl *D : ULE->decls()) { if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { if (Method->isInstance()) @@ -12396,10 +12846,10 @@ static bool isQualifiedMemberAccess(Expr *E) { break; } } - + return false; } - + return false; } @@ -12549,11 +12999,8 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, LastExpr = rebuiltLastStmt; } else { LastExpr = PerformCopyInitialization( - InitializedEntity::InitializeResult(LPLoc, - Ty, - false), - SourceLocation(), - LastExpr); + InitializedEntity::InitializeStmtExprResult(LPLoc, Ty), + SourceLocation(), LastExpr); } if (LastExpr.isInvalid()) @@ -12584,17 +13031,17 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, QualType ArgTy = TInfo->getType(); bool Dependent = ArgTy->isDependentType(); SourceRange TypeRange = TInfo->getTypeLoc().getLocalSourceRange(); - + // We must have at least one component that refers to the type, and the first // one is known to be a field designator. Verify that the ArgTy represents // a struct/union/class. if (!Dependent && !ArgTy->isRecordType()) - return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type) + return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type) << ArgTy << TypeRange); - + // Type must be complete per C99 7.17p3 because a declaring a variable // with an incomplete type would be ill-formed. - if (!Dependent + if (!Dependent && RequireCompleteType(BuiltinLoc, ArgTy, diag::err_offsetof_incomplete_type, TypeRange)) return ExprError(); @@ -12614,7 +13061,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, CurrentType = AT->getElementType(); } else CurrentType = Context.DependentTy; - + ExprResult IdxRval = DefaultLvalueConversion(static_cast<Expr*>(OC.U.E)); if (IdxRval.isInvalid()) return ExprError(); @@ -12633,7 +13080,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, Exprs.push_back(Idx); continue; } - + // Offset of a field. if (CurrentType->isDependentType()) { // We have the offset of a field, but we can't look into the dependent @@ -12642,19 +13089,19 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, CurrentType = Context.DependentTy; continue; } - + // We need to have a complete type to look into. if (RequireCompleteType(OC.LocStart, CurrentType, diag::err_offsetof_incomplete_type)) return ExprError(); - + // Look for the designated field. const RecordType *RC = CurrentType->getAs<RecordType>(); - if (!RC) + if (!RC) return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type) << CurrentType); RecordDecl *RD = RC->getDecl(); - + // C++ [lib.support.types]p5: // The macro offsetof accepts a restricted set of type arguments in this // International Standard. type shall be a POD structure or a POD union @@ -12675,7 +13122,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, << CurrentType)) DidWarnAboutNonPOD = true; } - + // Look for the field. LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName); LookupQualifiedName(R, RD); @@ -12688,9 +13135,9 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, if (!MemberDecl) return ExprError(Diag(BuiltinLoc, diag::err_no_member) - << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, + << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd)); - + // C99 7.17p3: // (If the specified member is a bit-field, the behavior is undefined.) // @@ -12733,9 +13180,9 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, } else Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd)); - CurrentType = MemberDecl->getType().getNonReferenceType(); + CurrentType = MemberDecl->getType().getNonReferenceType(); } - + return OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc, TInfo, Comps, Exprs, RParenLoc); } @@ -12746,7 +13193,7 @@ ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, ParsedType ParsedArgTy, ArrayRef<OffsetOfComponent> Components, SourceLocation RParenLoc) { - + TypeSourceInfo *ArgTInfo; QualType ArgTy = GetTypeFromParser(ParsedArgTy, &ArgTInfo); if (ArgTy.isNull()) @@ -12784,7 +13231,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, CondExpr = CondICE.get(); CondIsTrue = condEval.getZExtValue(); - // If the condition is > zero, then the AST type is the same as the LSHExpr. + // If the condition is > zero, then the AST type is the same as the LHSExpr. Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr; resType = ActiveExpr->getType(); @@ -12851,7 +13298,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, T = Context.getFunctionType(Context.DependentTy, None, EPI); Sig = Context.getTrivialTypeSourceInfo(T); } - + // GetTypeForDeclarator always produces a function type for a block // literal signature. Furthermore, it is always a FunctionProtoType // unless the function was written with a typedef. @@ -12929,7 +13376,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, CheckParmsForFunctionDef(CurBlock->TheDecl->parameters(), /*CheckParameterNames=*/false); } - + // Finally we can process decl attributes. ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); @@ -12990,7 +13437,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, // Set the captured variables on the block. // FIXME: Share capture structure between BlockDecl and CapturingScopeInfo! SmallVector<BlockDecl::Capture, 4> Captures; - for (CapturingScopeInfo::Capture &Cap : BSI->Captures) { + for (Capture &Cap : BSI->Captures) { if (Cap.isThisCapture()) continue; BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(), @@ -13005,7 +13452,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, FunctionType::ExtInfo Ext = FTy->getExtInfo(); if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true); - + // Turn protoless block types into nullary block types. if (isa<FunctionNoProtoType>(FTy)) { FunctionProtoType::ExtProtoInfo EPI; @@ -13053,7 +13500,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (getLangOpts().CPlusPlus && RetTy->isRecordType() && !BSI->TheDecl->isDependentContext()) computeNRVO(Body, BSI); - + BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result); @@ -13070,7 +13517,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, for (const auto &CI : Result->getBlockDecl()->captures()) { const VarDecl *var = CI.getVariable(); if (var->getType().isDestructedType() != QualType::DK_none) { - getCurFunction()->setHasBranchProtectedScope(); + setFunctionHasBranchProtectedScope(); break; } } @@ -13227,7 +13674,7 @@ bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp, if (!ID || !ID->getIdentifier()->isStr("NSString")) return false; } - + // Ignore any parens, implicit casts (should only be // array-to-pointer decays), and not-so-opaque values. The last is // important for making this trigger for property assignments. @@ -13336,7 +13783,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, DiagKind = diag::err_typecheck_incompatible_address_space; break; - } else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) { DiagKind = diag::err_typecheck_incompatible_ownership; break; @@ -13460,8 +13906,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, if (DiagKind == diag::warn_incompatible_qualified_id && PDecl && IFace && !IFace->hasDefinition()) Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id) - << IFace->getName() << PDecl->getName(); - + << IFace << PDecl; + if (SecondType == Context.OverloadTy) NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression, FirstType, /*TakingAddress=*/true); @@ -13471,7 +13917,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, if (Action == AA_Returning && ConvTy == IncompatiblePointer) EmitRelatedResultTypeNoteForReturn(DstType); - + if (Complained) *Complained = true; return isInvalid; @@ -13485,7 +13931,7 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus << SR; } } Diagnoser; - + return VerifyIntegerConstantExpression(E, Result, Diagnoser); } @@ -13495,16 +13941,16 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, bool AllowFold) { class IDDiagnoser : public VerifyICEDiagnoser { unsigned DiagID; - + public: IDDiagnoser(unsigned DiagID) : VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) { } - + void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override { S.Diag(Loc, DiagID) << SR; } } Diagnoser(DiagID); - + return VerifyIntegerConstantExpression(E, Result, Diagnoser, AllowFold); } @@ -13701,22 +14147,22 @@ ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) { } void -Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl, - bool IsDecltype) { +Sema::PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl, + ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, - LambdaContextDecl, IsDecltype); + LambdaContextDecl, ExprContext); Cleanup.reset(); if (!MaybeODRUseExprs.empty()) std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); } void -Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - ReuseLambdaContextDecl_t, - bool IsDecltype) { +Sema::PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, + ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl; - PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype); + PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext); } void Sema::PopExpressionEvaluationContext() { @@ -13724,30 +14170,30 @@ void Sema::PopExpressionEvaluationContext() { unsigned NumTypos = Rec.NumTypos; if (!Rec.Lambdas.empty()) { - if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) { + using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind; + if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument || Rec.isUnevaluated() || + (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17)) { unsigned D; if (Rec.isUnevaluated()) { // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand // (Clause 5). D = diag::err_lambda_unevaluated_operand; - } else { + } else if (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17) { // C++1y [expr.const]p2: // A conditional-expression e is a core constant expression unless the // evaluation of e, following the rules of the abstract machine, would // evaluate [...] a lambda-expression. D = diag::err_lambda_in_constant_expression; - } + } else if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument) { + // C++17 [expr.prim.lamda]p2: + // A lambda-expression shall not appear [...] in a template-argument. + D = diag::err_lambda_in_invalid_context; + } else + llvm_unreachable("Couldn't infer lambda error message."); - // C++1z allows lambda expressions as core constant expressions. - // FIXME: In C++1z, reinstate the restrictions on lambda expressions (CWG - // 1607) from appearing within template-arguments and array-bounds that - // are part of function-signatures. Be mindful that P0315 (Lambdas in - // unevaluated contexts) might lift some of these restrictions in a - // future version. - if (!Rec.isConstantEvaluated() || !getLangOpts().CPlusPlus17) - for (const auto *L : Rec.Lambdas) - Diag(L->getLocStart(), D); + for (const auto *L : Rec.Lambdas) + Diag(L->getLocStart(), D); } else { // Mark the capture expressions odr-used. This was deferred // during lambda expression creation. @@ -13806,13 +14252,13 @@ static bool isEvaluatableContext(Sema &SemaRef) { switch (SemaRef.ExprEvalContexts.back().Context) { case Sema::ExpressionEvaluationContext::Unevaluated: case Sema::ExpressionEvaluationContext::UnevaluatedAbstract: - case Sema::ExpressionEvaluationContext::DiscardedStatement: // Expressions in this context are never evaluated. return false; case Sema::ExpressionEvaluationContext::UnevaluatedList: case Sema::ExpressionEvaluationContext::ConstantEvaluated: case Sema::ExpressionEvaluationContext::PotentiallyEvaluated: + case Sema::ExpressionEvaluationContext::DiscardedStatement: // Expressions in this context could be evaluated. return true; @@ -13856,7 +14302,7 @@ static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) { (Func->isImplicitlyInstantiable() || (MD && !MD->isUserProvided())); } -/// \brief Mark a function referenced, and check whether it is odr-used +/// Mark a function referenced, and check whether it is odr-used /// (C++ [basic.def.odr]p2, C99 6.9p3) void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse) { @@ -14070,26 +14516,26 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, // capture. } - -static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDecl *Var, + +static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDecl *Var, bool &SubCapturesAreNested, - QualType &CaptureType, + QualType &CaptureType, QualType &DeclRefType) { // Check whether we've already captured it. if (CSI->CaptureMap.count(Var)) { // If we found a capture, any subcaptures are nested. SubCapturesAreNested = true; - + // Retrieve the capture type for this variable. CaptureType = CSI->getCapture(Var).getCaptureType(); - + // Compute the type of an expression that refers to this variable. DeclRefType = CaptureType.getNonReferenceType(); // Similarly to mutable captures in lambda, all the OpenMP captures by copy // are mutable in the sense that user can change their value - they are // private instances of the captured declarations. - const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var); + const Capture &Cap = CSI->getCapture(Var); if (Cap.isCopyCapture() && !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable) && !(isa<CapturedRegionScopeInfo>(CSI) && @@ -14102,8 +14548,8 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDec // Only block literals, captured statements, and lambda expressions can // capture; other scopes don't work. -static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var, - SourceLocation Loc, +static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var, + SourceLocation Loc, const bool Diagnose, Sema &S) { if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC)) return getLambdaAwareParentOfDeclContext(DC); @@ -14114,11 +14560,11 @@ static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl * return nullptr; } -// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture +// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture // certain types of variables (unnamed, variably modified types etc.) // so check for eligibility. -static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, - SourceLocation Loc, +static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, + SourceLocation Loc, const bool Diagnose, Sema &S) { bool IsBlock = isa<BlockScopeInfo>(CSI); @@ -14140,7 +14586,7 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, if (Var->getType()->isVariablyModifiedType() && IsBlock) { if (Diagnose) { S.Diag(Loc, diag::err_ref_vm_type); - S.Diag(Var->getLocation(), diag::note_previous_decl) + S.Diag(Var->getLocation(), diag::note_previous_decl) << Var->getDeclName(); } return false; @@ -14185,21 +14631,21 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, } // Returns true if the capture by block was successful. -static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, - SourceLocation Loc, - const bool BuildAndDiagnose, +static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, + SourceLocation Loc, + const bool BuildAndDiagnose, QualType &CaptureType, - QualType &DeclRefType, + QualType &DeclRefType, const bool Nested, Sema &S) { Expr *CopyExpr = nullptr; bool ByRef = false; - + // Blocks are not allowed to capture arrays. if (CaptureType->isArrayType()) { if (BuildAndDiagnose) { S.Diag(Loc, diag::err_ref_array_type); - S.Diag(Var->getLocation(), diag::note_previous_decl) + S.Diag(Var->getLocation(), diag::note_previous_decl) << Var->getDeclName(); } return false; @@ -14242,30 +14688,6 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, if (BuildAndDiagnose) { SourceLocation VarLoc = Var->getLocation(); S.Diag(Loc, diag::warn_block_capture_autoreleasing); - { - auto AddAutoreleaseNote = - S.Diag(VarLoc, diag::note_declare_parameter_autoreleasing); - // Provide a fix-it for the '__autoreleasing' keyword at the - // appropriate location in the variable's type. - if (const auto *TSI = Var->getTypeSourceInfo()) { - PointerTypeLoc PTL = - TSI->getTypeLoc().getAsAdjusted<PointerTypeLoc>(); - if (PTL) { - SourceLocation Loc = PTL.getPointeeLoc().getEndLoc(); - Loc = Lexer::getLocForEndOfToken(Loc, 0, S.getSourceManager(), - S.getLangOpts()); - if (Loc.isValid()) { - StringRef CharAtLoc = Lexer::getSourceText( - CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(1)), - S.getSourceManager(), S.getLangOpts()); - AddAutoreleaseNote << FixItHint::CreateInsertion( - Loc, CharAtLoc.empty() || !isWhitespace(CharAtLoc[0]) - ? " __autoreleasing " - : " __autoreleasing"); - } - } - } - } S.Diag(VarLoc, diag::note_declare_parameter_strong); } } @@ -14273,7 +14695,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>(); if (HasBlocksAttr || CaptureType->isReferenceType() || - (S.getLangOpts().OpenMP && S.IsOpenMPCapturedDecl(Var))) { + (S.getLangOpts().OpenMP && S.isOpenMPCapturedDecl(Var))) { // Block capture by reference does not change the capture or // declaration reference types. ByRef = true; @@ -14281,7 +14703,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, // Block capture by copy introduces 'const'. CaptureType = CaptureType.getNonReferenceType().withConst(); DeclRefType = CaptureType; - + if (S.getLangOpts().CPlusPlus && BuildAndDiagnose) { if (const RecordType *Record = DeclRefType->getAs<RecordType>()) { // The capture logic needs the destructor, so make sure we mark it. @@ -14301,15 +14723,15 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, // the stack requires a const copy constructor. This is not true // of the copy/move done to move a __block variable to the heap. Expr *DeclRef = new (S.Context) DeclRefExpr(Var, Nested, - DeclRefType.withConst(), + DeclRefType.withConst(), VK_LValue, Loc); - + ExprResult Result = S.PerformCopyInitialization( InitializedEntity::InitializeBlock(Var->getLocation(), CaptureType, false), Loc, DeclRef); - + // Build a full-expression copy expression if initialization // succeeded and used a non-trivial constructor. Recover from // errors by pretending that the copy isn't necessary. @@ -14325,7 +14747,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, // Actually capture the variable. if (BuildAndDiagnose) - BSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc, + BSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc, SourceLocation(), CaptureType, CopyExpr); return true; @@ -14333,27 +14755,27 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, } -/// \brief Capture the given variable in the captured region. +/// Capture the given variable in the captured region. static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, - VarDecl *Var, - SourceLocation Loc, - const bool BuildAndDiagnose, + VarDecl *Var, + SourceLocation Loc, + const bool BuildAndDiagnose, QualType &CaptureType, - QualType &DeclRefType, + QualType &DeclRefType, const bool RefersToCapturedVariable, Sema &S) { // By default, capture variables by reference. bool ByRef = true; // Using an LValue reference type is consistent with Lambdas (see below). if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) { - if (S.IsOpenMPCapturedDecl(Var)) { + if (S.isOpenMPCapturedDecl(Var)) { bool HasConst = DeclRefType.isConstQualified(); DeclRefType = DeclRefType.getUnqualifiedType(); // Don't lose diagnostics about assignments to const. if (HasConst) DeclRefType.addConst(); } - ByRef = S.IsOpenMPCapturedByRef(Var, RSI->OpenMPLevel); + ByRef = S.isOpenMPCapturedByRef(Var, RSI->OpenMPLevel); } if (ByRef) @@ -14377,7 +14799,7 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, RD->addDecl(Field); if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) S.setOpenMPCaptureKind(Field, Var, RSI->OpenMPLevel); - + CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable, DeclRefType, VK_LValue, Loc); Var->setReferenced(true); @@ -14388,14 +14810,14 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, if (BuildAndDiagnose) RSI->addCapture(Var, /*isBlock*/false, ByRef, RefersToCapturedVariable, Loc, SourceLocation(), CaptureType, CopyExpr); - - + + return true; } -/// \brief Create a field within the lambda class for the variable +/// Create a field within the lambda class for the variable /// being captured. -static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, +static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, QualType FieldType, QualType DeclRefType, SourceLocation Loc, bool RefersToCapturedVariable) { @@ -14411,15 +14833,15 @@ static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, Lambda->addDecl(Field); } -/// \brief Capture the given variable in the lambda. +/// Capture the given variable in the lambda. static bool captureInLambda(LambdaScopeInfo *LSI, - VarDecl *Var, - SourceLocation Loc, - const bool BuildAndDiagnose, + VarDecl *Var, + SourceLocation Loc, + const bool BuildAndDiagnose, QualType &CaptureType, - QualType &DeclRefType, + QualType &DeclRefType, const bool RefersToCapturedVariable, - const Sema::TryCaptureKind Kind, + const Sema::TryCaptureKind Kind, SourceLocation EllipsisLoc, const bool IsTopScope, Sema &S) { @@ -14431,7 +14853,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI, } else { ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref); } - + // Compute the type of the field that will capture this variable. if (ByRef) { // C++11 [expr.prim.lambda]p15: @@ -14443,7 +14865,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI, // // FIXME: It is not clear whether we want to build an lvalue reference // to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears - // to do the former, while EDG does the latter. Core issue 1249 will + // to do the former, while EDG does the latter. Core issue 1249 will // clarify, but for now we follow GCC because it's a more permissive and // easily defensible position. CaptureType = S.Context.getLValueReferenceType(DeclRefType); @@ -14491,26 +14913,26 @@ static bool captureInLambda(LambdaScopeInfo *LSI, if (BuildAndDiagnose) addAsFieldToClosureType(S, LSI, CaptureType, DeclRefType, Loc, RefersToCapturedVariable); - + // Compute the type of a reference to this captured variable. if (ByRef) DeclRefType = CaptureType.getNonReferenceType(); else { // C++ [expr.prim.lambda]p5: - // The closure type for a lambda-expression has a public inline - // function call operator [...]. This function call operator is - // declared const (9.3.1) if and only if the lambda-expression's + // The closure type for a lambda-expression has a public inline + // function call operator [...]. This function call operator is + // declared const (9.3.1) if and only if the lambda-expression's // parameter-declaration-clause is not followed by mutable. DeclRefType = CaptureType.getNonReferenceType(); if (!LSI->Mutable && !CaptureType->isReferenceType()) - DeclRefType.addConst(); + DeclRefType.addConst(); } - + // Add the capture. if (BuildAndDiagnose) - LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable, + LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable, Loc, EllipsisLoc, CaptureType, /*CopyExpr=*/nullptr); - + return true; } @@ -14523,10 +14945,10 @@ bool Sema::tryCaptureVariable( DeclContext *VarDC = Var->getDeclContext(); if (Var->isInitCapture()) VarDC = VarDC->getParent(); - + DeclContext *DC = CurContext; - const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt - ? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1; + const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt + ? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1; // We need to sync up the Declaration Context with the // FunctionScopeIndexToStopAt if (FunctionScopeIndexToStopAt) { @@ -14537,7 +14959,7 @@ bool Sema::tryCaptureVariable( } } - + // If the variable is declared in the current context, there is no need to // capture it. if (VarDC == DC) return true; @@ -14545,7 +14967,7 @@ bool Sema::tryCaptureVariable( // Capture global variables if it is required to use private copy of this // variable. bool IsGlobal = !Var->hasLocalStorage(); - if (IsGlobal && !(LangOpts.OpenMP && IsOpenMPCapturedDecl(Var))) + if (IsGlobal && !(LangOpts.OpenMP && isOpenMPCapturedDecl(Var))) return true; Var = Var->getCanonicalDecl(); @@ -14553,7 +14975,7 @@ bool Sema::tryCaptureVariable( // performing the "simple" checks that don't depend on type. We stop when // we've either hit the declared scope of the variable or find an existing // capture of that variable. We start from the innermost capturing-entity - // (the DC) and ensure that all intervening capturing-entities + // (the DC) and ensure that all intervening capturing-entities // (blocks/lambdas etc.) between the innermost capturer and the variable`s // declcontext can either capture the variable or have already captured // the variable. @@ -14565,8 +14987,8 @@ bool Sema::tryCaptureVariable( do { // Only block literals, captured statements, and lambda expressions can // capture; other scopes don't work. - DeclContext *ParentDC = getParentOfCapturingContextOrNull(DC, Var, - ExprLoc, + DeclContext *ParentDC = getParentOfCapturingContextOrNull(DC, Var, + ExprLoc, BuildAndDiagnose, *this); // We need to check for the parent *first* because, if we *have* @@ -14585,29 +15007,29 @@ bool Sema::tryCaptureVariable( // Check whether we've already captured it. - if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType, + if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType, DeclRefType)) { CSI->getCapture(Var).markUsed(BuildAndDiagnose); break; } - // If we are instantiating a generic lambda call operator body, + // If we are instantiating a generic lambda call operator body, // we do not want to capture new variables. What was captured // during either a lambdas transformation or initial parsing - // should be used. + // should be used. if (isGenericLambdaCallOperatorSpecialization(DC)) { if (BuildAndDiagnose) { - LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI); + LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI); if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) { Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName(); - Diag(Var->getLocation(), diag::note_previous_decl) + Diag(Var->getLocation(), diag::note_previous_decl) << Var->getDeclName(); - Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl); + Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl); } else diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC); } return true; } - // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture + // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture // certain types of variables (unnamed, variably modified types etc.) // so check for eligibility. if (!isVariableCapturable(CSI, Var, ExprLoc, BuildAndDiagnose, *this)) @@ -14648,11 +15070,11 @@ bool Sema::tryCaptureVariable( } } if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) { - // No capture-default, and this is not an explicit capture - // so cannot capture this variable. + // No capture-default, and this is not an explicit capture + // so cannot capture this variable. if (BuildAndDiagnose) { Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName(); - Diag(Var->getLocation(), diag::note_previous_decl) + Diag(Var->getLocation(), diag::note_previous_decl) << Var->getDeclName(); if (cast<LambdaScopeInfo>(CSI)->Lambda) Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getLocStart(), @@ -14661,12 +15083,12 @@ bool Sema::tryCaptureVariable( // capture a variable that an inner lambda explicitly captures, we // should have the inner lambda do the explicit capture - because // it makes for cleaner diagnostics later. This would purely be done - // so that the diagnostic does not misleadingly claim that a variable - // can not be captured by a lambda implicitly even though it is captured + // so that the diagnostic does not misleadingly claim that a variable + // can not be captured by a lambda implicitly even though it is captured // explicitly. Suggestion: - // - create const bool VariableCaptureWasInitiallyExplicit = Explicit + // - create const bool VariableCaptureWasInitiallyExplicit = Explicit // at the function head - // - cache the StartingDeclContext - this must be a lambda + // - cache the StartingDeclContext - this must be a lambda // - captureInLambda in the innermost lambda the variable. } return true; @@ -14678,31 +15100,31 @@ bool Sema::tryCaptureVariable( } while (!VarDC->Equals(DC)); // Walk back down the scope stack, (e.g. from outer lambda to inner lambda) - // computing the type of the capture at each step, checking type-specific - // requirements, and adding captures if requested. - // If the variable had already been captured previously, we start capturing - // at the lambda nested within that one. - for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1; I != N; + // computing the type of the capture at each step, checking type-specific + // requirements, and adding captures if requested. + // If the variable had already been captured previously, we start capturing + // at the lambda nested within that one. + for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1; I != N; ++I) { CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[I]); - + if (BlockScopeInfo *BSI = dyn_cast<BlockScopeInfo>(CSI)) { - if (!captureInBlock(BSI, Var, ExprLoc, - BuildAndDiagnose, CaptureType, + if (!captureInBlock(BSI, Var, ExprLoc, + BuildAndDiagnose, CaptureType, DeclRefType, Nested, *this)) return true; Nested = true; } else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { - if (!captureInCapturedRegion(RSI, Var, ExprLoc, - BuildAndDiagnose, CaptureType, + if (!captureInCapturedRegion(RSI, Var, ExprLoc, + BuildAndDiagnose, CaptureType, DeclRefType, Nested, *this)) return true; Nested = true; } else { LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI); - if (!captureInLambda(LSI, Var, ExprLoc, - BuildAndDiagnose, CaptureType, - DeclRefType, Nested, Kind, EllipsisLoc, + if (!captureInLambda(LSI, Var, ExprLoc, + BuildAndDiagnose, CaptureType, + DeclRefType, Nested, Kind, EllipsisLoc, /*IsTopScope*/I == N - 1, *this)) return true; Nested = true; @@ -14712,7 +15134,7 @@ bool Sema::tryCaptureVariable( } bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, - TryCaptureKind Kind, SourceLocation EllipsisLoc) { + TryCaptureKind Kind, SourceLocation EllipsisLoc) { QualType CaptureType; QualType DeclRefType; return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc, @@ -14731,10 +15153,10 @@ bool Sema::NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc) { QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { QualType CaptureType; QualType DeclRefType; - + // Determine whether we can capture this variable. if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(), - /*BuildAndDiagnose=*/false, CaptureType, + /*BuildAndDiagnose=*/false, CaptureType, DeclRefType, nullptr)) return QualType(); @@ -14743,49 +15165,49 @@ QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { -// If either the type of the variable or the initializer is dependent, +// If either the type of the variable or the initializer is dependent, // return false. Otherwise, determine whether the variable is a constant // expression. Use this if you need to know if a variable that might or // might not be dependent is truly a constant expression. -static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var, +static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var, ASTContext &Context) { - - if (Var->getType()->isDependentType()) + + if (Var->getType()->isDependentType()) return false; const VarDecl *DefVD = nullptr; Var->getAnyInitializer(DefVD); - if (!DefVD) + if (!DefVD) return false; EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt(); Expr *Init = cast<Expr>(Eval->Value); - if (Init->isValueDependent()) + if (Init->isValueDependent()) return false; - return IsVariableAConstantExpression(Var, Context); + return IsVariableAConstantExpression(Var, Context); } void Sema::UpdateMarkingForLValueToRValue(Expr *E) { - // Per C++11 [basic.def.odr], a variable is odr-used "unless it is + // Per C++11 [basic.def.odr], a variable is odr-used "unless it is // an object that satisfies the requirements for appearing in a // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) // is immediately applied." This function handles the lvalue-to-rvalue // conversion part. MaybeODRUseExprs.erase(E->IgnoreParens()); - + // If we are in a lambda, check if this DeclRefExpr or MemberExpr refers // to a variable that is a constant expression, and if so, identify it as - // a reference to a variable that does not involve an odr-use of that - // variable. + // a reference to a variable that does not involve an odr-use of that + // variable. if (LambdaScopeInfo *LSI = getCurLambda()) { Expr *SansParensExpr = E->IgnoreParens(); VarDecl *Var = nullptr; - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr)) + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr)) Var = dyn_cast<VarDecl>(DRE->getFoundDecl()); else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr)) Var = dyn_cast<VarDecl>(ME->getMemberDecl()); - - if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context)) - LSI->markVariableExprAsNonODRUsed(SansParensExpr); + + if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context)) + LSI->markVariableExprAsNonODRUsed(SansParensExpr); } } @@ -14910,7 +15332,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, // A reference initialized by a constant expression can never be // odr-used, so simply ignore it. if (!Var->getType()->isReferenceType() || - (SemaRef.LangOpts.OpenMP && SemaRef.IsOpenMPCapturedDecl(Var))) + (SemaRef.LangOpts.OpenMP && SemaRef.isOpenMPCapturedDecl(Var))) SemaRef.MaybeODRUseExprs.insert(E); } else if (OdrUseContext) { MarkVarDeclODRUsed(Var, Loc, SemaRef, @@ -14945,7 +15367,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, } } -/// \brief Mark a variable referenced, and check whether it is odr-used +/// Mark a variable referenced, and check whether it is odr-used /// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be /// used directly for normal expressions referring to VarDecl. void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) { @@ -14986,7 +15408,7 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse); } -/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr. +/// Perform reference-marking and odr-use handling for a DeclRefExpr. void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) { // TODO: update this with DR# once a defect report is filed. // C++11 defect. The address of a pure member should not be an ODR use, even @@ -14999,7 +15421,7 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) { MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse); } -/// \brief Perform reference-marking and odr-use handling for a MemberExpr. +/// Perform reference-marking and odr-use handling for a MemberExpr. void Sema::MarkMemberReferenced(MemberExpr *E) { // C++11 [basic.def.odr]p2: // A non-overloaded function whose name appears as a potentially-evaluated @@ -15018,7 +15440,7 @@ void Sema::MarkMemberReferenced(MemberExpr *E) { MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse); } -/// \brief Perform marking for a reference to an arbitrary declaration. It +/// Perform marking for a reference to an arbitrary declaration. It /// marks the declaration referenced, and performs odr-use checking for /// functions and variables. This method should not be used when building a /// normal expression which refers to a variable. @@ -15081,18 +15503,18 @@ void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) { } namespace { - /// \brief Helper class that marks all of the declarations referenced by + /// Helper class that marks all of the declarations referenced by /// potentially-evaluated subexpressions as "referenced". class EvaluatedExprMarker : public EvaluatedExprVisitor<EvaluatedExprMarker> { Sema &S; bool SkipLocalVariables; - + public: typedef EvaluatedExprVisitor<EvaluatedExprMarker> Inherited; - - EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) + + EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) : Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { } - + void VisitDeclRefExpr(DeclRefExpr *E) { // If we were asked not to visit local variables, don't. if (SkipLocalVariables) { @@ -15100,7 +15522,7 @@ namespace { if (VD->hasLocalStorage()) return; } - + S.MarkDeclRefReferenced(E); } @@ -15108,13 +15530,13 @@ namespace { S.MarkMemberReferenced(E); Inherited::VisitMemberExpr(E); } - + void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { S.MarkFunctionReferenced(E->getLocStart(), const_cast<CXXDestructorDecl*>(E->getTemporary()->getDestructor())); Visit(E->getSubExpr()); } - + void VisitCXXNewExpr(CXXNewExpr *E) { if (E->getOperatorNew()) S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew()); @@ -15129,18 +15551,18 @@ namespace { QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType()); if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); - S.MarkFunctionReferenced(E->getLocStart(), + S.MarkFunctionReferenced(E->getLocStart(), S.LookupDestructor(Record)); } - + Inherited::VisitCXXDeleteExpr(E); } - + void VisitCXXConstructExpr(CXXConstructExpr *E) { S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor()); Inherited::VisitCXXConstructExpr(E); } - + void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { Visit(E->getExpr()); } @@ -15154,17 +15576,17 @@ namespace { }; } -/// \brief Mark any declarations that appear within this expression or any +/// Mark any declarations that appear within this expression or any /// potentially-evaluated subexpressions as "referenced". /// -/// \param SkipLocalVariables If true, don't mark local variables as +/// \param SkipLocalVariables If true, don't mark local variables as /// 'referenced'. -void Sema::MarkDeclarationsReferencedInExpr(Expr *E, +void Sema::MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables) { EvaluatedExprMarker(*this, SkipLocalVariables).Visit(E); } -/// \brief Emit a diagnostic that describes an effect on the run-time behavior +/// Emit a diagnostic that describes an effect on the run-time behavior /// of the program being compiled. /// /// This routine emits the given diagnostic when the code currently being @@ -15230,7 +15652,8 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, // If we're inside a decltype's expression, don't check for a valid return // type or construct temporaries until we know whether this is the last call. - if (ExprEvalContexts.back().IsDecltype) { + if (ExprEvalContexts.back().ExprContext == + ExpressionEvaluationContextRecord::EK_Decltype) { ExprEvalContexts.back().DelayedDecltypeCalls.push_back(CE); return false; } @@ -15238,7 +15661,7 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, class CallReturnIncompleteDiagnoser : public TypeDiagnoser { FunctionDecl *FD; CallExpr *CE; - + public: CallReturnIncompleteDiagnoser(FunctionDecl *FD, CallExpr *CE) : FD(FD), CE(CE) { } @@ -15249,14 +15672,14 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, << T << CE->getSourceRange(); return; } - + S.Diag(Loc, diag::err_call_function_incomplete_return) << CE->getSourceRange() << FD->getDeclName() << T; S.Diag(FD->getLocation(), diag::note_entity_declared_at) << FD->getDeclName(); } } Diagnoser(FD, CE); - + if (RequireCompleteType(Loc, ReturnType, Diagnoser)) return true; @@ -15321,7 +15744,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { << FixItHint::CreateReplacement(Loc, "=="); } -/// \brief Redundant parentheses over an equality comparison can indicate +/// Redundant parentheses over an equality comparison can indicate /// that the user intended an assignment used as condition. void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) { // Don't warn if the parens came from a macro. @@ -15339,7 +15762,7 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) { opE->getLHS()->IgnoreParenImpCasts()->isModifiableLvalue(Context) == Expr::MLV_Valid) { SourceLocation Loc = opE->getOperatorLoc(); - + Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange(); SourceRange ParenERange = ParenE->getSourceRange(); Diag(Loc, diag::note_equality_comparison_silence) @@ -15676,7 +16099,7 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) { } // Rebuild the appropriate pointer-to-function type. - switch (Kind) { + switch (Kind) { case FK_MemberFunction: // Nothing to do. break; @@ -15725,15 +16148,15 @@ ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) { if (E->getCastKind() == CK_FunctionToPointerDecay) { assert(E->getValueKind() == VK_RValue); assert(E->getObjectKind() == OK_Ordinary); - + E->setType(DestType); - + // Rebuild the sub-expression as the pointee (function) type. DestType = DestType->castAs<PointerType>()->getPointeeType(); - + ExprResult Result = Visit(E->getSubExpr()); if (!Result.isUsable()) return ExprError(); - + E->setSubExpr(Result.get()); return E; } else if (E->getCastKind() == CK_LValueToRValue) { @@ -15795,7 +16218,7 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { SC_None, false/*isInlineSpecified*/, FD->hasPrototype(), false/*isConstexprSpecified*/); - + if (FD->getQualifier()) NewFD->setQualifierInfo(FD->getQualifierLoc()); @@ -16063,7 +16486,7 @@ Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { Sema::LookupOrdinaryName); if (LookupName(Result, getCurScope()) && Result.isSingleResult()) { NamedDecl *ND = Result.getFoundDecl(); - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND)) + if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND)) Context.setBOOLDecl(TD); } } |
