diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp | 2613 |
1 files changed, 789 insertions, 1824 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp index 4cce0abc2315..687b1be94592 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "CheckExprLifetime.h" #include "TreeTransform.h" #include "UsedDeclVisitor.h" #include "clang/AST/ASTConsumer.h" @@ -49,10 +50,15 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" +#include "clang/Sema/SemaOpenMP.h" +#include "clang/Sema/SemaPseudoObject.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ConvertUTF.h" @@ -63,8 +69,6 @@ using namespace clang; using namespace sema; -/// 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. if (ParsingInitForAutoVars.count(D)) @@ -106,14 +110,13 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { // should diagnose them. if (A->getSemanticSpelling() != UnusedAttr::CXX11_maybe_unused && A->getSemanticSpelling() != UnusedAttr::C23_maybe_unused) { - const Decl *DC = cast_or_null<Decl>(S.getCurObjCLexicalContext()); + const Decl *DC = cast_or_null<Decl>(S.ObjC().getCurObjCLexicalContext()); if (DC && !DC->hasAttr<UnusedAttr>()) S.Diag(Loc, diag::warn_used_but_marked_unused) << D; } } } -/// Emit a note explaining that this function is deleted. void Sema::NoteDeletedFunction(FunctionDecl *Decl) { assert(Decl && Decl->isDeleted()); @@ -209,18 +212,6 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) { } } -/// Determine whether the use of this declaration is valid, and -/// emit any corresponding diagnostics. -/// -/// This routine diagnoses various problems with referencing -/// declarations that can occur when using a declaration. For example, -/// it might warn if a deprecated or unavailable declaration is being -/// used, or produce an error (and return true) if a C++0x deleted -/// function is being used. -/// -/// \returns true if there was an error (this declaration cannot be -/// referenced), false otherwise. -/// bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass, bool ObjCPropertyAccess, @@ -271,8 +262,11 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, Diag(Loc, diag::err_deleted_inherited_ctor_use) << Ctor->getParent() << Ctor->getInheritedConstructor().getConstructor()->getParent(); - else - Diag(Loc, diag::err_deleted_function_use); + else { + StringLiteral *Msg = FD->getDeletedMessage(); + Diag(Loc, diag::err_deleted_function_use) + << (Msg != nullptr) << (Msg ? Msg->getString() : StringRef()); + } NoteDeletedFunction(FD); return true; } @@ -307,7 +301,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, DeduceReturnType(FD, Loc)) return true; - if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD)) + if (getLangOpts().CUDA && !CUDA().CheckCall(Loc, FD)) return true; } @@ -355,9 +349,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, // at the same location. // [OpenMP 5.2] Also allow iterator declared variables. if (LangOpts.OpenMP && isa<VarDecl>(D) && - !isOpenMPDeclareMapperVarDeclAllowed(cast<VarDecl>(D))) { + !OpenMP().isOpenMPDeclareMapperVarDeclAllowed(cast<VarDecl>(D))) { Diag(Loc, diag::err_omp_declare_mapper_wrong_var) - << getOpenMPDeclareMapperVarName(); + << OpenMP().getOpenMPDeclareMapperVarName(); Diag(D->getLocation(), diag::note_entity_declared_at) << D; return true; } @@ -410,10 +404,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, return false; } -/// DiagnoseSentinelCalls - This routine checks whether a call or -/// message-send is to a declaration with the sentinel attribute, and -/// if so, it checks that the requirements of the sentinel are -/// satisfied. void Sema::DiagnoseSentinelCalls(const NamedDecl *D, SourceLocation Loc, ArrayRef<Expr *> Args) { const SentinelAttr *Attr = D->getAttr<SentinelAttr>(); @@ -658,17 +648,19 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { QualType T = E->getType(); assert(!T.isNull() && "r-value conversion on typeless expression?"); - // lvalue-to-rvalue conversion cannot be applied to function or array types. - if (T->isFunctionType() || T->isArrayType()) + // lvalue-to-rvalue conversion cannot be applied to types that decay to + // pointers (i.e. function or array types). + if (T->canDecayToPointerType()) return E; // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. - if (getLangOpts().CPlusPlus && - (E->getType() == Context.OverloadTy || - T->isDependentType() || - T->isRecordType())) - return E; + if (getLangOpts().CPlusPlus) { + if (T == Context.OverloadTy || T->isRecordType() || + (T->isDependentType() && !T->isAnyPointerType() && + !T->isMemberPointerType())) + return E; + } // The C standard is actually really unclear on this point, and // DR106 tells us what the result should be but not why. It's @@ -762,8 +754,6 @@ ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose) { return Res; } -/// CallExprUnaryConversions - a special case of an unary conversion -/// performed on a function designator of a call expression. ExprResult Sema::CallExprUnaryConversions(Expr *E) { QualType Ty = E->getType(); ExprResult Res = E; @@ -931,9 +921,6 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { return E; } -/// Determine the degree of POD-ness for an expression. -/// Incomplete types are considered POD, since this check can be performed -/// when we're in an unevaluated context. Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) { if (Ty->isIncompleteType()) { // C++11 [expr.call]p7: @@ -1034,8 +1021,6 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) { } } -/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but -/// will create a trap if the resulting type is not a POD type. ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, FunctionDecl *FDecl) { if (const BuiltinType *PlaceholderTy = E->getType()->getAsPlaceholderType()) { @@ -1043,9 +1028,9 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast && (CT == VariadicMethod || (FDecl && FDecl->hasAttr<CFAuditedTransferAttr>()))) { - E = stripARCUnbridgedCast(E); + E = ObjC().stripARCUnbridgedCast(E); - // Otherwise, do normal placeholder checking. + // Otherwise, do normal placeholder checking. } else { ExprResult ExprRes = CheckPlaceholderExpr(E); if (ExprRes.isInvalid()) @@ -1099,12 +1084,13 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, return E; } -/// Converts an integer to complex float type. Helper function of +/// Convert complex integers to complex floats and real integers to +/// real floats as required for complex arithmetic. Helper function of /// UsualArithmeticConversions() /// /// \return false if the integer expression is an integer type and is -/// successfully converted to the complex type. -static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr, +/// successfully converted to the (complex) float type. +static bool handleComplexIntegerToFloatConversion(Sema &S, ExprResult &IntExpr, ExprResult &ComplexExpr, QualType IntTy, QualType ComplexTy, @@ -1114,8 +1100,6 @@ static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr, if (IntTy->isIntegerType()) { QualType fpTy = ComplexTy->castAs<ComplexType>()->getElementType(); IntExpr = S.ImpCastExprToType(IntExpr.get(), fpTy, CK_IntegralToFloating); - IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy, - CK_FloatingRealToComplex); } else { assert(IntTy->isComplexIntegerType()); IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy, @@ -1160,11 +1144,11 @@ static QualType handleComplexFloatConversion(Sema &S, ExprResult &Shorter, static QualType handleComplexConversion(Sema &S, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign) { - // if we have an integer operand, the result is the complex type. - if (!handleIntegerToComplexFloatConversion(S, RHS, LHS, RHSType, LHSType, + // Handle (complex) integer types. + if (!handleComplexIntegerToFloatConversion(S, RHS, LHS, RHSType, LHSType, /*SkipCast=*/false)) return LHSType; - if (!handleIntegerToComplexFloatConversion(S, LHS, RHS, LHSType, RHSType, + if (!handleComplexIntegerToFloatConversion(S, LHS, RHS, LHSType, RHSType, /*SkipCast=*/IsCompAssign)) return RHSType; @@ -1497,7 +1481,8 @@ static void checkEnumArithmeticConversions(Sema &S, Expr *LHS, Expr *RHS, // // Warn on this in all language modes. Produce a deprecation warning in C++20. // Eventually we will presumably reject these cases (in C++23 onwards?). - QualType L = LHS->getType(), R = RHS->getType(); + QualType L = LHS->getEnumCoercedType(S.Context), + R = RHS->getEnumCoercedType(S.Context); bool LEnum = L->isUnscopedEnumerationType(), REnum = R->isUnscopedEnumerationType(); bool IsCompAssign = ACK == Sema::ACK_CompAssign; @@ -2041,12 +2026,6 @@ Sema::ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> Toks) { return ExpandedToks; } -/// ActOnStringLiteral - The specified tokens were lexed as pasted string -/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string -/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from -/// multiple tokens. However, the common case is that StringToks points to one -/// string. -/// ExprResult Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { assert(!StringToks.empty() && "Must have at least one string!"); @@ -2072,6 +2051,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { } else if (Literal.isUTF8()) { if (getLangOpts().Char8) CharTy = Context.Char8Ty; + else if (getLangOpts().C23) + CharTy = Context.UnsignedCharTy; Kind = StringLiteralKind::UTF8; } else if (Literal.isUTF16()) { CharTy = Context.Char16Ty; @@ -2083,17 +2064,23 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { CharTy = Context.UnsignedCharTy; } - // Warn on initializing an array of char from a u8 string literal; this - // becomes ill-formed in C++2a. - if (getLangOpts().CPlusPlus && !getLangOpts().CPlusPlus20 && - !getLangOpts().Char8 && Kind == StringLiteralKind::UTF8) { - Diag(StringTokLocs.front(), diag::warn_cxx20_compat_utf8_string); + // Warn on u8 string literals before C++20 and C23, whose type + // was an array of char before but becomes an array of char8_t. + // In C++20, it cannot be used where a pointer to char is expected. + // In C23, it might have an unexpected value if char was signed. + if (Kind == StringLiteralKind::UTF8 && + (getLangOpts().CPlusPlus + ? !getLangOpts().CPlusPlus20 && !getLangOpts().Char8 + : !getLangOpts().C23)) { + Diag(StringTokLocs.front(), getLangOpts().CPlusPlus + ? diag::warn_cxx20_compat_utf8_string + : diag::warn_c23_compat_utf8_string); // Create removals for all 'u8' prefixes in the string literal(s). This - // ensures C++2a compatibility (but may change the program behavior when + // ensures C++20/C23 compatibility (but may change the program behavior when // built by non-Clang compilers for which the execution character set is // not always UTF-8). - auto RemovalDiag = PDiag(diag::note_cxx20_compat_utf8_string_remove_u8); + auto RemovalDiag = PDiag(diag::note_cxx20_c23_compat_utf8_string_remove_u8); SourceLocation RemovalDiagLoc; for (const Token &Tok : StringToks) { if (Tok.getKind() == tok::utf8_string_literal) { @@ -2261,7 +2248,7 @@ NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) { // be loaded from the captured. if (VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->getType()->isReferenceType() && - !(getLangOpts().OpenMP && isOpenMPCapturedDecl(D)) && + !(getLangOpts().OpenMP && OpenMP().isOpenMPCapturedDecl(D)) && !isCapturingReferenceToHostVarInCUDADeviceLambda(*this, VD) && VD->isUsableInConstantExpressions(Context)) return NOUR_Constant; @@ -2272,8 +2259,6 @@ NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) { return NOUR_None; } -/// BuildDeclRefExpr - Build an expression that references a -/// declaration that does not require a closure capture. DeclRefExpr * Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, const DeclarationNameInfo &NameInfo, @@ -2331,15 +2316,6 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, return E; } -/// Decomposes the given name into a DeclarationNameInfo, its location, and -/// possibly a list of template arguments. -/// -/// If this produces template arguments, it is permitted to call -/// DecomposeTemplateName. -/// -/// This actually loses a lot of source location information for -/// non-standard name kinds; we should consider preserving that in -/// some way. void Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer, @@ -2396,14 +2372,6 @@ static void emitEmptyLookupTypoDiagnostic( SemaRef.PDiag(NoteID)); } -/// Diagnose a lookup that found results in an enclosing class during error -/// recovery. This usually indicates that the results were found in a dependent -/// base class that could not be searched as part of a template definition. -/// Always issues a diagnostic (though this may be only a warning in MS -/// compatibility mode). -/// -/// Return \c true if the error is unrecoverable, or \c false if the caller -/// should attempt to recover using these lookup results. bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) { // During a default argument instantiation the CurContext points // to a CXXMethodDecl; but we can't apply a this-> fixit inside a @@ -2463,9 +2431,6 @@ bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) { return false; } -/// Diagnose an empty lookup. -/// -/// \return false if new lookup candidates were found bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs, @@ -2653,7 +2618,7 @@ recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context, RD = ThisType->getPointeeType()->getAsCXXRecordDecl(); else if (auto *MD = dyn_cast<CXXMethodDecl>(S.CurContext)) RD = MD->getParent(); - if (!RD || !RD->hasAnyDependentBases()) + if (!RD || !RD->hasDefinition() || !RD->hasAnyDependentBases()) return nullptr; // Diagnose this as unqualified lookup into a dependent base class. If 'this' @@ -2709,34 +2674,23 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, return ExprError(); } - // C++ [temp.dep.expr]p3: - // An id-expression is type-dependent if it contains: - // -- an identifier that was declared with a dependent type, - // (note: handled after lookup) - // -- a template-id that is dependent, - // (note: handled in BuildTemplateIdExpr) - // -- a conversion-function-id that specifies a dependent type, - // -- a nested-name-specifier that contains a class-name that - // names a dependent type. - // Determine whether this is a member of an unknown specialization; - // we need to handle these differently. - bool DependentID = false; - if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && - Name.getCXXNameType()->isDependentType()) { - DependentID = true; - } else if (SS.isSet()) { - if (DeclContext *DC = computeDeclContext(SS, false)) { - if (RequireCompleteDeclContext(SS, DC)) - return ExprError(); - } else { - DependentID = true; + // This specially handles arguments of attributes appertains to a type of C + // struct field such that the name lookup within a struct finds the member + // name, which is not the case for other contexts in C. + if (isAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) { + // See if this is reference to a field of struct. + LookupResult R(*this, NameInfo, LookupMemberName); + // LookupName handles a name lookup from within anonymous struct. + if (LookupName(R, S)) { + if (auto *VD = dyn_cast<ValueDecl>(R.getFoundDecl())) { + QualType type = VD->getType().getNonReferenceType(); + // This will eventually be translated into MemberExpr upon + // the use of instantiated struct fields. + return BuildDeclRefExpr(VD, type, VK_LValue, NameLoc); + } } } - if (DependentID) - return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, - IsAddressOfOperand, TemplateArgs); - // Perform the required lookup. LookupResult R(*this, NameInfo, (Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam) @@ -2748,31 +2702,30 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // 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; AssumedTemplateKind AssumedTemplate; - if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false, - MemberOfUnknownSpecialization, TemplateKWLoc, + if (LookupTemplateName(R, S, SS, /*ObjectType=*/QualType(), + /*EnteringContext=*/false, TemplateKWLoc, &AssumedTemplate)) return ExprError(); - if (MemberOfUnknownSpecialization || - (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); } else { bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl(); - LookupParsedName(R, S, &SS, !IvarLookupFollowUp); + LookupParsedName(R, S, &SS, /*ObjectType=*/QualType(), + /*AllowBuiltinCreation=*/!IvarLookupFollowUp); // If the result might be in a dependent base class, this is a dependent // id-expression. - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); // If this reference is in an Objective-C method, then we need to do // some special Objective-C lookup, too. if (IvarLookupFollowUp) { - ExprResult E(LookupInObjCMethod(R, S, II, true)); + ExprResult E(ObjC().LookupInObjCMethod(R, S, II, true)); if (E.isInvalid()) return ExprError(); @@ -2857,7 +2810,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // reference the ivar. if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) { R.clear(); - ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier())); + ExprResult E(ObjC().LookupInObjCMethod(R, S, Ivar->getIdentifier())); // In a hopelessly buggy code, Objective-C instance variable // lookup fails and no expression will be built to reference it. if (!E.isInvalid() && !E.get()) @@ -2893,25 +2846,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // to get this right here so that we don't end up making a // spuriously dependent expression if we're inside a dependent // instance method. - if (!R.empty() && (*R.begin())->isCXXClassMember()) { - bool MightBeImplicitMember; - if (!IsAddressOfOperand) - MightBeImplicitMember = true; - else if (!SS.isEmpty()) - MightBeImplicitMember = false; - else if (R.isOverloadedResult()) - MightBeImplicitMember = false; - else if (R.isUnresolvableResult()) - MightBeImplicitMember = true; - else - MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) || - isa<IndirectFieldDecl>(R.getFoundDecl()) || - isa<MSPropertyDecl>(R.getFoundDecl()); - - if (MightBeImplicitMember) - return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, - R, TemplateArgs, S); - } + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, + S); if (TemplateArgs || TemplateKWLoc.isValid()) { @@ -2930,32 +2867,16 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, return BuildDeclarationNameExpr(SS, R, ADL); } -/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified -/// declaration name, generally during template instantiation. -/// There's a large number of things which don't need to be done along -/// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, - bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { - if (NameInfo.getName().isDependentName()) - return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - DeclContext *DC = computeDeclContext(SS, false); - if (!DC) - return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - if (RequireCompleteDeclContext(SS, DC)) - return ExprError(); - + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupQualifiedName(R, DC); + LookupParsedName(R, /*S=*/nullptr, &SS, /*ObjectType=*/QualType()); if (R.isAmbiguous()) return ExprError(); - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo, /*TemplateArgs=*/nullptr); @@ -2964,6 +2885,7 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( // diagnostic during template instantiation is likely bogus, e.g. if a class // is invalid because it's derived from an invalid base class, then missing // members were likely supposed to be inherited. + DeclContext *DC = computeDeclContext(SS); if (const auto *CD = dyn_cast<CXXRecordDecl>(DC)) if (CD->isInvalidDecl()) return ExprError(); @@ -3007,198 +2929,16 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( return ExprEmpty(); } - // Defend against this resolving to an implicit member access. We usually - // won't get here if this might be a legitimate a class member (we end up in - // BuildMemberReferenceExpr instead), but this can be valid if we're forming - // a pointer-to-member or in an unevaluated context in C++11. - if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand) + // If necessary, build an implicit class member access. + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) return BuildPossibleImplicitMemberExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - R, /*TemplateArgs=*/nullptr, S); - - return BuildDeclarationNameExpr(SS, R, /* ADL */ false); -} - -/// The parser has read a name in, and Sema has detected that we're currently -/// inside an ObjC method. Perform some additional checks and determine if we -/// should form a reference to an ivar. -/// -/// Ideally, most of this would be done by lookup, but there's -/// actually quite a lot of extra work involved. -DeclResult Sema::LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, - IdentifierInfo *II) { - SourceLocation Loc = Lookup.getNameLoc(); - ObjCMethodDecl *CurMethod = getCurMethodDecl(); - - // Check for error condition which is already reported. - if (!CurMethod) - return DeclResult(true); - - // There are two cases to handle here. 1) scoped lookup could have failed, - // in which case we should look for an ivar. 2) scoped lookup could have - // found a decl, but that decl is outside the current instance method (i.e. - // a global variable). In these two cases, we do a lookup for an ivar with - // this name, if the lookup sucedes, we replace it our current decl. - - // If we're in a class method, we don't normally want to look for - // ivars. But if we don't find anything else, and there's an - // ivar, that's an error. - bool IsClassMethod = CurMethod->isClassMethod(); - - bool LookForIvars; - if (Lookup.empty()) - LookForIvars = true; - else if (IsClassMethod) - LookForIvars = false; - else - LookForIvars = (Lookup.isSingleResult() && - Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); - ObjCInterfaceDecl *IFace = nullptr; - if (LookForIvars) { - IFace = CurMethod->getClassInterface(); - ObjCInterfaceDecl *ClassDeclared; - ObjCIvarDecl *IV = nullptr; - if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) { - // Diagnose using an ivar in a class method. - if (IsClassMethod) { - Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName(); - return DeclResult(true); - } - - // Diagnose the use of an ivar outside of the declaring class. - if (IV->getAccessControl() == ObjCIvarDecl::Private && - !declaresSameEntity(ClassDeclared, IFace) && - !getLangOpts().DebuggerSupport) - Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName(); - - // Success. - return IV; - } - } else if (CurMethod->isInstanceMethod()) { - // We should warn if a local variable hides an ivar. - if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) { - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { - if (IV->getAccessControl() != ObjCIvarDecl::Private || - declaresSameEntity(IFace, ClassDeclared)) - Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); - } - } - } else if (Lookup.isSingleResult() && - Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) { - // If accessing a stand-alone ivar in a class method, this is an error. - if (const ObjCIvarDecl *IV = - dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl())) { - Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName(); - return DeclResult(true); - } - } - - // Didn't encounter an error, didn't find an ivar. - return DeclResult(false); -} - -ExprResult Sema::BuildIvarRefExpr(Scope *S, SourceLocation Loc, - ObjCIvarDecl *IV) { - ObjCMethodDecl *CurMethod = getCurMethodDecl(); - assert(CurMethod && CurMethod->isInstanceMethod() && - "should not reference ivar from this context"); - - ObjCInterfaceDecl *IFace = CurMethod->getClassInterface(); - assert(IFace && "should not reference ivar from this context"); - - // If we're referencing an invalid decl, just return this as a silent - // error node. The error diagnostic was already emitted on the decl. - if (IV->isInvalidDecl()) - return ExprError(); - - // Check if referencing a field with __attribute__((deprecated)). - if (DiagnoseUseOfDecl(IV, Loc)) - return ExprError(); - - // FIXME: This should use a new expr for a direct reference, don't - // turn this into Self->ivar, just return a BareIVarExpr or something. - IdentifierInfo &II = Context.Idents.get("self"); - UnqualifiedId SelfName; - SelfName.setImplicitSelfParam(&II); - CXXScopeSpec SelfScopeSpec; - SourceLocation TemplateKWLoc; - ExprResult SelfExpr = - ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName, - /*HasTrailingLParen=*/false, - /*IsAddressOfOperand=*/false); - if (SelfExpr.isInvalid()) - return ExprError(); - - SelfExpr = DefaultLvalueConversion(SelfExpr.get()); - if (SelfExpr.isInvalid()) - return ExprError(); + R, /*TemplateArgs=*/nullptr, + /*S=*/nullptr); - MarkAnyDeclReferenced(Loc, IV, true); - - ObjCMethodFamily MF = CurMethod->getMethodFamily(); - if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize && - !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV)) - Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName(); - - ObjCIvarRefExpr *Result = new (Context) - ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc, - IV->getLocation(), SelfExpr.get(), true, true); - - if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { - if (!isUnevaluatedContext() && - !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) - getCurFunction()->recordUseOfWeak(Result); - } - if (getLangOpts().ObjCAutoRefCount && !isUnevaluatedContext()) - if (const BlockDecl *BD = CurContext->getInnermostBlockDecl()) - ImplicitlyRetainedSelfLocs.push_back({Loc, BD}); - - return Result; -} - -/// The parser has read a name in, and Sema has detected that we're currently -/// inside an ObjC method. Perform some additional checks and determine if we -/// should form a reference to an ivar. If so, build an expression referencing -/// that ivar. -ExprResult -Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, - IdentifierInfo *II, bool AllowBuiltinCreation) { - // FIXME: Integrate this lookup step into LookupParsedName. - DeclResult Ivar = LookupIvarInObjCMethod(Lookup, S, II); - if (Ivar.isInvalid()) - return ExprError(); - if (Ivar.isUsable()) - return BuildIvarRefExpr(S, Lookup.getNameLoc(), - cast<ObjCIvarDecl>(Ivar.get())); - - if (Lookup.empty() && II && AllowBuiltinCreation) - LookupBuiltin(Lookup); - - // Sentinel value saying that we didn't do anything special. - return ExprResult(false); + return BuildDeclarationNameExpr(SS, R, /*ADL=*/false); } -/// Cast a base object to a member's actual type. -/// -/// There are two relevant checks: -/// -/// C++ [class.access.base]p7: -/// -/// If a class member access operator [...] is used to access a non-static -/// data member or non-static member function, the reference is ill-formed if -/// the left operand [...] cannot be implicitly converted to a pointer to the -/// naming class of the right operand. -/// -/// C++ [expr.ref]p7: -/// -/// If E2 is a non-static data member or a non-static member function, the -/// program is ill-formed if the class of which E2 is directly a member is an -/// ambiguous base (11.8) of the naming class (11.9.3) of E2. -/// -/// Note that the latter check does not consider access; the access of the -/// "real" base class is checked as appropriate when checking the access of the -/// member name. ExprResult Sema::PerformObjectMemberConversion(Expr *From, NestedNameSpecifier *Qualifier, @@ -3340,7 +3080,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, return false; // Never if a scope specifier was provided. - if (SS.isSet()) + if (SS.isNotEmpty()) return false; // Only in C++ or ObjC++. @@ -3445,12 +3185,10 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // we've picked a target. R.suppressDiagnostics(); - UnresolvedLookupExpr *ULE - = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), - SS.getWithLocInContext(Context), - R.getLookupNameInfo(), - NeedsADL, R.isOverloadedResult(), - R.begin(), R.end()); + UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create( + Context, R.getNamingClass(), SS.getWithLocInContext(Context), + R.getLookupNameInfo(), NeedsADL, R.begin(), R.end(), + /*KnownDependent=*/false, /*KnownInstantiationDependent=*/false); return ULE; } @@ -3459,7 +3197,6 @@ static void diagnoseUncapturableValueReferenceOrBinding(Sema &S, SourceLocation loc, ValueDecl *var); -/// 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, @@ -3476,10 +3213,10 @@ ExprResult Sema::BuildDeclarationNameExpr( return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}); } - if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) { + if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) { // Specifically diagnose references to class templates that are missing // a template argument list. - diagnoseMissingTemplateArguments(TemplateName(Template), Loc); + diagnoseMissingTemplateArguments(SS, /*TemplateKeyword=*/false, TD, Loc); return ExprError(); } @@ -3549,7 +3286,8 @@ ExprResult Sema::BuildDeclarationNameExpr( case Decl::Field: case Decl::IndirectField: case Decl::ObjCIvar: - assert(getLangOpts().CPlusPlus && "building reference to field in C?"); + assert((getLangOpts().CPlusPlus || isAttrContext()) && + "building reference to field in C?"); // These can't have reference type in well-formed programs, but // for internal consistency we do this anyway. @@ -3740,7 +3478,10 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, else { // Pre-defined identifiers are of type char[x], where x is the length of // the string. - auto Str = PredefinedExpr::ComputeName(IK, currentDecl); + bool ForceElaboratedPrinting = + IK == PredefinedIdentKind::Function && getLangOpts().MSVCCompat; + auto Str = + PredefinedExpr::ComputeName(IK, currentDecl, ForceElaboratedPrinting); unsigned Length = Str.length(); llvm::APInt LengthI(32, Length + 1); @@ -3770,28 +3511,6 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, SL); } -ExprResult Sema::BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc, - SourceLocation LParen, - SourceLocation RParen, - TypeSourceInfo *TSI) { - return SYCLUniqueStableNameExpr::Create(Context, OpLoc, LParen, RParen, TSI); -} - -ExprResult Sema::ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc, - SourceLocation LParen, - SourceLocation RParen, - ParsedType ParsedTy) { - TypeSourceInfo *TSI = nullptr; - QualType Ty = GetTypeFromParser(ParsedTy, &TSI); - - if (Ty.isNull()) - return ExprError(); - if (!TSI) - TSI = Context.getTrivialTypeSourceInfo(Ty, LParen); - - return BuildSYCLUniqueStableNameExpr(OpLoc, LParen, RParen, TSI); -} - ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { return BuildPredefinedExpr(Loc, getPredefinedExprKind(Kind)); } @@ -3869,7 +3588,10 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, using llvm::APFloat; APFloat Val(Format); - APFloat::opStatus result = Literal.GetFloatValue(Val); + llvm::RoundingMode RM = S.CurFPFeatures.getRoundingMode(); + if (RM == llvm::RoundingMode::Dynamic) + RM = llvm::RoundingMode::NearestTiesToEven; + APFloat::opStatus result = Literal.GetFloatValue(Val, RM); // Overflow is always an error, but underflow is only an error if // we underflowed to zero (APFloat reports denormals as underflow). @@ -3885,16 +3607,14 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, APFloat::getSmallest(Format).toString(buffer); } - S.Diag(Loc, diagnostic) - << Ty - << StringRef(buffer.data(), buffer.size()); + S.Diag(Loc, diagnostic) << Ty << buffer.str(); } bool isExact = (result == APFloat::opOK); return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc); } -bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) { +bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc, bool AllowZero) { assert(E && "Invalid expression"); if (E->isValueDependent()) @@ -3912,9 +3632,15 @@ bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) { if (R.isInvalid()) return true; - bool ValueIsPositive = ValueAPS.isStrictlyPositive(); + // GCC allows the value of unroll count to be 0. + // https://gcc.gnu.org/onlinedocs/gcc/Loop-Specific-Pragmas.html says + // "The values of 0 and 1 block any unrolling of the loop." + // The values doesn't have to be strictly positive in '#pragma GCC unroll' and + // '#pragma unroll' cases. + bool ValueIsPositive = + AllowZero ? ValueAPS.isNonNegative() : ValueAPS.isStrictlyPositive(); if (!ValueIsPositive || ValueAPS.getActiveBits() > 31) { - Diag(E->getExprLoc(), diag::err_pragma_loop_invalid_argument_value) + Diag(E->getExprLoc(), diag::err_requires_positive_value) << toString(ValueAPS, 10) << ValueIsPositive; return true; } @@ -3925,9 +3651,9 @@ bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) { ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // Fast path for a single digit (which is quite common). A single digit // cannot have a trigraph, escaped newline, radix prefix, or suffix. - if (Tok.getLength() == 1) { + if (Tok.getLength() == 1 || Tok.getKind() == tok::binary_data) { const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok); - return ActOnIntegerConstant(Tok.getLocation(), Val-'0'); + return ActOnIntegerConstant(Tok.getLocation(), Val); } SmallString<128> SpellingBuffer; @@ -4093,7 +3819,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } else if (Literal.isFloatingLiteral()) { QualType Ty; if (Literal.isHalf){ - if (getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts())) + if (getLangOpts().HLSL || + getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts())) Ty = Context.HalfTy; else { Diag(Tok.getLocation(), diag::err_half_const_requires_fp16); @@ -4102,11 +3829,13 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } else if (Literal.isFloat) Ty = Context.FloatTy; else if (Literal.isLong) - Ty = Context.LongDoubleTy; + Ty = !getLangOpts().HLSL ? Context.LongDoubleTy : Context.DoubleTy; else if (Literal.isFloat16) Ty = Context.Float16Ty; else if (Literal.isFloat128) Ty = Context.Float128Ty; + else if (getLangOpts().HLSL) + Ty = Context.FloatTy; else Ty = Context.DoubleTy; @@ -4141,11 +3870,13 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // 'wb/uwb' literals are a C23 feature. We support _BitInt as a type in C++, // but we do not currently support the suffix in C++ mode because it's not // entirely clear whether WG21 will prefer this suffix to return a library - // type such as std::bit_int instead of returning a _BitInt. - if (Literal.isBitInt && !getLangOpts().CPlusPlus) - PP.Diag(Tok.getLocation(), getLangOpts().C23 - ? diag::warn_c23_compat_bitint_suffix - : diag::ext_c23_bitint_suffix); + // type such as std::bit_int instead of returning a _BitInt. '__wb/__uwb' + // literals are a C++ extension. + if (Literal.isBitInt) + PP.Diag(Tok.getLocation(), + getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix + : getLangOpts().C23 ? diag::warn_c23_compat_bitint_suffix + : diag::ext_c23_bitint_suffix); // Get the value in the widest-possible width. What is "widest" depends on // whether the literal is a bit-precise integer or not. For a bit-precise @@ -4175,6 +3906,15 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // be an unsigned int. bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10; + // HLSL doesn't really have `long` or `long long`. We support the `ll` + // suffix for portability of code with C++, but both `l` and `ll` are + // 64-bit integer types, and we want the type of `1l` and `1ll` to be the + // same. + if (getLangOpts().HLSL && !Literal.isLong && Literal.isLongLong) { + Literal.isLong = true; + Literal.isLongLong = false; + } + // Check from smallest to largest, picking the smallest type we can. unsigned Width = 0; @@ -4377,6 +4117,21 @@ static bool CheckVectorElementsTraitOperandType(Sema &S, QualType T, return false; } +static bool checkPtrAuthTypeDiscriminatorOperandType(Sema &S, QualType T, + SourceLocation Loc, + SourceRange ArgRange) { + if (S.checkPointerAuthEnabled(Loc, ArgRange)) + return true; + + if (!T->isFunctionType() && !T->isFunctionPointerType() && + !T->isFunctionReferenceType() && !T->isMemberFunctionPointerType()) { + S.Diag(Loc, diag::err_ptrauth_type_disc_undiscriminated) << T << ArgRange; + return true; + } + + return false; +} + static bool CheckExtensionTraitOperandType(Sema &S, QualType T, SourceLocation Loc, SourceRange ArgRange, @@ -4441,13 +4196,6 @@ static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T, << ICE->getSubExpr()->getType(); } -/// Check the constraints on expression operands to unary type expression -/// and type traits. -/// -/// Completes any types necessary and validates the constraints on the operand -/// expression. The logic mostly mirrors the type-based overload, but may modify -/// the expression as it completes the type for that expression through template -/// instantiation, etc. bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind) { QualType ExprTy = E->getType(); @@ -4663,6 +4411,9 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::Decayed: T = cast<DecayedType>(Ty)->getPointeeType(); break; + case Type::ArrayParameter: + T = cast<ArrayParameterType>(Ty)->getElementType(); + break; case Type::Pointer: T = cast<PointerType>(Ty)->getPointeeType(); break; @@ -4706,6 +4457,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::BTFTagAttributed: case Type::SubstTemplateTypeParm: case Type::MacroQualified: + case Type::CountAttributed: // Keep walking after single level desugaring. T = T.getSingleStepDesugaredType(Context); break; @@ -4715,6 +4467,9 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::Decltype: T = cast<DecltypeType>(Ty)->desugar(); break; + case Type::PackIndexing: + T = cast<PackIndexingType>(Ty)->desugar(); + break; case Type::Using: T = cast<UsingType>(Ty)->desugar(); break; @@ -4732,21 +4487,6 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, } while (!T.isNull() && T->isVariablyModifiedType()); } -/// Check the constraints on operands to unary expression and type -/// traits. -/// -/// This will complete any types necessary, and validate the various constraints -/// on those operands. -/// -/// The UsualUnaryConversions() function is *not* called by this routine. -/// C99 6.3.2.1p[2-4] all state: -/// Except when it is the operand of the sizeof operator ... -/// -/// C++ [expr.sizeof]p4 -/// The lvalue-to-rvalue, array-to-pointer, and function-to-pointer -/// standard conversions are not applied to the operand of sizeof. -/// -/// This policy is followed for all of the unary trait expressions. bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc, SourceRange ExprRange, @@ -4768,8 +4508,16 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, // When alignof or _Alignof is applied to an array type, the result // is the alignment of the element type. if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf || - ExprKind == UETT_OpenMPRequiredSimdAlign) + ExprKind == UETT_OpenMPRequiredSimdAlign) { + // If the trait is 'alignof' in C before C2y, the ability to apply the + // trait to an incomplete array is an extension. + if (ExprKind == UETT_AlignOf && !getLangOpts().CPlusPlus && + ExprType->isIncompleteArrayType()) + Diag(OpLoc, getLangOpts().C2y + ? diag::warn_c2y_compat_alignof_incomplete_array + : diag::ext_c2y_alignof_incomplete_array); ExprType = Context.getBaseElementType(ExprType); + } if (ExprKind == UETT_VecStep) return CheckVecStepTraitOperandType(*this, ExprType, OpLoc, ExprRange); @@ -4778,6 +4526,10 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, return CheckVectorElementsTraitOperandType(*this, ExprType, OpLoc, ExprRange); + if (ExprKind == UETT_PtrAuthTypeDiscriminator) + return checkPtrAuthTypeDiscriminatorOperandType(*this, ExprType, OpLoc, + ExprRange); + // Explicitly list some types as extensions. if (!CheckExtensionTraitOperandType(*this, ExprType, OpLoc, ExprRange, ExprKind)) @@ -4833,7 +4585,6 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, return false; } -/// Build a sizeof or alignof expression given a type operand. ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind, @@ -4859,8 +4610,6 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd()); } -/// Build a sizeof or alignof expression given an expression -/// operand. ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind) { @@ -4904,9 +4653,6 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, ExprKind, E, Context.getSizeType(), OpLoc, E->getSourceRange().getEnd()); } -/// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c -/// expr and the same for @c alignof and @c __alignof -/// Note that the ArgRange is invalid if isType is false. ExprResult Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind, bool IsType, @@ -4933,13 +4679,6 @@ bool Sema::CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo, UETT_AlignOf, KWName); } -/// ActOnAlignasTypeArgument - Handle @c alignas(type-id) and @c -/// _Alignas(type-name) . -/// [dcl.align] An alignment-specifier of the form -/// alignas(type-id) has the same effect as alignas(alignof(type-id)). -/// -/// [N1570 6.7.5] _Alignas(type-name) is equivalent to -/// _Alignas(_Alignof(type-name)). bool Sema::ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty, SourceLocation OpLoc, SourceRange R) { TypeSourceInfo *TInfo; @@ -5064,10 +4803,18 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation rbLoc) { if (base && !base->getType().isNull() && - base->hasPlaceholderType(BuiltinType::OMPArraySection)) - return ActOnOMPArraySectionExpr(base, lbLoc, ArgExprs.front(), SourceLocation(), - SourceLocation(), /*Length*/ nullptr, - /*Stride=*/nullptr, rbLoc); + base->hasPlaceholderType(BuiltinType::ArraySection)) { + auto *AS = cast<ArraySectionExpr>(base); + if (AS->isOMPArraySection()) + return OpenMP().ActOnOMPArraySectionExpr( + base, lbLoc, ArgExprs.front(), SourceLocation(), SourceLocation(), + /*Length*/ nullptr, + /*Stride=*/nullptr, rbLoc); + + return OpenACC().ActOnArraySectionExpr(base, lbLoc, ArgExprs.front(), + SourceLocation(), /*Length*/ nullptr, + rbLoc); + } // Since this might be a postfix expression, get rid of ParenListExprs. if (isa<ParenListExpr>(base)) { @@ -5339,558 +5086,6 @@ void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) { } } -ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, - Expr *LowerBound, - SourceLocation ColonLocFirst, - SourceLocation ColonLocSecond, - Expr *Length, Expr *Stride, - SourceLocation RBLoc) { - if (Base->hasPlaceholderType() && - !Base->hasPlaceholderType(BuiltinType::OMPArraySection)) { - ExprResult Result = CheckPlaceholderExpr(Base); - if (Result.isInvalid()) - return ExprError(); - Base = Result.get(); - } - if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) { - ExprResult Result = CheckPlaceholderExpr(LowerBound); - if (Result.isInvalid()) - return ExprError(); - Result = DefaultLvalueConversion(Result.get()); - if (Result.isInvalid()) - return ExprError(); - LowerBound = Result.get(); - } - if (Length && Length->getType()->isNonOverloadPlaceholderType()) { - ExprResult Result = CheckPlaceholderExpr(Length); - if (Result.isInvalid()) - return ExprError(); - Result = DefaultLvalueConversion(Result.get()); - if (Result.isInvalid()) - return ExprError(); - Length = Result.get(); - } - if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) { - ExprResult Result = CheckPlaceholderExpr(Stride); - if (Result.isInvalid()) - return ExprError(); - Result = DefaultLvalueConversion(Result.get()); - if (Result.isInvalid()) - return ExprError(); - Stride = Result.get(); - } - - // Build an unanalyzed expression if either operand is type-dependent. - if (Base->isTypeDependent() || - (LowerBound && - (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) || - (Length && (Length->isTypeDependent() || Length->isValueDependent())) || - (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) { - return new (Context) OMPArraySectionExpr( - Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue, - OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc); - } - - // Perform default conversions. - QualType OriginalTy = OMPArraySectionExpr::getBaseOriginalType(Base); - QualType ResultTy; - if (OriginalTy->isAnyPointerType()) { - ResultTy = OriginalTy->getPointeeType(); - } else if (OriginalTy->isArrayType()) { - ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType(); - } else { - return ExprError( - Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value) - << Base->getSourceRange()); - } - // C99 6.5.2.1p1 - if (LowerBound) { - auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(), - LowerBound); - if (Res.isInvalid()) - return ExprError(Diag(LowerBound->getExprLoc(), - diag::err_omp_typecheck_section_not_integer) - << 0 << LowerBound->getSourceRange()); - LowerBound = Res.get(); - - if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || - LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) - Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char) - << 0 << LowerBound->getSourceRange(); - } - if (Length) { - auto Res = - PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length); - if (Res.isInvalid()) - return ExprError(Diag(Length->getExprLoc(), - diag::err_omp_typecheck_section_not_integer) - << 1 << Length->getSourceRange()); - Length = Res.get(); - - if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || - Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) - Diag(Length->getExprLoc(), diag::warn_omp_section_is_char) - << 1 << Length->getSourceRange(); - } - if (Stride) { - ExprResult Res = - PerformOpenMPImplicitIntegerConversion(Stride->getExprLoc(), Stride); - if (Res.isInvalid()) - return ExprError(Diag(Stride->getExprLoc(), - diag::err_omp_typecheck_section_not_integer) - << 1 << Stride->getSourceRange()); - Stride = Res.get(); - - if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || - Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) - Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char) - << 1 << Stride->getSourceRange(); - } - - // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly, - // C++ [expr.sub]p1: The type "T" shall be a completely-defined object - // type. Note that functions are not objects, and that (in C99 parlance) - // incomplete types are not object types. - if (ResultTy->isFunctionType()) { - Diag(Base->getExprLoc(), diag::err_omp_section_function_type) - << ResultTy << Base->getSourceRange(); - return ExprError(); - } - - if (RequireCompleteType(Base->getExprLoc(), ResultTy, - diag::err_omp_section_incomplete_type, Base)) - return ExprError(); - - if (LowerBound && !OriginalTy->isAnyPointerType()) { - Expr::EvalResult Result; - if (LowerBound->EvaluateAsInt(Result, Context)) { - // OpenMP 5.0, [2.1.5 Array Sections] - // The array section must be a subset of the original array. - llvm::APSInt LowerBoundValue = Result.Val.getInt(); - if (LowerBoundValue.isNegative()) { - Diag(LowerBound->getExprLoc(), diag::err_omp_section_not_subset_of_array) - << LowerBound->getSourceRange(); - return ExprError(); - } - } - } - - if (Length) { - Expr::EvalResult Result; - if (Length->EvaluateAsInt(Result, Context)) { - // OpenMP 5.0, [2.1.5 Array Sections] - // The length must evaluate to non-negative integers. - llvm::APSInt LengthValue = Result.Val.getInt(); - if (LengthValue.isNegative()) { - Diag(Length->getExprLoc(), diag::err_omp_section_length_negative) - << toString(LengthValue, /*Radix=*/10, /*Signed=*/true) - << Length->getSourceRange(); - return ExprError(); - } - } - } else if (ColonLocFirst.isValid() && - (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() && - !OriginalTy->isVariableArrayType()))) { - // OpenMP 5.0, [2.1.5 Array Sections] - // When the size of the array dimension is not known, the length must be - // specified explicitly. - Diag(ColonLocFirst, diag::err_omp_section_length_undefined) - << (!OriginalTy.isNull() && OriginalTy->isArrayType()); - return ExprError(); - } - - if (Stride) { - Expr::EvalResult Result; - if (Stride->EvaluateAsInt(Result, Context)) { - // OpenMP 5.0, [2.1.5 Array Sections] - // The stride must evaluate to a positive integer. - llvm::APSInt StrideValue = Result.Val.getInt(); - if (!StrideValue.isStrictlyPositive()) { - Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive) - << toString(StrideValue, /*Radix=*/10, /*Signed=*/true) - << Stride->getSourceRange(); - return ExprError(); - } - } - } - - if (!Base->hasPlaceholderType(BuiltinType::OMPArraySection)) { - ExprResult Result = DefaultFunctionArrayLvalueConversion(Base); - if (Result.isInvalid()) - return ExprError(); - Base = Result.get(); - } - return new (Context) OMPArraySectionExpr( - Base, LowerBound, Length, Stride, Context.OMPArraySectionTy, VK_LValue, - OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc); -} - -ExprResult Sema::ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, - SourceLocation RParenLoc, - ArrayRef<Expr *> Dims, - ArrayRef<SourceRange> Brackets) { - if (Base->hasPlaceholderType()) { - ExprResult Result = CheckPlaceholderExpr(Base); - if (Result.isInvalid()) - return ExprError(); - Result = DefaultLvalueConversion(Result.get()); - if (Result.isInvalid()) - return ExprError(); - Base = Result.get(); - } - QualType BaseTy = Base->getType(); - // Delay analysis of the types/expressions if instantiation/specialization is - // required. - if (!BaseTy->isPointerType() && Base->isTypeDependent()) - return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base, - LParenLoc, RParenLoc, Dims, Brackets); - if (!BaseTy->isPointerType() || - (!Base->isTypeDependent() && - BaseTy->getPointeeType()->isIncompleteType())) - return ExprError(Diag(Base->getExprLoc(), - diag::err_omp_non_pointer_type_array_shaping_base) - << Base->getSourceRange()); - - SmallVector<Expr *, 4> NewDims; - bool ErrorFound = false; - for (Expr *Dim : Dims) { - if (Dim->hasPlaceholderType()) { - ExprResult Result = CheckPlaceholderExpr(Dim); - if (Result.isInvalid()) { - ErrorFound = true; - continue; - } - Result = DefaultLvalueConversion(Result.get()); - if (Result.isInvalid()) { - ErrorFound = true; - continue; - } - Dim = Result.get(); - } - if (!Dim->isTypeDependent()) { - ExprResult Result = - PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim); - if (Result.isInvalid()) { - ErrorFound = true; - Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer) - << Dim->getSourceRange(); - continue; - } - Dim = Result.get(); - Expr::EvalResult EvResult; - if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) { - // OpenMP 5.0, [2.1.4 Array Shaping] - // Each si is an integral type expression that must evaluate to a - // positive integer. - llvm::APSInt Value = EvResult.Val.getInt(); - if (!Value.isStrictlyPositive()) { - Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive) - << toString(Value, /*Radix=*/10, /*Signed=*/true) - << Dim->getSourceRange(); - ErrorFound = true; - continue; - } - } - } - NewDims.push_back(Dim); - } - if (ErrorFound) - return ExprError(); - return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base, - LParenLoc, RParenLoc, NewDims, Brackets); -} - -ExprResult Sema::ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, - SourceLocation LLoc, SourceLocation RLoc, - ArrayRef<OMPIteratorData> Data) { - SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID; - bool IsCorrect = true; - for (const OMPIteratorData &D : Data) { - TypeSourceInfo *TInfo = nullptr; - SourceLocation StartLoc; - QualType DeclTy; - if (!D.Type.getAsOpaquePtr()) { - // OpenMP 5.0, 2.1.6 Iterators - // In an iterator-specifier, if the iterator-type is not specified then - // the type of that iterator is of int type. - DeclTy = Context.IntTy; - StartLoc = D.DeclIdentLoc; - } else { - DeclTy = GetTypeFromParser(D.Type, &TInfo); - StartLoc = TInfo->getTypeLoc().getBeginLoc(); - } - - bool IsDeclTyDependent = DeclTy->isDependentType() || - DeclTy->containsUnexpandedParameterPack() || - DeclTy->isInstantiationDependentType(); - if (!IsDeclTyDependent) { - if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) { - // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++ - // The iterator-type must be an integral or pointer type. - Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer) - << DeclTy; - IsCorrect = false; - continue; - } - if (DeclTy.isConstant(Context)) { - // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++ - // The iterator-type must not be const qualified. - Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer) - << DeclTy; - IsCorrect = false; - continue; - } - } - - // Iterator declaration. - assert(D.DeclIdent && "Identifier expected."); - // Always try to create iterator declarator to avoid extra error messages - // about unknown declarations use. - auto *VD = VarDecl::Create(Context, CurContext, StartLoc, D.DeclIdentLoc, - D.DeclIdent, DeclTy, TInfo, SC_None); - VD->setImplicit(); - if (S) { - // Check for conflicting previous declaration. - DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc); - LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForVisibleRedeclaration); - Previous.suppressDiagnostics(); - LookupName(Previous, S); - - FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage=*/false, - /*AllowInlineNamespace=*/false); - if (!Previous.empty()) { - NamedDecl *Old = Previous.getRepresentativeDecl(); - Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName(); - Diag(Old->getLocation(), diag::note_previous_definition); - } else { - PushOnScopeChains(VD, S); - } - } else { - CurContext->addDecl(VD); - } - - /// Act on the iterator variable declaration. - ActOnOpenMPIteratorVarDecl(VD); - - Expr *Begin = D.Range.Begin; - if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) { - ExprResult BeginRes = - PerformImplicitConversion(Begin, DeclTy, AA_Converting); - Begin = BeginRes.get(); - } - Expr *End = D.Range.End; - if (!IsDeclTyDependent && End && !End->isTypeDependent()) { - ExprResult EndRes = PerformImplicitConversion(End, DeclTy, AA_Converting); - End = EndRes.get(); - } - Expr *Step = D.Range.Step; - if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) { - if (!Step->getType()->isIntegralType(Context)) { - Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral) - << Step << Step->getSourceRange(); - IsCorrect = false; - continue; - } - std::optional<llvm::APSInt> Result = - Step->getIntegerConstantExpr(Context); - // OpenMP 5.0, 2.1.6 Iterators, Restrictions - // If the step expression of a range-specification equals zero, the - // behavior is unspecified. - if (Result && Result->isZero()) { - Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero) - << Step << Step->getSourceRange(); - IsCorrect = false; - continue; - } - } - if (!Begin || !End || !IsCorrect) { - IsCorrect = false; - continue; - } - OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back(); - IDElem.IteratorDecl = VD; - IDElem.AssignmentLoc = D.AssignLoc; - IDElem.Range.Begin = Begin; - IDElem.Range.End = End; - IDElem.Range.Step = Step; - IDElem.ColonLoc = D.ColonLoc; - IDElem.SecondColonLoc = D.SecColonLoc; - } - if (!IsCorrect) { - // Invalidate all created iterator declarations if error is found. - for (const OMPIteratorExpr::IteratorDefinition &D : ID) { - if (Decl *ID = D.IteratorDecl) - ID->setInvalidDecl(); - } - return ExprError(); - } - SmallVector<OMPIteratorHelperData, 4> Helpers; - if (!CurContext->isDependentContext()) { - // Build number of ityeration for each iteration range. - // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) : - // ((Begini-Stepi-1-Endi) / -Stepi); - for (OMPIteratorExpr::IteratorDefinition &D : ID) { - // (Endi - Begini) - ExprResult Res = CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub, D.Range.End, - D.Range.Begin); - if(!Res.isUsable()) { - IsCorrect = false; - continue; - } - ExprResult St, St1; - if (D.Range.Step) { - St = D.Range.Step; - // (Endi - Begini) + Stepi - Res = CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(), St.get()); - if (!Res.isUsable()) { - IsCorrect = false; - continue; - } - // (Endi - Begini) + Stepi - 1 - Res = - CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub, Res.get(), - ActOnIntegerConstant(D.AssignmentLoc, 1).get()); - if (!Res.isUsable()) { - IsCorrect = false; - continue; - } - // ((Endi - Begini) + Stepi - 1) / Stepi - Res = CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(), St.get()); - if (!Res.isUsable()) { - IsCorrect = false; - continue; - } - St1 = CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus, D.Range.Step); - // (Begini - Endi) - ExprResult Res1 = CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub, - D.Range.Begin, D.Range.End); - if (!Res1.isUsable()) { - IsCorrect = false; - continue; - } - // (Begini - Endi) - Stepi - Res1 = - CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(), St1.get()); - if (!Res1.isUsable()) { - IsCorrect = false; - continue; - } - // (Begini - Endi) - Stepi - 1 - Res1 = - CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub, Res1.get(), - ActOnIntegerConstant(D.AssignmentLoc, 1).get()); - if (!Res1.isUsable()) { - IsCorrect = false; - continue; - } - // ((Begini - Endi) - Stepi - 1) / (-Stepi) - Res1 = - CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(), St1.get()); - if (!Res1.isUsable()) { - IsCorrect = false; - continue; - } - // Stepi > 0. - ExprResult CmpRes = - CreateBuiltinBinOp(D.AssignmentLoc, BO_GT, D.Range.Step, - ActOnIntegerConstant(D.AssignmentLoc, 0).get()); - if (!CmpRes.isUsable()) { - IsCorrect = false; - continue; - } - Res = ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc, CmpRes.get(), - Res.get(), Res1.get()); - if (!Res.isUsable()) { - IsCorrect = false; - continue; - } - } - Res = ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false); - if (!Res.isUsable()) { - IsCorrect = false; - continue; - } - - // Build counter update. - // Build counter. - auto *CounterVD = - VarDecl::Create(Context, CurContext, D.IteratorDecl->getBeginLoc(), - D.IteratorDecl->getBeginLoc(), nullptr, - Res.get()->getType(), nullptr, SC_None); - CounterVD->setImplicit(); - ExprResult RefRes = - BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue, - D.IteratorDecl->getBeginLoc()); - // Build counter update. - // I = Begini + counter * Stepi; - ExprResult UpdateRes; - if (D.Range.Step) { - UpdateRes = CreateBuiltinBinOp( - D.AssignmentLoc, BO_Mul, - DefaultLvalueConversion(RefRes.get()).get(), St.get()); - } else { - UpdateRes = DefaultLvalueConversion(RefRes.get()); - } - if (!UpdateRes.isUsable()) { - IsCorrect = false; - continue; - } - UpdateRes = CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, D.Range.Begin, - UpdateRes.get()); - if (!UpdateRes.isUsable()) { - IsCorrect = false; - continue; - } - ExprResult VDRes = - BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl), - cast<VarDecl>(D.IteratorDecl)->getType(), VK_LValue, - D.IteratorDecl->getBeginLoc()); - UpdateRes = CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign, VDRes.get(), - UpdateRes.get()); - if (!UpdateRes.isUsable()) { - IsCorrect = false; - continue; - } - UpdateRes = - ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true); - if (!UpdateRes.isUsable()) { - IsCorrect = false; - continue; - } - ExprResult CounterUpdateRes = - CreateBuiltinUnaryOp(D.AssignmentLoc, UO_PreInc, RefRes.get()); - if (!CounterUpdateRes.isUsable()) { - IsCorrect = false; - continue; - } - CounterUpdateRes = - ActOnFinishFullExpr(CounterUpdateRes.get(), /*DiscardedValue=*/true); - if (!CounterUpdateRes.isUsable()) { - IsCorrect = false; - continue; - } - OMPIteratorHelperData &HD = Helpers.emplace_back(); - HD.CounterVD = CounterVD; - HD.Upper = Res.get(); - HD.Update = UpdateRes.get(); - HD.CounterUpdate = CounterUpdateRes.get(); - } - } else { - Helpers.assign(ID.size(), {}); - } - if (!IsCorrect) { - // Invalidate all created iterator declarations if error is found. - for (const OMPIteratorExpr::IteratorDefinition &D : ID) { - if (Decl *ID = D.IteratorDecl) - ID->setInvalidDecl(); - } - return ExprError(); - } - return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc, - LLoc, RLoc, ID, Helpers); -} - ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc) { @@ -5911,7 +5106,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, } // Perform default conversions. - if (!LHSExp->getType()->getAs<VectorType>()) { + if (!LHSExp->getType()->isSubscriptableVectorType()) { ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp); if (Result.isInvalid()) return ExprError(); @@ -5947,8 +5142,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // Use custom logic if this should be the pseudo-object subscript // expression. if (!LangOpts.isSubscriptPointerArithmetic()) - return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, nullptr, - nullptr); + return ObjC().BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, + nullptr, nullptr); ResultType = PTy->getPointeeType(); } else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) { @@ -5967,36 +5162,22 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, << ResultType << BaseExpr->getSourceRange(); return ExprError(); } - } 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->isPRValue()) { - ExprResult Materialized = TemporaryMaterializationConversion(LHSExp); - if (Materialized.isInvalid()) - return ExprError(); - LHSExp = Materialized.get(); + } else if (LHSTy->isSubscriptableVectorType()) { + if (LHSTy->isBuiltinType() && + LHSTy->getAs<BuiltinType>()->isSveVLSBuiltinType()) { + const BuiltinType *BTy = LHSTy->getAs<BuiltinType>(); + if (BTy->isSVEBool()) + return ExprError(Diag(LLoc, diag::err_subscript_svbool_t) + << LHSExp->getSourceRange() + << RHSExp->getSourceRange()); + ResultType = BTy->getSveEltType(Context); + } else { + const VectorType *VTy = LHSTy->getAs<VectorType>(); + ResultType = VTy->getElementType(); } - VK = LHSExp->getValueKind(); - if (VK != VK_PRValue) - OK = OK_VectorComponent; - - 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->isBuiltinType() && - LHSTy->getAs<BuiltinType>()->isSveVLSBuiltinType()) { - const BuiltinType *BTy = LHSTy->getAs<BuiltinType>(); - if (BTy->isSVEBool()) - return ExprError(Diag(LLoc, diag::err_subscript_svbool_t) - << LHSExp->getSourceRange() << RHSExp->getSourceRange()); - - BaseExpr = LHSExp; + BaseExpr = LHSExp; // vectors: V[123] IndexExpr = RHSExp; + // We apply C++ DR1213 to vector subscripting too. if (getLangOpts().CPlusPlus11 && LHSExp->isPRValue()) { ExprResult Materialized = TemporaryMaterializationConversion(LHSExp); if (Materialized.isInvalid()) @@ -6007,8 +5188,6 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, if (VK != VK_PRValue) OK = OK_VectorComponent; - ResultType = BTy->getSveEltType(Context); - QualType BaseType = BaseExpr->getType(); Qualifiers BaseQuals = BaseType.getQualifiers(); Qualifiers MemberQuals = ResultType.getQualifiers(); @@ -6198,6 +5377,12 @@ struct ImmediateCallVisitor : public RecursiveASTVisitor<ImmediateCallVisitor> { return RecursiveASTVisitor<ImmediateCallVisitor>::VisitStmt(E); } + bool VisitCXXConstructExpr(CXXConstructExpr *E) { + if (const FunctionDecl *FD = E->getConstructor()) + HasImmediateCalls |= FD->isImmediateFunction(); + return RecursiveASTVisitor<ImmediateCallVisitor>::VisitStmt(E); + } + // SourceLocExpr are not immediate invocations // but CXXDefaultInitExpr/CXXDefaultArgExpr containing a SourceLocExpr // need to be rebuilt so that they refer to the correct SourceLocation and @@ -6217,12 +5402,6 @@ struct ImmediateCallVisitor : public RecursiveASTVisitor<ImmediateCallVisitor> { return VisitCXXMethodDecl(E->getCallOperator()); } - // Blocks don't support default parameters, and, as for lambdas, - // we don't consider their body a subexpression. - bool VisitBlockDecl(BlockDecl *B) { return false; } - - bool VisitCompoundStmt(CompoundStmt *B) { return false; } - bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { return TraverseStmt(E->getExpr()); } @@ -6248,6 +5427,28 @@ struct EnsureImmediateInvocationInDefaultArgs // cause it to incorrectly point it to the outermost class // in the case of nested struct initialization. ExprResult TransformCXXThisExpr(CXXThisExpr *E) { return E; } + + // Rewrite to source location to refer to the context in which they are used. + ExprResult TransformSourceLocExpr(SourceLocExpr *E) { + DeclContext *DC = E->getParentContext(); + if (DC == SemaRef.CurContext) + return E; + + // FIXME: During instantiation, because the rebuild of defaults arguments + // is not always done in the context of the template instantiator, + // we run the risk of producing a dependent source location + // that would never be rebuilt. + // This usually happens during overload resolution, or in contexts + // where the value of the source location does not matter. + // However, we should find a better way to deal with source location + // of function templates. + if (!SemaRef.CurrentInstantiationScope || + !SemaRef.CurContext->isDependentContext() || DC->isDependentContext()) + DC = SemaRef.CurContext; + + return getDerived().RebuildSourceLocExpr( + E->getIdentKind(), E->getType(), E->getBeginLoc(), E->getEndLoc(), DC); + } }; ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, @@ -6256,7 +5457,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, assert(Param->hasDefaultArg() && "can't build nonexistent default arg"); bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - + bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); std::optional<ExpressionEvaluationContextRecord::InitializationContext> InitializationContext = OutermostDeclarationWithDelayedImmediateInvocations(); @@ -6289,9 +5490,16 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Param); - if (V.HasImmediateCalls) { - ExprEvalContexts.back().DelayedDefaultInitializationContext = { - CallLoc, Param, CurContext}; + + // Rewrite the call argument that was created from the corresponding + // parameter's default argument. + if (V.HasImmediateCalls || InLifetimeExtendingContext) { + if (V.HasImmediateCalls) + ExprEvalContexts.back().DelayedDefaultInitializationContext = { + CallLoc, Param, CurContext}; + // Pass down lifetime extending flag, and collect temporaries in + // CreateMaterializeTemporaryExpr when we rewrite the call argument. + keepInLifetimeExtendingContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; runWithSufficientStackSpace(CallLoc, [&] { @@ -6522,12 +5730,26 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn, return TypoCorrection(); } -/// ConvertArgumentsForCall - Converts the arguments specified in -/// Args/NumArgs to the parameter types of the function FDecl with -/// function prototype Proto. Call is the call expression itself, and -/// Fn is the function expression. For a C++ member function, this -/// routine does not attempt to convert the object argument. Returns -/// true if the call is ill-formed. +// [C++26][[expr.unary.op]/p4 +// A pointer to member is only formed when an explicit & +// is used and its operand is a qualified-id not enclosed in parentheses. +static bool isParenthetizedAndQualifiedAddressOfExpr(Expr *Fn) { + if (!isa<ParenExpr>(Fn)) + return false; + + Fn = Fn->IgnoreParens(); + + auto *UO = dyn_cast<UnaryOperator>(Fn); + if (!UO || UO->getOpcode() != clang::UO_AddrOf) + return false; + if (auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) { + return DRE->hasQualifier(); + } + if (auto *OVL = dyn_cast<OverloadExpr>(UO->getSubExpr()->IgnoreParens())) + return OVL->getQualifier(); + return false; +} + bool Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FunctionDecl *FDecl, @@ -6543,8 +5765,10 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by // assignment, to the types of the corresponding parameter, ... + + bool AddressOf = isParenthetizedAndQualifiedAddressOfExpr(Fn); bool HasExplicitObjectParameter = - FDecl && FDecl->hasCXXExplicitFunctionObjectParameter(); + !AddressOf && FDecl && FDecl->hasCXXExplicitFunctionObjectParameter(); unsigned ExplicitObjectParameterOffset = HasExplicitObjectParameter ? 1 : 0; unsigned NumParams = Proto->getNumParams(); bool Invalid = false; @@ -6694,7 +5918,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, if (Arg->getType() == Context.ARCUnbridgedCastTy && FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() && (!Param || !Param->hasAttr<CFConsumedAttr>())) - Arg = stripARCUnbridgedCast(Arg); + Arg = ObjC().stripARCUnbridgedCast(Arg); else if (getLangOpts().ObjCAutoRefCount && FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() && (!Param || !Param->hasAttr<CFConsumedAttr>())) @@ -6780,14 +6004,6 @@ static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) { << ATL.getLocalSourceRange(); } -/// CheckStaticArrayArgument - If the given argument corresponds to a static -/// array parameter, check that it is non-null, and that if it is formed by -/// array-to-pointer decay, the underlying array is sufficiently large. -/// -/// C99 6.7.5.3p7: If the keyword static also appears within the [ and ] of the -/// array type derivation, then for each call to the function, the value of the -/// corresponding actual argument shall provide access to the first element of -/// an array with at least as many elements as specified by the size expression. void Sema::CheckStaticArrayArgument(SourceLocation CallLoc, ParmVarDecl *Param, @@ -6822,9 +6038,8 @@ Sema::CheckStaticArrayArgument(SourceLocation CallLoc, ArgCAT->getElementType())) { if (ArgCAT->getSize().ult(CAT->getSize())) { Diag(CallLoc, diag::warn_static_array_too_small) - << ArgExpr->getSourceRange() - << (unsigned)ArgCAT->getSize().getZExtValue() - << (unsigned)CAT->getSize().getZExtValue() << 0; + << ArgExpr->getSourceRange() << (unsigned)ArgCAT->getZExtSize() + << (unsigned)CAT->getZExtSize() << 0; DiagnoseCalleeStaticArrayParam(*this, Param); } return; @@ -6873,11 +6088,14 @@ static bool isPlaceholderToRemoveAsArg(QualType type) { #include "clang/Basic/RISCVVTypes.def" #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/WebAssemblyReferenceTypes.def" +#define AMDGPU_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/AMDGPUTypes.def" #define PLACEHOLDER_TYPE(ID, SINGLETON_ID) #define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: #include "clang/AST/BuiltinTypes.def" return false; + case BuiltinType::UnresolvedTemplate: // We cannot lower out overload sets; they might validly be resolved // by the call machinery. case BuiltinType::Overload: @@ -6901,7 +6119,7 @@ static bool isPlaceholderToRemoveAsArg(QualType type) { case BuiltinType::BoundMember: case BuiltinType::BuiltinFn: case BuiltinType::IncompleteMatrixIdx: - case BuiltinType::OMPArraySection: + case BuiltinType::ArraySection: case BuiltinType::OMPArrayShaping: case BuiltinType::OMPIterator: return true; @@ -7169,18 +6387,23 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, } if (LangOpts.OpenMP) - Call = ActOnOpenMPCall(Call, Scope, LParenLoc, ArgExprs, RParenLoc, - ExecConfig); + Call = OpenMP().ActOnOpenMPCall(Call, Scope, LParenLoc, ArgExprs, RParenLoc, + ExecConfig); if (LangOpts.CPlusPlus) { if (const auto *CE = dyn_cast<CallExpr>(Call.get())) DiagnosedUnqualifiedCallsToStdFunctions(*this, CE); + + // If we previously found that the id-expression of this call refers to a + // consteval function but the call is dependent, we should not treat is an + // an invalid immediate call. + if (auto *DRE = dyn_cast<DeclRefExpr>(Fn->IgnoreParens()); + DRE && Call.get()->isValueDependent()) { + currentEvaluationContext().ReferenceToConsteval.erase(DRE); + } } return Call; } -/// BuildCallExpr - Handle a call to Fn with the specified array of arguments. -/// This provides the location of the left/right parens and a list of comma -/// locations. ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig, bool IsExecConfig, @@ -7255,7 +6478,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, OverloadExpr::FindResult find = OverloadExpr::find(Fn); // We aren't supposed to apply this logic if there's an '&' involved. - if (!find.HasFormOfMemberPointer) { + if (!find.HasFormOfMemberPointer || find.IsAddressOfOperandWithParen) { if (Expr::hasAnyTypeDependentArguments(ArgExprs)) return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, VK_PRValue, RParenLoc, CurFPFeatureOverrides()); @@ -7323,7 +6546,8 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, // the parameter type. if (getLangOpts().HIP && getLangOpts().CUDAIsDevice && FD && FD->getBuiltinID()) { - for (unsigned Idx = 0; Idx < FD->param_size(); ++Idx) { + for (unsigned Idx = 0; Idx < ArgExprs.size() && Idx < FD->param_size(); + ++Idx) { ParmVarDecl *Param = FD->getParamDecl(Idx); if (!ArgExprs[Idx] || !Param || !Param->getType()->isPointerType() || !ArgExprs[Idx]->getType()->isPointerType()) @@ -7381,8 +6605,6 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, ExecConfig, IsExecConfig); } -/// BuildBuiltinCallExpr - Create a call to a builtin function specified by Id -// with the specified CallArgs Expr *Sema::BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, MultiExprArg CallArgs) { StringRef Name = Context.BuiltinInfo.getName(Id); @@ -7404,10 +6626,6 @@ Expr *Sema::BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, return Call.get(); } -/// Parse a __builtin_astype expression. -/// -/// __builtin_astype( value, dst type ) -/// ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc) { @@ -7415,7 +6633,6 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, return BuildAsTypeExpr(E, DstTy, BuiltinLoc, RParenLoc); } -/// Create a new AsTypeExpr node (bitcast) from the arguments. ExprResult Sema::BuildAsTypeExpr(Expr *E, QualType DestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc) { @@ -7430,25 +6647,14 @@ ExprResult Sema::BuildAsTypeExpr(Expr *E, QualType DestTy, return new (Context) AsTypeExpr(E, DestTy, VK, OK, BuiltinLoc, RParenLoc); } -/// ActOnConvertVectorExpr - create a new convert-vector expression from the -/// provided arguments. -/// -/// __builtin_convertvector( value, dst type ) -/// ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc) { TypeSourceInfo *TInfo; GetTypeFromParser(ParsedDestTy, &TInfo); - return SemaConvertVectorExpr(E, TInfo, BuiltinLoc, RParenLoc); + return ConvertVectorExpr(E, TInfo, BuiltinLoc, RParenLoc); } -/// BuildResolvedCallExpr - Build a call to a resolved expression, -/// i.e. an expression not of \p OverloadTy. The expression should -/// unary-convert to an expression of function-pointer or -/// block-pointer type. -/// -/// \param NDecl the declaration being called, if available ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, ArrayRef<Expr *> Args, @@ -7458,27 +6664,21 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); // Functions with 'interrupt' attribute cannot be called directly. - if (FDecl && FDecl->hasAttr<AnyX86InterruptAttr>()) { - Diag(Fn->getExprLoc(), diag::err_anyx86_interrupt_called); - return ExprError(); + if (FDecl) { + if (FDecl->hasAttr<AnyX86InterruptAttr>()) { + Diag(Fn->getExprLoc(), diag::err_anyx86_interrupt_called); + return ExprError(); + } + if (FDecl->hasAttr<ARMInterruptAttr>()) { + Diag(Fn->getExprLoc(), diag::err_arm_interrupt_called); + return ExprError(); + } } - // Interrupt handlers don't save off the VFP regs automatically on ARM, - // so there's some risk when calling out to non-interrupt handler functions - // that the callee might not preserve them. This is easy to diagnose here, - // but can be very challenging to debug. - // Likewise, X86 interrupt handlers may only call routines with attribute + // X86 interrupt handlers may only call routines with attribute // no_caller_saved_registers since there is no efficient way to // save and restore the non-GPR state. if (auto *Caller = getCurFunctionDecl()) { - if (Caller->hasAttr<ARMInterruptAttr>()) { - bool VFP = Context.getTargetInfo().hasFeature("vfp"); - if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>())) { - Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_calling_convention); - if (FDecl) - Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl; - } - } if (Caller->hasAttr<AnyX86InterruptAttr>() || Caller->hasAttr<AnyX86NoCallerSavedRegistersAttr>()) { const TargetInfo &TI = Context.getTargetInfo(); @@ -7504,7 +6704,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Extract the return type from the (builtin) function pointer type. // FIXME Several builtins still have setType in // Sema::CheckBuiltinFunctionCall. One should review their definitions in - // Builtins.def to ensure they are correct before removing setType calls. + // Builtins.td to ensure they are correct before removing setType calls. QualType FnPtrTy = Context.getPointerType(FDecl->getType()); Result = ImpCastExprToType(Fn, FnPtrTy, CK_BuiltinFnToFnPtr).get(); ResultTy = FDecl->getCallResultType(); @@ -7601,8 +6801,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } // Bail out early if calling a builtin with custom type checking. - if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) - return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall); + if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) { + ExprResult E = CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall); + if (!E.isInvalid() && Context.BuiltinInfo.isImmediate(BuiltinID)) + E = CheckForImmediateInvocation(E, FDecl); + return E; + } if (getLangOpts().CUDA) { if (Config) { @@ -7794,12 +6998,19 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, // init a VLA in C++ in all cases (such as with non-trivial constructors). // FIXME: should we allow this construct in C++ when it makes sense to do // so? - std::optional<unsigned> NumInits; - if (const auto *ILE = dyn_cast<InitListExpr>(LiteralExpr)) - NumInits = ILE->getNumInits(); - if ((LangOpts.CPlusPlus || NumInits.value_or(0)) && - !tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc, - diag::err_variable_object_no_init)) + // + // But: C99-C23 6.5.2.5 Compound literals constraint 1: The type name + // shall specify an object type or an array of unknown size, but not a + // variable length array type. This seems odd, as it allows 'int a[size] = + // {}', but forbids 'int *a = (int[size]){}'. As this is what the standard + // says, this is what's implemented here for C (except for the extension + // that permits constant foldable size arrays) + + auto diagID = LangOpts.CPlusPlus + ? diag::err_variable_object_no_init + : diag::err_compound_literal_with_vla_type; + if (!tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc, + diagID)) return ExprError(); } } else if (!literalType->isDependentType() && @@ -7859,7 +7070,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, if (!LiteralExpr->isTypeDependent() && !LiteralExpr->isValueDependent() && !literalType->isDependentType()) // C99 6.5.2.5p3 - if (CheckForConstantInitializer(LiteralExpr, literalType)) + if (CheckForConstantInitializer(LiteralExpr)) return ExprError(); } else if (literalType.getAddressSpace() != LangAS::opencl_private && literalType.getAddressSpace() != LangAS::Default) { @@ -7985,13 +7196,12 @@ Sema::BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, } } - InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitArgList, - RBraceLoc); + InitListExpr *E = + new (Context) InitListExpr(Context, LBraceLoc, InitArgList, RBraceLoc); E->setType(Context.VoidTy); // FIXME: just a place holder for now. return E; } -/// Do an explicit extend of the given block pointer if we're in ARC. void Sema::maybeExtendBlockObject(ExprResult &E) { assert(E.get()->getType()->isBlockPointerType()); assert(E.get()->isPRValue()); @@ -8005,23 +7215,6 @@ void Sema::maybeExtendBlockObject(ExprResult &E) { Cleanup.setExprNeedsCleanups(true); } -/// Prepare a conversion of the given expression to an ObjC object -/// pointer type. -CastKind Sema::PrepareCastToObjCObjectPointer(ExprResult &E) { - QualType type = E.get()->getType(); - if (type->isObjCObjectPointerType()) { - return CK_BitCast; - } else if (type->isBlockPointerType()) { - maybeExtendBlockObject(E); - return CK_BlockPointerToObjCPointerCast; - } else { - assert(type->isPointerType()); - return CK_CPointerToObjCPointerCast; - } -} - -/// Prepares for a scalar cast, performing all the necessary stages -/// except the final cast and returning the kind required. CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { // Both Src and Dest are scalar types, i.e. arithmetic or pointer. // Also, callers should have filtered out the invalid cases with @@ -8248,12 +7441,6 @@ static bool breakDownVectorType(QualType type, uint64_t &len, return true; } -/// Are the two types SVE-bitcast-compatible types? I.e. is bitcasting from the -/// first SVE type (e.g. an SVE VLAT) to the second type (e.g. an SVE VLST) -/// allowed? -/// -/// This will also return false if the two given types do not make sense from -/// the perspective of SVE bitcasts. bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) { assert(srcTy->isVectorType() || destTy->isVectorType()); @@ -8269,29 +7456,6 @@ bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) { ValidScalableConversion(destTy, srcTy); } -/// Are the two types RVV-bitcast-compatible types? I.e. is bitcasting from the -/// first RVV type (e.g. an RVV scalable type) to the second type (e.g. an RVV -/// VLS type) allowed? -/// -/// This will also return false if the two given types do not make sense from -/// the perspective of RVV bitcasts. -bool Sema::isValidRVVBitcast(QualType srcTy, QualType destTy) { - assert(srcTy->isVectorType() || destTy->isVectorType()); - - auto ValidScalableConversion = [](QualType FirstType, QualType SecondType) { - if (!FirstType->isRVVSizelessBuiltinType()) - return false; - - const auto *VecTy = SecondType->getAs<VectorType>(); - return VecTy && VecTy->getVectorKind() == VectorKind::RVVFixedLengthData; - }; - - return ValidScalableConversion(srcTy, destTy) || - ValidScalableConversion(destTy, srcTy); -} - -/// Are the two types matrix types and do they have the same dimensions i.e. -/// do they have the same number of rows and the same number of columns? bool Sema::areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy) { if (!destTy->isMatrixType() || !srcTy->isMatrixType()) return false; @@ -8322,7 +7486,6 @@ bool Sema::areVectorTypesSameSize(QualType SrcTy, QualType DestTy) { return (SrcLen * SrcEltSize == DestLen * DestEltSize); } -// This returns true if at least one of the types is an altivec vector. bool Sema::anyAltivecTypes(QualType SrcTy, QualType DestTy) { assert((DestTy->isVectorType() || SrcTy->isVectorType()) && "expected at least one type to be a vector here"); @@ -8346,13 +7509,6 @@ bool Sema::anyAltivecTypes(QualType SrcTy, QualType DestTy) { return (IsSrcTyAltivec || IsDestTyAltivec); } -/// Are the two types lax-compatible vector types? That is, given -/// that one of them is a vector, do they have equal storage sizes, -/// where the storage size is the number of elements times the element -/// size? -/// -/// This will also return false if either of the types is neither a -/// vector nor a real type. bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) { assert(destTy->isVectorType() || srcTy->isVectorType()); @@ -8367,8 +7523,6 @@ bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) { return areVectorTypesSameSize(srcTy, destTy); } -/// Is this a legal conversion between two types, one of which is -/// known to be a vector type? bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) { assert(destTy->isVectorType() || srcTy->isVectorType()); @@ -8570,9 +7724,9 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, if (getLangOpts().CPlusPlus && !castType->isVoidType()) Diag(LParenLoc, diag::warn_old_style_cast) << CastExpr->getSourceRange(); - CheckTollFreeBridgeCast(castType, CastExpr); + ObjC().CheckTollFreeBridgeCast(castType, CastExpr); - CheckObjCBridgeRelatedCast(castType, CastExpr); + ObjC().CheckObjCBridgeRelatedCast(castType, CastExpr); DiscardMisalignedMemberAddress(castType.getTypePtr(), CastExpr); @@ -8661,8 +7815,6 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE); } -/// This is not an AltiVec-style cast or or C++ direct-initialization, so turn -/// the ParenListExpr into a sequence of comma binary operators. ExprResult Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) { ParenListExpr *E = dyn_cast<ParenListExpr>(OrigExpr); @@ -8686,9 +7838,6 @@ ExprResult Sema::ActOnParenListExpr(SourceLocation L, return ParenListExpr::Create(Context, L, Val, R); } -/// 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(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation QuestionLoc) { const Expr *NullExpr = LHSExpr; @@ -9322,8 +8471,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, if (!checkConditionalNullPointer(*this, LHS, RHSTy)) return RHSTy; // All objective-c pointer type analysis is done here. - QualType compositeType = FindCompositeObjCPointerType(LHS, RHS, - QuestionLoc); + QualType compositeType = + ObjC().FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); if (!compositeType.isNull()) @@ -9367,148 +8516,6 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, return QualType(); } -/// FindCompositeObjCPointerType - Helper method to find composite type of -/// two objective-c pointer types of the two input expressions. -QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, - SourceLocation QuestionLoc) { - QualType LHSTy = LHS.get()->getType(); - QualType RHSTy = RHS.get()->getType(); - - // Handle things like Class and struct objc_class*. Here we case the result - // to the pseudo-builtin, because that will be implicitly cast back to the - // redefinition type if an attempt is made to access its fields. - if (LHSTy->isObjCClassType() && - (Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) { - RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_CPointerToObjCPointerCast); - return LHSTy; - } - if (RHSTy->isObjCClassType() && - (Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) { - LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_CPointerToObjCPointerCast); - return RHSTy; - } - // And the same for struct objc_object* / id - if (LHSTy->isObjCIdType() && - (Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) { - RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_CPointerToObjCPointerCast); - return LHSTy; - } - if (RHSTy->isObjCIdType() && - (Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) { - LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_CPointerToObjCPointerCast); - return RHSTy; - } - // And the same for struct objc_selector* / SEL - if (Context.isObjCSelType(LHSTy) && - (Context.hasSameType(RHSTy, Context.getObjCSelRedefinitionType()))) { - RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_BitCast); - return LHSTy; - } - if (Context.isObjCSelType(RHSTy) && - (Context.hasSameType(LHSTy, Context.getObjCSelRedefinitionType()))) { - LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_BitCast); - return RHSTy; - } - // Check constraints for Objective-C object pointers types. - if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) { - - if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { - // Two identical object pointer types are always compatible. - return LHSTy; - } - const ObjCObjectPointerType *LHSOPT = LHSTy->castAs<ObjCObjectPointerType>(); - const ObjCObjectPointerType *RHSOPT = RHSTy->castAs<ObjCObjectPointerType>(); - QualType compositeType = LHSTy; - - // If both operands are interfaces and either operand can be - // assigned to the other, use that type as the composite - // type. This allows - // xxx ? (A*) a : (B*) b - // where B is a subclass of A. - // - // Additionally, as for assignment, if either type is 'id' - // allow silent coercion. Finally, if the types are - // incompatible then make sure to use 'id' as the composite - // type so the result is acceptable for sending messages to. - - // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. - // It could return the composite type. - if (!(compositeType = - Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) { - // Nothing more to do. - } else if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) { - compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy; - } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) { - compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy; - } else if ((LHSOPT->isObjCQualifiedIdType() || - RHSOPT->isObjCQualifiedIdType()) && - Context.ObjCQualifiedIdTypesAreCompatible(LHSOPT, RHSOPT, - true)) { - // Need to handle "id<xx>" explicitly. - // GCC allows qualified id and any Objective-C type to devolve to - // id. Currently localizing to here until clear this should be - // part of ObjCQualifiedIdTypesAreCompatible. - compositeType = Context.getObjCIdType(); - } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) { - compositeType = Context.getObjCIdType(); - } else { - Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy - << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); - QualType incompatTy = Context.getObjCIdType(); - LHS = ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast); - RHS = ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast); - return incompatTy; - } - // The object pointer types are compatible. - LHS = ImpCastExprToType(LHS.get(), compositeType, CK_BitCast); - RHS = ImpCastExprToType(RHS.get(), compositeType, CK_BitCast); - return compositeType; - } - // Check Objective-C object pointer types and 'void *' - if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { - if (getLangOpts().ObjCAutoRefCount) { - // ARC forbids the implicit conversion of object pointers to 'void *', - // so these types are not compatible. - Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy - << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); - LHS = RHS = true; - return QualType(); - } - QualType lhptee = LHSTy->castAs<PointerType>()->getPointeeType(); - QualType rhptee = RHSTy->castAs<ObjCObjectPointerType>()->getPointeeType(); - QualType destPointee - = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); - QualType destType = Context.getPointerType(destPointee); - // Add qualifiers if necessary. - LHS = ImpCastExprToType(LHS.get(), destType, CK_NoOp); - // Promote to void*. - RHS = ImpCastExprToType(RHS.get(), destType, CK_BitCast); - return destType; - } - if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { - if (getLangOpts().ObjCAutoRefCount) { - // ARC forbids the implicit conversion of object pointers to 'void *', - // so these types are not compatible. - Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy - << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); - LHS = RHS = true; - return QualType(); - } - QualType lhptee = LHSTy->castAs<ObjCObjectPointerType>()->getPointeeType(); - QualType rhptee = RHSTy->castAs<PointerType>()->getPointeeType(); - QualType destPointee - = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); - QualType destType = Context.getPointerType(destPointee); - // Add qualifiers if necessary. - RHS = ImpCastExprToType(RHS.get(), destType, CK_NoOp); - // Promote to void*. - LHS = ImpCastExprToType(LHS.get(), destType, CK_BitCast); - return destType; - } - return QualType(); -} - /// SuggestParentheses - Emit a note with a fixit hint that wraps /// ParenRange in parentheses. static void SuggestParentheses(Sema &Self, SourceLocation Loc, @@ -9693,8 +8700,6 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin, return Ctx.getAttributedType(NewAttr, ResTy, ResTy); } -/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null -/// in the case of a the GNU conditional expr extension. ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, @@ -9798,7 +8803,6 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, ColonLoc, result, VK, OK); } -// Check that the SME attributes for PSTATE.ZA and PSTATE.SM are compatible. bool Sema::IsInvalidSMECallConversion(QualType FromType, QualType ToType) { unsigned FromAttributes = 0, ToAttributes = 0; if (const auto *FromFn = @@ -10373,7 +9377,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, checkObjCPointerTypesForAssignment(*this, LHSType, RHSType); if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && result == Compatible && - !CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType)) + !ObjC().CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType)) result = IncompatibleObjCWeakRef; return result; } @@ -10599,7 +9603,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, return Incompatible; Sema::AssignConvertType result = Compatible; if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - !CheckObjCARCUnavailableWeakConversion(LHSType, RHSType)) + !ObjC().CheckObjCARCUnavailableWeakConversion(LHSType, RHSType)) result = IncompatibleObjCWeakRef; return result; } @@ -10705,15 +9709,16 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, // diagnostics and just checking for errors, e.g., during overload // resolution, return Incompatible to indicate the failure. if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - CheckObjCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion, - Diagnose, DiagnoseCFAudited) != ACR_okay) { + ObjC().CheckObjCConversion(SourceRange(), Ty, E, + CheckedConversionKind::Implicit, Diagnose, + DiagnoseCFAudited) != SemaObjC::ACR_okay) { if (!Diagnose) return Incompatible; } if (getLangOpts().ObjC && - (CheckObjCBridgeRelatedConversions(E->getBeginLoc(), LHSType, - E->getType(), E, Diagnose) || - CheckConversionToObjCLiteral(LHSType, E, Diagnose))) { + (ObjC().CheckObjCBridgeRelatedConversions(E->getBeginLoc(), LHSType, + E->getType(), E, Diagnose) || + ObjC().CheckConversionToObjCLiteral(LHSType, E, Diagnose))) { if (!Diagnose) return Incompatible; // Replace the expression with a corrected version and continue so we @@ -10776,9 +9781,6 @@ QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, return QualType(); } -// Diagnose cases where a scalar was implicitly converted to a vector and -// diagnose the underlying types. Otherwise, diagnose the error -// as invalid vector logical operands for non-C++ cases. QualType Sema::InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, ExprResult &RHS) { QualType LHSType = LHS.get()->IgnoreImpCasts()->getType(); @@ -11647,7 +10649,7 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>()) ResType = ResAtomicType->getValueType(); - assert(ResType->isAnyPointerType() && !ResType->isDependentType()); + assert(ResType->isAnyPointerType()); QualType PointeeTy = ResType->getPointeeType(); return S.RequireCompleteSizedType( Loc, PointeeTy, @@ -11937,6 +10939,14 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS, if (isObjCPointer && checkArithmeticOnObjCPointer(*this, Loc, PExp)) return QualType(); + // Arithmetic on label addresses is normally allowed, except when we add + // a ptrauth signature to the addresses. + if (isa<AddrLabelExpr>(PExp) && getLangOpts().PointerAuthIndirectGotos) { + Diag(Loc, diag::err_ptrauth_indirect_goto_addrlabel_arithmetic) + << /*addition*/ 1; + return QualType(); + } + // Check array bounds for pointer arithemtic CheckArrayAccess(PExp, IExp); @@ -12011,6 +11021,15 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, checkArithmeticOnObjCPointer(*this, Loc, LHS.get())) return QualType(); + // Arithmetic on label addresses is normally allowed, except when we add + // a ptrauth signature to the addresses. + if (isa<AddrLabelExpr>(LHS.get()) && + getLangOpts().PointerAuthIndirectGotos) { + Diag(Loc, diag::err_ptrauth_indirect_goto_addrlabel_arithmetic) + << /*subtraction*/ 0; + return QualType(); + } + // The result type of a pointer-int computation is the pointer type. if (RHS.get()->getType()->isIntegerType()) { // Subtracting from a null pointer should produce a warning. @@ -12118,7 +11137,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, if (Right.isNegative()) { S.DiagRuntimeBehavior(Loc, RHS.get(), S.PDiag(diag::warn_shift_negative) - << RHS.get()->getSourceRange()); + << RHS.get()->getSourceRange()); return; } @@ -12133,7 +11152,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, if (Right.uge(LeftSize)) { S.DiagRuntimeBehavior(Loc, RHS.get(), S.PDiag(diag::warn_shift_gt_typewidth) - << RHS.get()->getSourceRange()); + << RHS.get()->getSourceRange()); return; } @@ -12166,7 +11185,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, if (Left.isNegative()) { S.DiagRuntimeBehavior(Loc, LHS.get(), S.PDiag(diag::warn_shift_lhs_negative) - << LHS.get()->getSourceRange()); + << LHS.get()->getSourceRange()); return; } @@ -12530,19 +11549,20 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { return false; // Try to find the -isEqual: method. - Selector IsEqualSel = S.NSAPIObj->getIsEqualSelector(); - ObjCMethodDecl *Method = S.LookupMethodInObjectType(IsEqualSel, - InterfaceType, - /*IsInstance=*/true); + Selector IsEqualSel = S.ObjC().NSAPIObj->getIsEqualSelector(); + ObjCMethodDecl *Method = + S.ObjC().LookupMethodInObjectType(IsEqualSel, InterfaceType, + /*IsInstance=*/true); if (!Method) { if (Type->isObjCIdType()) { // For 'id', just check the global pool. - Method = S.LookupInstanceMethodInGlobalPool(IsEqualSel, SourceRange(), - /*receiverId=*/true); + Method = + S.ObjC().LookupInstanceMethodInGlobalPool(IsEqualSel, SourceRange(), + /*receiverId=*/true); } else { // Check protocols. - Method = S.LookupMethodInQualifiedType(IsEqualSel, Type, - /*IsInstance=*/true); + Method = S.ObjC().LookupMethodInQualifiedType(IsEqualSel, Type, + /*IsInstance=*/true); } } @@ -12560,48 +11580,6 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { return true; } -Sema::ObjCLiteralKind Sema::CheckLiteralKind(Expr *FromE) { - FromE = FromE->IgnoreParenImpCasts(); - switch (FromE->getStmtClass()) { - default: - break; - case Stmt::ObjCStringLiteralClass: - // "string literal" - return LK_String; - case Stmt::ObjCArrayLiteralClass: - // "array literal" - return LK_Array; - case Stmt::ObjCDictionaryLiteralClass: - // "dictionary literal" - return LK_Dictionary; - case Stmt::BlockExprClass: - return LK_Block; - case Stmt::ObjCBoxedExprClass: { - Expr *Inner = cast<ObjCBoxedExpr>(FromE)->getSubExpr()->IgnoreParens(); - switch (Inner->getStmtClass()) { - case Stmt::IntegerLiteralClass: - case Stmt::FloatingLiteralClass: - case Stmt::CharacterLiteralClass: - case Stmt::ObjCBoolLiteralExprClass: - case Stmt::CXXBoolLiteralExprClass: - // "numeric literal" - return LK_Numeric; - case Stmt::ImplicitCastExprClass: { - CastKind CK = cast<CastExpr>(Inner)->getCastKind(); - // Boolean literals can be represented by implicit casts. - if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast) - return LK_Numeric; - break; - } - default: - break; - } - return LK_Boxed; - } - } - return LK_None; -} - static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, ExprResult &LHS, ExprResult &RHS, BinaryOperator::Opcode Opc){ @@ -12624,13 +11602,13 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, // This should be kept in sync with warn_objc_literal_comparison. // LK_String should always be after the other literals, since it has its own // warning flag. - Sema::ObjCLiteralKind LiteralKind = S.CheckLiteralKind(Literal); - assert(LiteralKind != Sema::LK_Block); - if (LiteralKind == Sema::LK_None) { + SemaObjC::ObjCLiteralKind LiteralKind = S.ObjC().CheckLiteralKind(Literal); + assert(LiteralKind != SemaObjC::LK_Block); + if (LiteralKind == SemaObjC::LK_None) { llvm_unreachable("Unknown Objective-C object literal kind"); } - if (LiteralKind == Sema::LK_String) + if (LiteralKind == SemaObjC::LK_String) S.Diag(Loc, diag::warn_objc_string_literal_comparison) << Literal->getSourceRange(); else @@ -12874,6 +11852,8 @@ static ImplicitConversionKind castKindToImplicitConversionKind(CastKind CK) { case CK_IntegralComplexToReal: case CK_IntegralRealToComplex: return ICK_Complex_Real; + case CK_HLSLArrayRValue: + return ICK_HLSL_Array_RValue; } } @@ -13424,17 +12404,18 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, if (LHSIsNull && !RHSIsNull) { Expr *E = LHS.get(); if (getLangOpts().ObjCAutoRefCount) - CheckObjCConversion(SourceRange(), RHSType, E, - CCK_ImplicitConversion); + ObjC().CheckObjCConversion(SourceRange(), RHSType, E, + CheckedConversionKind::Implicit); LHS = ImpCastExprToType(E, RHSType, RPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } else { Expr *E = RHS.get(); if (getLangOpts().ObjCAutoRefCount) - CheckObjCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion, - /*Diagnose=*/true, - /*DiagnoseCFAudited=*/false, Opc); + ObjC().CheckObjCConversion(SourceRange(), LHSType, E, + CheckedConversionKind::Implicit, + /*Diagnose=*/true, + /*DiagnoseCFAudited=*/false, Opc); RHS = ImpCastExprToType(E, LHSType, LPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } @@ -13543,11 +12524,6 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return InvalidOperands(Loc, LHS, RHS); } -// Return a signed ext_vector_type that is of identical size and number of -// elements. For floating point vectors, return an integer type of identical -// size and number of elements. In the non ext_vector_type case, search from -// the largest type to the smallest type to avoid cases where long long == long, -// where long gets picked over long long. QualType Sema::GetSignedVectorType(QualType V) { const VectorType *VTy = V->castAs<VectorType>(); unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); @@ -13603,10 +12579,6 @@ QualType Sema::GetSignedSizelessVectorType(QualType V) { return Context.getScalableVectorType(IntTy, VecSize.getKnownMinValue()); } -/// CheckVectorCompareOperands - vector comparisons are a clang extension that -/// operates on extended vector types. Instead of producing an IntTy result, -/// like a scalar comparison, a vector comparison produces a vector of integer -/// types. QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc) { @@ -14645,7 +13617,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, const Expr *InnerLHS = LHSExpr->IgnoreParenCasts(); const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InnerLHS); if (!DRE || DRE->getDecl()->hasAttr<BlocksAttr>()) - checkRetainCycles(LHSExpr, RHS.get()); + ObjC().checkRetainCycles(LHSExpr, RHS.get()); } if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong || @@ -14678,6 +13650,9 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, CheckForNullPointerDereference(*this, LHSExpr); + AssignedEntity AE{LHSExpr}; + checkExprLifetime(*this, AE, RHS.get()); + if (getLangOpts().CPlusPlus20 && LHSType.isVolatileQualified()) { if (CompoundType.isNull()) { // C++2a [expr.ass]p5: @@ -14722,9 +13697,6 @@ static bool IgnoreCommaOperand(const Expr *E, const ASTContext &Context) { return false; } -// Look for instances where it is likely the comma operator is confused with -// another operator. There is an explicit list of acceptable expressions for -// the left hand side of the comma operator, otherwise emit a warning. void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) { // No warnings in macros if (Loc.isMacroID()) @@ -14813,11 +13785,8 @@ static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS, static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, ExprValueKind &VK, ExprObjectKind &OK, - SourceLocation OpLoc, - bool IsInc, bool IsPrefix) { - if (Op->isTypeDependent()) - return S.Context.DependentTy; - + SourceLocation OpLoc, bool IsInc, + bool IsPrefix) { QualType ResType = Op->getType(); // Atomic types can be used for increment / decrement where the non-atomic // versions can, so ignore the _Atomic() specifier for the purpose of @@ -14855,8 +13824,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, 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) - << ResType << Op->getSourceRange(); + S.Diag(OpLoc, S.getLangOpts().C2y ? diag::warn_c2y_compat_increment_complex + : diag::ext_c2y_increment_complex) + << IsInc << Op->getSourceRange(); } else if (ResType->isPlaceholderType()) { ExprResult PR = S.CheckPlaceholderExpr(Op); if (PR.isInvalid()) return QualType(); @@ -14899,7 +13869,6 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, } } - /// getPrimaryDecl - Helper function for CheckAddressOfOperand(). /// This routine allows us to typecheck complex/recursive expressions /// where the declaration is needed for type checking. We only need to @@ -15008,13 +13977,6 @@ bool Sema::CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc, << FixItHint::CreateInsertion(DRE->getSourceRange().getBegin(), Qual); } -/// CheckAddressOfOperand - The operand of & must be either a function -/// designator or an lvalue designating an object. If it is an lvalue, the -/// object cannot be declared with storage class register or be a bit field. -/// Note: The usual conversions are *not* applied to the operand of the & -/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue. -/// In C++, the operand might be an overloaded function name, in which case -/// we allow the '&' but retain the overloaded-function type. QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){ if (PTy->getKind() == BuiltinType::Overload) { @@ -15121,6 +14083,39 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { QualType MPTy = Context.getMemberPointerType( op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr()); + + if (getLangOpts().PointerAuthCalls && MD->isVirtual() && + !isUnevaluatedContext() && !MPTy->isDependentType()) { + // When pointer authentication is enabled, argument and return types of + // vitual member functions must be complete. This is because vitrual + // member function pointers are implemented using virtual dispatch + // thunks and the thunks cannot be emitted if the argument or return + // types are incomplete. + auto ReturnOrParamTypeIsIncomplete = [&](QualType T, + SourceLocation DeclRefLoc, + SourceLocation RetArgTypeLoc) { + if (RequireCompleteType(DeclRefLoc, T, diag::err_incomplete_type)) { + Diag(DeclRefLoc, + diag::note_ptrauth_virtual_function_pointer_incomplete_arg_ret); + Diag(RetArgTypeLoc, + diag::note_ptrauth_virtual_function_incomplete_arg_ret_type) + << T; + return true; + } + return false; + }; + QualType RetTy = MD->getReturnType(); + bool IsIncomplete = + !RetTy->isVoidType() && + ReturnOrParamTypeIsIncomplete( + RetTy, OpLoc, MD->getReturnTypeSourceRange().getBegin()); + for (auto *PVD : MD->parameters()) + IsIncomplete |= ReturnOrParamTypeIsIncomplete(PVD->getType(), OpLoc, + PVD->getBeginLoc()); + if (IsIncomplete) + return QualType(); + } + // Under the MS ABI, lock down the inheritance model now. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) (void)isCompleteType(OpLoc, MPTy); @@ -15169,7 +14164,14 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { // Okay: we can take the address of a field. // Could be a pointer to member, though, if there is an explicit // scope qualifier for the class. - if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) { + + // [C++26] [expr.prim.id.general] + // If an id-expression E denotes a non-static non-type member + // of some class C [...] and if E is a qualified-id, E is + // not the un-parenthesized operand of the unary & operator [...] + // the id-expression is transformed into a class member access expression. + if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() && + !isa<ParenExpr>(OrigOp.get())) { DeclContext *Ctx = dcl->getDeclContext(); if (Ctx && Ctx->isRecord()) { if (dcl->getType()->isReferenceType()) { @@ -15253,9 +14255,6 @@ static void RecordModifiableNonNullParam(Sema &S, const Expr *Exp) { static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, SourceLocation OpLoc, bool IsAfterAmp = false) { - if (Op->isTypeDependent()) - return S.Context.DependentTy; - ExprResult ConvResult = S.UsualUnaryConversions(Op); if (ConvResult.isInvalid()) return QualType(); @@ -15587,9 +14586,6 @@ static bool needsConversionOfHalfVec(bool OpRequiresConversion, ASTContext &Ctx, return HasVectorOfHalfType(E0) && (!E1 || HasVectorOfHalfType(E1)); } -/// CreateBuiltinBinOp - Creates a new built-in binary operation with -/// operator @p Opc at location @c TokLoc. This routine only supports -/// built-in operations; ActOnBinOp handles overloaded operators. ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr) { @@ -15721,6 +14717,11 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, case BO_GT: ConvertHalfVec = true; ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc); + + if (const auto *BI = dyn_cast<BinaryOperator>(LHSExpr); + BI && BI->isComparisonOp()) + Diag(OpLoc, diag::warn_consecutive_comparison); + break; case BO_EQ: case BO_NE: @@ -16057,7 +15058,6 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, DiagnoseShiftCompare(Self, OpLoc, LHSExpr, RHSExpr); } -// Binary Operators. 'Tok' is the token for the operator. ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr) { @@ -16131,7 +15131,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, LHSExpr = LHS.get(); RHSExpr = RHS.get(); - // We want to end up calling one of checkPseudoObjectAssignment + // We want to end up calling one of SemaPseudoObject::checkAssignment // (if the LHS is a pseudo-object), BuildOverloadedBinOp (if // both expressions are overloadable or either is type-dependent), // or CreateBuiltinBinOp (in any other case). We also want to get @@ -16142,7 +15142,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, // Assignments with a pseudo-object l-value need special analysis. if (pty->getKind() == BuiltinType::PseudoObject && BinaryOperator::isAssignmentOp(Opc)) - return checkPseudoObjectAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr); + return PseudoObject().checkAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr); // Don't resolve overloads if the other type is overloadable. if (getLangOpts().CPlusPlus && pty->getKind() == BuiltinType::Overload) { @@ -16211,14 +15211,10 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, } if (getLangOpts().CPlusPlus) { - // If either expression is type-dependent, always build an - // overloaded op. - if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) - return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); - - // Otherwise, build an overloaded op if either expression has an - // overloadable type. - if (LHSExpr->getType()->isOverloadableType() || + // Otherwise, build an overloaded op if either expression is type-dependent + // or has an overloadable type. + if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent() || + LHSExpr->getType()->isOverloadableType() || RHSExpr->getType()->isOverloadableType()) return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); } @@ -16309,188 +15305,191 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 1); } - switch (Opc) { - case UO_PreInc: - case UO_PreDec: - case UO_PostInc: - case UO_PostDec: - resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, - OpLoc, - Opc == UO_PreInc || - Opc == UO_PostInc, - Opc == UO_PreInc || - Opc == UO_PreDec); - CanOverflow = isOverflowingIntegerType(Context, resultType); - break; - case UO_AddrOf: - resultType = CheckAddressOfOperand(Input, OpLoc); - CheckAddressOfNoDeref(InputExpr); - RecordModifiableNonNullParam(*this, InputExpr); - break; - case UO_Deref: { - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) return ExprError(); - resultType = - CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); - break; - } - 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 - // float vector and truncating the result back to a half vector. For now, we - // do this only when HalfArgsAndReturns is set (that is, when the target is - // arm or arm64). - ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); - - // If the operand is a half vector, promote it to a float vector. - if (ConvertHalfVec) - Input = convertVector(Input.get(), Context.FloatTy, *this); - resultType = Input.get()->getType(); - if (resultType->isDependentType()) - break; - if (resultType->isArithmeticType()) // C99 6.5.3.3p1 - break; - else if (resultType->isVectorType() && - // The z vector extensions don't allow + or - with bool vectors. - (!Context.getLangOpts().ZVector || - resultType->castAs<VectorType>()->getVectorKind() != - VectorKind::AltiVecBool)) - break; - else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - - break; - else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 - Opc == UO_Plus && - resultType->isPointerType()) + if (InputExpr->isTypeDependent() && + InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) { + resultType = Context.DependentTy; + } else { + switch (Opc) { + case UO_PreInc: + case UO_PreDec: + case UO_PostInc: + case UO_PostDec: + resultType = + CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, OpLoc, + Opc == UO_PreInc || Opc == UO_PostInc, + Opc == UO_PreInc || Opc == UO_PreDec); + CanOverflow = isOverflowingIntegerType(Context, resultType); break; - - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - - case UO_Not: // bitwise complement - Input = UsualUnaryConversions(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = Input.get()->getType(); - if (resultType->isDependentType()) + case UO_AddrOf: + resultType = CheckAddressOfOperand(Input, OpLoc); + CheckAddressOfNoDeref(InputExpr); + RecordModifiableNonNullParam(*this, InputExpr); break; - // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. - if (resultType->isComplexType() || resultType->isComplexIntegerType()) - // C99 does not support '~' for complex conjugation. - Diag(OpLoc, diag::ext_integer_complement_complex) - << resultType << Input.get()->getSourceRange(); - else if (resultType->hasIntegerRepresentation()) + case UO_Deref: { + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = + CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); break; - else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { - // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate - // on vector float types. - QualType T = resultType->castAs<ExtVectorType>()->getElementType(); - if (!T->isIntegerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - break; - - case UO_LNot: // logical negation - // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) return ExprError(); - resultType = Input.get()->getType(); - - // Though we still have to promote half FP to float... - if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { - Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast).get(); - resultType = Context.FloatTy; } + 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 + // float vector and truncating the result back to a half vector. For now, + // we do this only when HalfArgsAndReturns is set (that is, when the + // target is arm or arm64). + ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); + + // If the operand is a half vector, promote it to a float vector. + if (ConvertHalfVec) + Input = convertVector(Input.get(), Context.FloatTy, *this); + resultType = Input.get()->getType(); + if (resultType->isArithmeticType()) // C99 6.5.3.3p1 + break; + else if (resultType->isVectorType() && + // The z vector extensions don't allow + or - with bool vectors. + (!Context.getLangOpts().ZVector || + resultType->castAs<VectorType>()->getVectorKind() != + VectorKind::AltiVecBool)) + break; + else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - + break; + else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 + Opc == UO_Plus && resultType->isPointerType()) + break; - // WebAsembly tables can't be used in unary expressions. - if (resultType->isPointerType() && - resultType->getPointeeType().isWebAssemblyReferenceType()) { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); - } - if (resultType->isDependentType()) - break; - if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { - // C99 6.5.3.3p1: ok, fallthrough; - if (Context.getLangOpts().CPlusPlus) { - // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: - // operand contextually converted to bool. - Input = ImpCastExprToType(Input.get(), Context.BoolTy, - ScalarTypeToBooleanCastKind(resultType)); - } else if (Context.getLangOpts().OpenCL && - Context.getLangOpts().OpenCLVersion < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on scalar float types. - if (!resultType->isIntegerType() && !resultType->isPointerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - } else if (resultType->isExtVectorType()) { - if (Context.getLangOpts().OpenCL && - Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on vector float types. + case UO_Not: // bitwise complement + Input = UsualUnaryConversions(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. + if (resultType->isComplexType() || resultType->isComplexIntegerType()) + // C99 does not support '~' for complex conjugation. + Diag(OpLoc, diag::ext_integer_complement_complex) + << resultType << Input.get()->getSourceRange(); + else if (resultType->hasIntegerRepresentation()) + break; + else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate + // on vector float types. QualType T = resultType->castAs<ExtVectorType>()->getElementType(); if (!T->isIntegerType()) return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); } - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); break; - } else if (Context.getLangOpts().CPlusPlus && resultType->isVectorType()) { - const VectorType *VTy = resultType->castAs<VectorType>(); - if (VTy->getVectorKind() != VectorKind::Generic) + + case UO_LNot: // logical negation + // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + + // Though we still have to promote half FP to float... + if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { + Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast) + .get(); + resultType = Context.FloatTy; + } + + // WebAsembly tables can't be used in unary expressions. + if (resultType->isPointerType() && + resultType->getPointeeType().isWebAssemblyReferenceType()) { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); + } - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); - break; - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } + if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { + // C99 6.5.3.3p1: ok, fallthrough; + if (Context.getLangOpts().CPlusPlus) { + // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: + // operand contextually converted to bool. + Input = ImpCastExprToType(Input.get(), Context.BoolTy, + ScalarTypeToBooleanCastKind(resultType)); + } else if (Context.getLangOpts().OpenCL && + Context.getLangOpts().OpenCLVersion < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on scalar float types. + if (!resultType->isIntegerType() && !resultType->isPointerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + } else if (resultType->isExtVectorType()) { + if (Context.getLangOpts().OpenCL && + Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on vector float types. + QualType T = resultType->castAs<ExtVectorType>()->getElementType(); + if (!T->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else if (Context.getLangOpts().CPlusPlus && + resultType->isVectorType()) { + const VectorType *VTy = resultType->castAs<VectorType>(); + if (VTy->getVectorKind() != VectorKind::Generic) + 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(); - break; - case UO_Real: - case UO_Imag: - resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); - // _Real maps ordinary l-values into ordinary l-values. _Imag maps ordinary - // complex l-values to ordinary l-values and all other values to r-values. - if (Input.isInvalid()) return ExprError(); - if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { - if (Input.get()->isGLValue() && - Input.get()->getObjectKind() == OK_Ordinary) - VK = Input.get()->getValueKind(); - } else if (!getLangOpts().CPlusPlus) { - // In C, a volatile scalar is read by __imag. In C++, it is not. - Input = DefaultLvalueConversion(Input.get()); + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else { + 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(); + break; + case UO_Real: + case UO_Imag: + resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); + // _Real maps ordinary l-values into ordinary l-values. _Imag maps + // ordinary complex l-values to ordinary l-values and all other values to + // r-values. + if (Input.isInvalid()) + return ExprError(); + if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { + if (Input.get()->isGLValue() && + Input.get()->getObjectKind() == OK_Ordinary) + VK = Input.get()->getValueKind(); + } else if (!getLangOpts().CPlusPlus) { + // In C, a volatile scalar is read by __imag. In C++, it is not. + Input = DefaultLvalueConversion(Input.get()); + } + break; + case UO_Extension: + resultType = Input.get()->getType(); + VK = Input.get()->getValueKind(); + OK = Input.get()->getObjectKind(); + break; + case UO_Coawait: + // 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 " + "building operator co_await"); + return Input; } - break; - case UO_Extension: - resultType = Input.get()->getType(); - VK = Input.get()->getValueKind(); - OK = Input.get()->getObjectKind(); - break; - case UO_Coawait: - // 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 " - "building operator co_await"); - return Input; } if (resultType.isNull() || Input.isInvalid()) return ExprError(); @@ -16517,9 +15516,6 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, return UO; } -/// 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. bool Sema::isQualifiedMemberAccess(Expr *E) { if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { if (!DRE->getQualifier()) @@ -16566,7 +15562,7 @@ ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, // Increment and decrement of pseudo-object references. if (pty->getKind() == BuiltinType::PseudoObject && UnaryOperator::isIncrementDecrementOp(Opc)) - return checkPseudoObjectIncDec(S, OpLoc, Opc, Input); + return PseudoObject().checkIncDec(S, OpLoc, Opc, Input); // extension is always a builtin operator. if (Opc == UO_Extension) @@ -16601,14 +15597,12 @@ ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, return CreateBuiltinUnaryOp(OpLoc, Opc, Input, IsAfterAmp); } -// Unary Operators. 'Tok' is the token for the operator. ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input, bool IsAfterAmp) { return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), Input, IsAfterAmp); } -/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, LabelDecl *TheDecl) { TheDecl->markUsed(Context); @@ -16935,7 +15929,6 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, // Clang Extensions. //===----------------------------------------------------------------------===// -/// ActOnBlockStart - This callback is invoked when a block literal is started. void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) { BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc); @@ -17084,8 +16077,6 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, } } -/// ActOnBlockError - If there is an error parsing a block, this callback -/// is invoked to pop the information about the block from the action impl. void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { // Leave the expression-evaluation context. DiscardCleanupsInEvaluationContext(); @@ -17096,8 +16087,6 @@ void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { PopFunctionScopeInfo(); } -/// ActOnBlockStmtExpr - This is called when the body of a block statement -/// literal was successfully completed. ^(int x){...} ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body, Scope *CurScope) { // If blocks are disabled, emit an error. @@ -17303,8 +16292,9 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, // CUDA device code does not support varargs. if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { if (const FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext)) { - CUDAFunctionTarget T = IdentifyCUDATarget(F); - if (T == CFT_Global || T == CFT_Device || T == CFT_HostDevice) + CUDAFunctionTarget T = CUDA().IdentifyTarget(F); + if (T == CUDAFunctionTarget::Global || T == CUDAFunctionTarget::Device || + T == CUDAFunctionTarget::HostDevice) return ExprError(Diag(E->getBeginLoc(), diag::err_va_arg_in_device)); } } @@ -17575,59 +16565,13 @@ ExprResult Sema::BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy, SourceLocExpr(Context, Kind, ResultTy, BuiltinLoc, RPLoc, ParentContext); } -bool Sema::CheckConversionToObjCLiteral(QualType DstType, Expr *&Exp, - bool Diagnose) { - if (!getLangOpts().ObjC) - return false; - - const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>(); - if (!PT) - return false; - const ObjCInterfaceDecl *ID = PT->getInterfaceDecl(); - - // 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. - Expr *SrcExpr = Exp->IgnoreParenImpCasts(); - if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(SrcExpr)) - if (OV->getSourceExpr()) - SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts(); - - if (auto *SL = dyn_cast<StringLiteral>(SrcExpr)) { - if (!PT->isObjCIdType() && - !(ID && ID->getIdentifier()->isStr("NSString"))) - return false; - if (!SL->isOrdinary()) - return false; - - if (Diagnose) { - Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix) - << /*string*/0 << FixItHint::CreateInsertion(SL->getBeginLoc(), "@"); - Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get(); - } - return true; - } - - if ((isa<IntegerLiteral>(SrcExpr) || isa<CharacterLiteral>(SrcExpr) || - isa<FloatingLiteral>(SrcExpr) || isa<ObjCBoolLiteralExpr>(SrcExpr) || - isa<CXXBoolLiteralExpr>(SrcExpr)) && - !SrcExpr->isNullPointerConstant( - getASTContext(), Expr::NPC_NeverValueDependent)) { - if (!ID || !ID->getIdentifier()->isStr("NSNumber")) - return false; - if (Diagnose) { - Diag(SrcExpr->getBeginLoc(), diag::err_missing_atsign_prefix) - << /*number*/1 - << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "@"); - Expr *NumLit = - BuildObjCNumericLiteral(SrcExpr->getBeginLoc(), SrcExpr).get(); - if (NumLit) - Exp = NumLit; - } - return true; - } - - return false; +ExprResult Sema::ActOnEmbedExpr(SourceLocation EmbedKeywordLoc, + StringLiteral *BinaryData) { + EmbedDataStorage *Data = new (Context) EmbedDataStorage; + Data->BinaryData = BinaryData; + return new (Context) + EmbedExpr(Context, EmbedKeywordLoc, Data, /*NumOfElements=*/0, + Data->getDataElementCount()); } static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType, @@ -17719,11 +16663,11 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, } CheckInferredResultType = DstType->isObjCObjectPointerType() && SrcType->isObjCObjectPointerType(); - if (!CheckInferredResultType) { - ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); - } else if (CheckInferredResultType) { + if (CheckInferredResultType) { SrcType = SrcType.getUnqualifiedType(); DstType = DstType.getUnqualifiedType(); + } else { + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); } MayHaveConvFixit = true; break; @@ -17754,7 +16698,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, if (lhq.getAddressSpace() != rhq.getAddressSpace()) { DiagKind = diag::err_typecheck_incompatible_address_space; break; - } else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) { DiagKind = diag::err_typecheck_incompatible_ownership; break; @@ -17924,10 +16867,10 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, FirstType, /*TakingAddress=*/true); if (CheckInferredResultType) - EmitRelatedResultTypeNote(SrcExpr); + ObjC().EmitRelatedResultTypeNote(SrcExpr); if (Action == AA_Returning && ConvTy == IncompatiblePointer) - EmitRelatedResultTypeNoteForReturn(DstType); + ObjC().EmitRelatedResultTypeNoteForReturn(DstType); if (Complained) *Complained = true; @@ -18046,6 +16989,12 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, if (Converted.isInvalid()) return Converted; E = Converted.get(); + // The 'explicit' case causes us to get a RecoveryExpr. Give up here so we + // don't try to evaluate it later. We also don't want to return the + // RecoveryExpr here, as it results in this call succeeding, thus callers of + // this function will attempt to use 'Value'. + if (isa<RecoveryExpr>(E)) + return ExprError(); if (!E->getType()->isIntegralOrUnscopedEnumerationType()) return ExprError(); } else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { @@ -18065,11 +17014,38 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, // Circumvent ICE checking in C++11 to avoid evaluating the expression twice // in the non-ICE case. if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) { + SmallVector<PartialDiagnosticAt, 8> Notes; if (Result) - *Result = E->EvaluateKnownConstIntCheckOverflow(Context); + *Result = E->EvaluateKnownConstIntCheckOverflow(Context, &Notes); if (!isa<ConstantExpr>(E)) E = Result ? ConstantExpr::Create(Context, E, APValue(*Result)) : ConstantExpr::Create(Context, E); + + if (Notes.empty()) + return E; + + // If our only note is the usual "invalid subexpression" note, just point + // the caret at its location rather than producing an essentially + // redundant note. + if (Notes.size() == 1 && Notes[0].second.getDiagID() == + diag::note_invalid_subexpr_in_const_expr) { + DiagLoc = Notes[0].first; + Notes.clear(); + } + + if (getLangOpts().CPlusPlus) { + if (!Diagnoser.Suppress) { + Diagnoser.diagnoseNotICE(*this, DiagLoc) << E->getSourceRange(); + for (const PartialDiagnosticAt &Note : Notes) + Diag(Note.first, Note.second); + } + return ExprError(); + } + + Diagnoser.diagnoseFold(*this, DiagLoc) << E->getSourceRange(); + for (const PartialDiagnosticAt &Note : Notes) + Diag(Note.first, Note.second); + return E; } @@ -18081,7 +17057,8 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, // not a constant expression as a side-effect. bool Folded = E->EvaluateAsRValue(EvalResult, Context, /*isConstantContext*/ true) && - EvalResult.Val.isInt() && !EvalResult.HasSideEffects; + EvalResult.Val.isInt() && !EvalResult.HasSideEffects && + (!getLangOpts().CPlusPlus || !EvalResult.HasUndefinedBehavior); if (!isa<ConstantExpr>(E)) E = ConstantExpr::Create(Context, E, EvalResult.Val); @@ -18184,8 +17161,7 @@ ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) { TypeSourceInfo *Sema::TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo) { assert(isUnevaluatedContext() && "Should only transform unevaluated expressions"); - ExprEvalContexts.back().Context = - ExprEvalContexts[ExprEvalContexts.size() - 2].Context; + ExprEvalContexts.back().Context = parentEvaluationContext().Context; if (isUnevaluatedContext()) return TInfo; return TransformToPE(*this).TransformType(TInfo); @@ -18202,14 +17178,13 @@ Sema::PushExpressionEvaluationContext( // discarded statements or immediate context are themselves // a discarded statement or an immediate context, respectively. ExprEvalContexts.back().InDiscardedStatement = - ExprEvalContexts[ExprEvalContexts.size() - 2] - .isDiscardedStatementContext(); + parentEvaluationContext().isDiscardedStatementContext(); // C++23 [expr.const]/p15 // An expression or conversion is in an immediate function context if [...] // it is a subexpression of a manifestly constant-evaluated expression or // conversion. - const auto &Prev = ExprEvalContexts[ExprEvalContexts.size() - 2]; + const auto &Prev = parentEvaluationContext(); ExprEvalContexts.back().InImmediateFunctionContext = Prev.isImmediateFunctionContext() || Prev.isConstantEvaluated(); @@ -18274,10 +17249,6 @@ void Sema::WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec) { Rec.PossibleDerefs.clear(); } -/// Check whether E, which is either a discarded-value expression or an -/// unevaluated operand, is a simple-assignment to a volatlie-qualified lvalue, -/// and if so, remove it from the list of volatile-qualified assignments that -/// we are going to warn are deprecated. void Sema::CheckUnusedVolatileAssignment(Expr *E) { if (!E->getType().isVolatileQualified() || !getLangOpts().CPlusPlus20) return; @@ -18533,7 +17504,7 @@ HandleImmediateInvocations(Sema &SemaRef, Sema::ExpressionEvaluationContextRecord &Rec) { if ((Rec.ImmediateInvocationCandidates.size() == 0 && Rec.ReferenceToConsteval.size() == 0) || - SemaRef.RebuildingImmediateInvocation) + Rec.isImmediateFunctionContext() || SemaRef.RebuildingImmediateInvocation) return; /// When we have more than 1 ImmediateInvocationCandidates or previously @@ -18652,6 +17623,16 @@ void Sema::PopExpressionEvaluationContext() { } } + // Append the collected materialized temporaries into previous context before + // exit if the previous also is a lifetime extending context. + auto &PrevRecord = parentEvaluationContext(); + if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext && + PrevRecord.InLifetimeExtendingContext && + !Rec.ForRangeLifetimeExtendTemps.empty()) { + PrevRecord.ForRangeLifetimeExtendTemps.append( + Rec.ForRangeLifetimeExtendTemps); + } + WarnOnPendingNoDerefs(Rec); HandleImmediateInvocations(*this, Rec); @@ -18867,8 +17848,6 @@ static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) { return CCD && CCD->getInheritedConstructor(); } -/// 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) { assert(Func && "No function?"); @@ -18931,8 +17910,10 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, // Note that we skip the implicit instantiation of templates that are only // used in unused default arguments or by recursive calls to themselves. // This is formally non-conforming, but seems reasonable in practice. - bool NeedDefinition = !IsRecursiveCall && (OdrUse == OdrUseContext::Used || - NeededForConstantEvaluation); + bool NeedDefinition = + !IsRecursiveCall && + (OdrUse == OdrUseContext::Used || + (NeededForConstantEvaluation && !Func->isPureVirtual())); // C++14 [temp.expl.spec]p6: // If a template [...] is explicitly specialized then that specialization @@ -18945,7 +17926,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, checkSpecializationReachability(Loc, Func); if (getLangOpts().CUDA) - CheckCUDACall(Loc, Func); + CUDA().CheckCall(Loc, Func); // If we need a definition, try to create one. if (NeedDefinition && !Func->getBody()) { @@ -19092,7 +18073,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, // side. Therefore keep trying until it is recorded. if (LangOpts.OffloadImplicitHostDeviceTemplates && LangOpts.CUDAIsDevice && !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(Func)) - CUDARecordImplicitHostDeviceFuncUsedByDevice(Func); + CUDA().RecordImplicitHostDeviceFuncUsedByDevice(Func); // If this is the first "real" use, act on that. if (OdrUse == OdrUseContext::Used && !Func->isUsed(/*CheckUsedAttr=*/false)) { @@ -19157,7 +18138,7 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef, } QualType CaptureType, DeclRefType; if (SemaRef.LangOpts.OpenMP) - SemaRef.tryCaptureOpenMPLambdas(V); + SemaRef.OpenMP().tryCaptureOpenMPLambdas(V); SemaRef.tryCaptureVariable(V, Loc, Sema::TryCapture_Implicit, /*EllipsisLoc*/ SourceLocation(), /*BuildAndDiagnose*/ true, CaptureType, @@ -19165,26 +18146,28 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef, if (SemaRef.LangOpts.CUDA && Var->hasGlobalStorage()) { auto *FD = dyn_cast_or_null<FunctionDecl>(SemaRef.CurContext); - auto VarTarget = SemaRef.IdentifyCUDATarget(Var); - auto UserTarget = SemaRef.IdentifyCUDATarget(FD); - if (VarTarget == Sema::CVT_Host && - (UserTarget == Sema::CFT_Device || UserTarget == Sema::CFT_HostDevice || - UserTarget == Sema::CFT_Global)) { + auto VarTarget = SemaRef.CUDA().IdentifyTarget(Var); + auto UserTarget = SemaRef.CUDA().IdentifyTarget(FD); + if (VarTarget == SemaCUDA::CVT_Host && + (UserTarget == CUDAFunctionTarget::Device || + UserTarget == CUDAFunctionTarget::HostDevice || + UserTarget == CUDAFunctionTarget::Global)) { // Diagnose ODR-use of host global variables in device functions. // Reference of device global variables in host functions is allowed // through shadow variables therefore it is not diagnosed. if (SemaRef.LangOpts.CUDAIsDevice && !SemaRef.LangOpts.HIPStdPar) { SemaRef.targetDiag(Loc, diag::err_ref_bad_target) - << /*host*/ 2 << /*variable*/ 1 << Var << UserTarget; + << /*host*/ 2 << /*variable*/ 1 << Var + << llvm::to_underlying(UserTarget); SemaRef.targetDiag(Var->getLocation(), Var->getType().isConstQualified() ? diag::note_cuda_const_var_unpromoted : diag::note_cuda_host_var); } - } else if (VarTarget == Sema::CVT_Device && + } else if (VarTarget == SemaCUDA::CVT_Device && !Var->hasAttr<CUDASharedAttr>() && - (UserTarget == Sema::CFT_Host || - UserTarget == Sema::CFT_HostDevice)) { + (UserTarget == CUDAFunctionTarget::Host || + UserTarget == CUDAFunctionTarget::HostDevice)) { // Record a CUDA/HIP device side variable if it is ODR-used // by host code. This is done conservatively, when the variable is // referenced in any of the following contexts: @@ -19197,7 +18180,10 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef, // externalize the static device side variable ODR-used by host code. if (!Var->hasExternalStorage()) SemaRef.getASTContext().CUDADeviceVarODRUsedByHost.insert(Var); - else if (SemaRef.LangOpts.GPURelocatableDeviceCode) + else if (SemaRef.LangOpts.GPURelocatableDeviceCode && + (!FD || (!FD->getDescribedFunctionTemplate() && + SemaRef.getASTContext().GetGVALinkageForFunction(FD) == + GVA_StrongExternal))) SemaRef.getASTContext().CUDAExternalDeviceDeclODRUsedByHost.insert(Var); } } @@ -19433,7 +18419,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, ValueDecl *Var, const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>(); if (HasBlocksAttr || CaptureType->isReferenceType() || - (S.getLangOpts().OpenMP && S.isOpenMPCapturedDecl(Var))) { + (S.getLangOpts().OpenMP && S.OpenMP().isOpenMPCapturedDecl(Var))) { // Block capture by reference does not change the capture or // declaration reference types. ByRef = true; @@ -19463,7 +18449,7 @@ static bool captureInCapturedRegion( ByRef = (Kind == Sema::TryCapture_ExplicitByRef); } else if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) { // Using an LValue reference type is consistent with Lambdas (see below). - if (S.isOpenMPCapturedDecl(Var)) { + if (S.OpenMP().isOpenMPCapturedDecl(Var)) { bool HasConst = DeclRefType.isConstQualified(); DeclRefType = DeclRefType.getUnqualifiedType(); // Don't lose diagnostics about assignments to const. @@ -19471,11 +18457,11 @@ static bool captureInCapturedRegion( DeclRefType.addConst(); } // Do not capture firstprivates in tasks. - if (S.isOpenMPPrivateDecl(Var, RSI->OpenMPLevel, RSI->OpenMPCaptureLevel) != - OMPC_unknown) + if (S.OpenMP().isOpenMPPrivateDecl(Var, RSI->OpenMPLevel, + RSI->OpenMPCaptureLevel) != OMPC_unknown) return true; - ByRef = S.isOpenMPCapturedByRef(Var, RSI->OpenMPLevel, - RSI->OpenMPCaptureLevel); + ByRef = S.OpenMP().isOpenMPCapturedByRef(Var, RSI->OpenMPLevel, + RSI->OpenMPCaptureLevel); } if (ByRef) @@ -19507,16 +18493,6 @@ static bool captureInLambda(LambdaScopeInfo *LSI, ValueDecl *Var, ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref); } - BindingDecl *BD = dyn_cast<BindingDecl>(Var); - // FIXME: We should support capturing structured bindings in OpenMP. - if (!Invalid && BD && S.LangOpts.OpenMP) { - if (BuildAndDiagnose) { - S.Diag(Loc, diag::err_capture_binding_openmp) << Var; - S.Diag(Var->getLocation(), diag::note_entity_declared_at) << Var; - } - Invalid = true; - } - if (BuildAndDiagnose && S.Context.getTargetInfo().getTriple().isWasm() && CaptureType.getNonReferenceType().isWebAssemblyReferenceType()) { S.Diag(Loc, diag::err_wasm_ca_reference) << 0; @@ -19715,6 +18691,10 @@ bool Sema::tryCaptureVariable( DeclContext *VarDC = Var->getDeclContext(); DeclContext *DC = CurContext; + // Skip past RequiresExprBodys because they don't constitute function scopes. + while (DC->isRequiresExprBody()) + DC = DC->getParent(); + // tryCaptureVariable is called every time a DeclRef is formed, // it can therefore have non-negigible impact on performances. // For local variables and when there is no capturing scope, @@ -19722,6 +18702,12 @@ bool Sema::tryCaptureVariable( if (CapturingFunctionScopes == 0 && (!BuildAndDiagnose || VarDC == DC)) return true; + // Exception: Function parameters are not tied to the function's DeclContext + // until we enter the function definition. Capturing them anyway would result + // in an out-of-bounds error while traversing DC and its parents. + if (isa<ParmVarDecl>(Var) && !VarDC->isFunctionOrMethod()) + return true; + const auto *VD = dyn_cast<VarDecl>(Var); if (VD) { if (VD->isInitCapture()) @@ -19746,9 +18732,9 @@ bool Sema::tryCaptureVariable( // Capture global variables if it is required to use private copy of this // variable. bool IsGlobal = !VD->hasLocalStorage(); - if (IsGlobal && - !(LangOpts.OpenMP && isOpenMPCapturedDecl(Var, /*CheckScopeInfo=*/true, - MaxFunctionScopesIndex))) + if (IsGlobal && !(LangOpts.OpenMP && + OpenMP().isOpenMPCapturedDecl(Var, /*CheckScopeInfo=*/true, + MaxFunctionScopesIndex))) return true; if (isa<VarDecl>(Var)) @@ -19858,7 +18844,15 @@ bool Sema::tryCaptureVariable( // just break here. Similarly, global variables that are captured in a // target region should not be captured outside the scope of the region. if (RSI->CapRegionKind == CR_OpenMP) { - OpenMPClauseKind IsOpenMPPrivateDecl = isOpenMPPrivateDecl( + // FIXME: We should support capturing structured bindings in OpenMP. + if (isa<BindingDecl>(Var)) { + if (BuildAndDiagnose) { + Diag(ExprLoc, diag::err_capture_binding_openmp) << Var; + Diag(Var->getLocation(), diag::note_entity_declared_at) << Var; + } + return true; + } + OpenMPClauseKind IsOpenMPPrivateDecl = OpenMP().isOpenMPPrivateDecl( Var, RSI->OpenMPLevel, RSI->OpenMPCaptureLevel); // If the variable is private (i.e. not captured) and has variably // modified type, we still need to capture the type for correct @@ -19869,7 +18863,8 @@ bool Sema::tryCaptureVariable( QualType QTy = Var->getType(); if (ParmVarDecl *PVD = dyn_cast_or_null<ParmVarDecl>(Var)) QTy = PVD->getOriginalType(); - for (int I = 1, E = getNumberOfConstructScopes(RSI->OpenMPLevel); + for (int I = 1, + E = OpenMP().getNumberOfConstructScopes(RSI->OpenMPLevel); I < E; ++I) { auto *OuterRSI = cast<CapturedRegionScopeInfo>( FunctionScopes[FunctionScopesIndex - I]); @@ -19881,18 +18876,19 @@ bool Sema::tryCaptureVariable( } bool IsTargetCap = IsOpenMPPrivateDecl != OMPC_private && - isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel, - RSI->OpenMPCaptureLevel); + OpenMP().isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel, + RSI->OpenMPCaptureLevel); // Do not capture global if it is not privatized in outer regions. bool IsGlobalCap = - IsGlobal && isOpenMPGlobalCapturedDecl(Var, RSI->OpenMPLevel, - RSI->OpenMPCaptureLevel); + IsGlobal && OpenMP().isOpenMPGlobalCapturedDecl( + Var, RSI->OpenMPLevel, RSI->OpenMPCaptureLevel); // When we detect target captures we are looking from inside the // target region, therefore we need to propagate the capture from the // enclosing region. Therefore, the capture is not initially nested. if (IsTargetCap) - adjustOpenMPTargetScopeIndex(FunctionScopesIndex, RSI->OpenMPLevel); + OpenMP().adjustOpenMPTargetScopeIndex(FunctionScopesIndex, + RSI->OpenMPLevel); if (IsTargetCap || IsOpenMPPrivateDecl == OMPC_private || (IsGlobal && !IsGlobalCap)) { @@ -20212,18 +19208,17 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, ExprResult Sub = Rebuild(LHS); if (!Sub.isUsable()) return Sub; - LHS = Sub.get(); + BO->setLHS(Sub.get()); // -- If e is a comma expression, ... } else if (BO->getOpcode() == BO_Comma) { ExprResult Sub = Rebuild(RHS); if (!Sub.isUsable()) return Sub; - RHS = Sub.get(); + BO->setRHS(Sub.get()); } else { break; } - return S.BuildBinOp(nullptr, BO->getOperatorLoc(), BO->getOpcode(), - LHS, RHS); + return ExprResult(BO); } // -- If e has the form (e1)... @@ -20653,9 +19648,6 @@ static void DoMarkBindingDeclReferenced(Sema &SemaRef, SourceLocation Loc, } } -/// 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) { DoMarkVarDeclReferenced(*this, Loc, Var, nullptr, RefsMinusAssignments); } @@ -20668,20 +19660,42 @@ void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) { static void FixDependencyOfIdExpressionsInLambdaWithDependentObjectParameter( Sema &SemaRef, ValueDecl *D, Expr *E) { auto *ID = dyn_cast<DeclRefExpr>(E); - if (!ID || ID->isTypeDependent()) + if (!ID || ID->isTypeDependent() || !ID->refersToEnclosingVariableOrCapture()) return; + // If any enclosing lambda with a dependent explicit object parameter either + // explicitly captures the variable by value, or has a capture default of '=' + // and does not capture the variable by reference, then the type of the DRE + // is dependent on the type of that lambda's explicit object parameter. auto IsDependent = [&]() { - const LambdaScopeInfo *LSI = SemaRef.getCurLambda(); - if (!LSI) - return false; - if (!LSI->ExplicitObjectParameter || - !LSI->ExplicitObjectParameter->getType()->isDependentType()) - return false; - if (!LSI->CaptureMap.count(D)) - return false; - const Capture &Cap = LSI->getCapture(D); - return !Cap.isCopyCapture(); + for (auto *Scope : llvm::reverse(SemaRef.FunctionScopes)) { + auto *LSI = dyn_cast<sema::LambdaScopeInfo>(Scope); + if (!LSI) + continue; + + if (LSI->Lambda && !LSI->Lambda->Encloses(SemaRef.CurContext) && + LSI->AfterParameterList) + return false; + + const auto *MD = LSI->CallOperator; + if (MD->getType().isNull()) + continue; + + const auto *Ty = MD->getType()->getAs<FunctionProtoType>(); + if (!Ty || !MD->isExplicitObjectMemberFunction() || + !Ty->getParamType(0)->isDependentType()) + continue; + + if (auto *C = LSI->CaptureMap.count(D) ? &LSI->getCapture(D) : nullptr) { + if (C->isCopyCapture()) + return true; + continue; + } + + if (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByval) + return true; + } + return false; }(); ID->setCapturedByCopyInLambdaWithExplicitObjectParameter( @@ -20692,8 +19706,8 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E, bool MightBeOdrUse, llvm::DenseMap<const VarDecl *, int> &RefsMinusAssignments) { - if (SemaRef.isInOpenMPDeclareTargetContext()) - SemaRef.checkDeclIsAllowedInOpenMPTarget(E, D); + if (SemaRef.OpenMP().isInOpenMPDeclareTargetContext()) + SemaRef.OpenMP().checkDeclIsAllowedInOpenMPTarget(E, D); if (VarDecl *Var = dyn_cast<VarDecl>(D)) { DoMarkVarDeclReferenced(SemaRef, Loc, Var, E, RefsMinusAssignments); @@ -20734,10 +19748,6 @@ MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E, SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse); } -/// Perform reference-marking and odr-use handling for a DeclRefExpr. -/// -/// Note, this may change the dependence of the DeclRefExpr, and so needs to be -/// handled with care if the DeclRefExpr is not newly-created. 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 @@ -20760,7 +19770,6 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) { RefsMinusAssignments); } -/// 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 @@ -20780,7 +19789,6 @@ void Sema::MarkMemberReferenced(MemberExpr *E) { RefsMinusAssignments); } -/// Perform reference-marking and odr-use handling for a FunctionParmPackExpr. void Sema::MarkFunctionParmPackReferenced(FunctionParmPackExpr *E) { for (VarDecl *VD : *E) MarkExprReferenced(*this, E->getParameterPackLocation(), VD, E, true, @@ -20898,12 +19906,6 @@ public: }; } // namespace -/// 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 -/// 'referenced'. -/// \param StopAt Subexpressions that we shouldn't recurse into. void Sema::MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables, ArrayRef<const Expr*> StopAt) { @@ -21052,7 +20054,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { Selector Sel = ME->getSelector(); // self = [<foo> init...] - if (isSelfExpr(Op->getLHS()) && ME->getMethodFamily() == OMF_init) + if (ObjC().isSelfExpr(Op->getLHS()) && ME->getMethodFamily() == OMF_init) diagnostic = diag::warn_condition_is_idiomatic_assignment; // <foo> = [<bar> nextObject] @@ -21090,8 +20092,6 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { << FixItHint::CreateReplacement(Loc, "=="); } -/// 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. SourceLocation parenLoc = ParenE->getBeginLoc(); @@ -21613,8 +20613,6 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { return E; } -/// Check a cast of an unknown-any type. We intentionally only -/// trigger this for C-style casts. ExprResult Sema::checkUnknownAnyCast(SourceRange TypeRange, QualType CastType, Expr *CastExpr, CastKind &CastKind, ExprValueKind &VK, CXXCastPath &Path) { @@ -21705,8 +20703,6 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) { return ExprError(); } -/// Check for operands with placeholder types and complain if found. -/// Returns ExprError() if there was an error and no recovery was possible. ExprResult Sema::CheckPlaceholderExpr(Expr *E) { if (!Context.isDependenceAllowed()) { // C cannot handle TypoExpr nodes on either side of a binop because it @@ -21721,6 +20717,27 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { if (!placeholderType) return E; switch (placeholderType->getKind()) { + case BuiltinType::UnresolvedTemplate: { + auto *ULE = cast<UnresolvedLookupExpr>(E); + const DeclarationNameInfo &NameInfo = ULE->getNameInfo(); + // There's only one FoundDecl for UnresolvedTemplate type. See + // BuildTemplateIdExpr. + NamedDecl *Temp = *ULE->decls_begin(); + const bool IsTypeAliasTemplateDecl = isa<TypeAliasTemplateDecl>(Temp); + + if (NestedNameSpecifierLoc Loc = ULE->getQualifierLoc(); Loc.hasQualifier()) + Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_type_template) + << Loc.getNestedNameSpecifier() << NameInfo.getName().getAsString() + << Loc.getSourceRange() << IsTypeAliasTemplateDecl; + else + Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_type_template) + << "" << NameInfo.getName().getAsString() << ULE->getSourceRange() + << IsTypeAliasTemplateDecl; + Diag(Temp->getLocation(), diag::note_referenced_type_template) + << IsTypeAliasTemplateDecl; + + return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}); + } // Overloaded expressions. case BuiltinType::Overload: { @@ -21762,8 +20779,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { // ARC unbridged casts. case BuiltinType::ARCUnbridgedCast: { - Expr *realCast = stripARCUnbridgedCast(E); - diagnoseARCUnbridgedCast(realCast); + Expr *realCast = ObjC().stripARCUnbridgedCast(E); + ObjC().diagnoseARCUnbridgedCast(realCast); return realCast; } @@ -21773,7 +20790,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { // Pseudo-objects. case BuiltinType::PseudoObject: - return checkPseudoObjectRValue(E); + return PseudoObject().checkRValue(E); case BuiltinType::BuiltinFn: { // Accept __noop without parens by implicitly converting it to a call expr. @@ -21833,8 +20850,9 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { return ExprError(); // Expressions of unknown type. - case BuiltinType::OMPArraySection: - Diag(E->getBeginLoc(), diag::err_omp_array_section_use); + case BuiltinType::ArraySection: + Diag(E->getBeginLoc(), diag::err_array_section_use) + << cast<ArraySectionExpr>(E)->isOMPArraySection(); return ExprError(); // Expressions of unknown type. @@ -21861,6 +20879,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { #include "clang/Basic/RISCVVTypes.def" #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/WebAssemblyReferenceTypes.def" +#define AMDGPU_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/AMDGPUTypes.def" #define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id: #define PLACEHOLDER_TYPE(Id, SingletonId) #include "clang/AST/BuiltinTypes.def" @@ -21878,61 +20898,6 @@ bool Sema::CheckCaseExpression(Expr *E) { return false; } -/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. -ExprResult -Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { - assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) && - "Unknown Objective-C Boolean value!"); - QualType BoolT = Context.ObjCBuiltinBoolTy; - if (!Context.getBOOLDecl()) { - LookupResult Result(*this, &Context.Idents.get("BOOL"), OpLoc, - Sema::LookupOrdinaryName); - if (LookupName(Result, getCurScope()) && Result.isSingleResult()) { - NamedDecl *ND = Result.getFoundDecl(); - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND)) - Context.setBOOLDecl(TD); - } - } - if (Context.getBOOLDecl()) - BoolT = Context.getBOOLType(); - return new (Context) - ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, BoolT, OpLoc); -} - -ExprResult Sema::ActOnObjCAvailabilityCheckExpr( - llvm::ArrayRef<AvailabilitySpec> AvailSpecs, SourceLocation AtLoc, - SourceLocation RParen) { - auto FindSpecVersion = - [&](StringRef Platform) -> std::optional<VersionTuple> { - auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { - return Spec.getPlatform() == Platform; - }); - // Transcribe the "ios" availability check to "maccatalyst" when compiling - // for "maccatalyst" if "maccatalyst" is not specified. - if (Spec == AvailSpecs.end() && Platform == "maccatalyst") { - Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { - return Spec.getPlatform() == "ios"; - }); - } - if (Spec == AvailSpecs.end()) - return std::nullopt; - return Spec->getVersion(); - }; - - VersionTuple Version; - if (auto MaybeVersion = - FindSpecVersion(Context.getTargetInfo().getPlatformName())) - Version = *MaybeVersion; - - // The use of `@available` in the enclosing context should be analyzed to - // warn when it's used inappropriately (i.e. not if(@available)). - if (FunctionScopeInfo *Context = getCurFunctionAvailabilityContext()) - Context->HasPotentialAvailabilityViolations = true; - - return new (Context) - ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy); -} - ExprResult Sema::CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef<Expr *> SubExprs, QualType T) { if (!Context.getLangOpts().RecoveryAST) |