diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaARM.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExceptionSpec.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenACC.cpp | 163 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 23 | ||||
-rw-r--r-- | clang/lib/Sema/SemaSPIRV.cpp | 57 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 46 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 126 |
15 files changed, 390 insertions, 101 deletions
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 719c3a9..3241cb5 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -79,6 +79,7 @@ add_clang_library(clangSema SemaStmt.cpp SemaStmtAsm.cpp SemaStmtAttr.cpp + SemaSPIRV.cpp SemaSYCL.cpp SemaSwift.cpp SemaSystemZ.cpp diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index d651751..abb46d3 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -61,6 +61,7 @@ #include "clang/Sema/SemaPPC.h" #include "clang/Sema/SemaPseudoObject.h" #include "clang/Sema/SemaRISCV.h" +#include "clang/Sema/SemaSPIRV.h" #include "clang/Sema/SemaSYCL.h" #include "clang/Sema/SemaSwift.h" #include "clang/Sema/SemaSystemZ.h" @@ -239,6 +240,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, PPCPtr(std::make_unique<SemaPPC>(*this)), PseudoObjectPtr(std::make_unique<SemaPseudoObject>(*this)), RISCVPtr(std::make_unique<SemaRISCV>(*this)), + SPIRVPtr(std::make_unique<SemaSPIRV>(*this)), SYCLPtr(std::make_unique<SemaSYCL>(*this)), SwiftPtr(std::make_unique<SemaSwift>(*this)), SystemZPtr(std::make_unique<SemaSystemZ>(*this)), diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index 3e93b38..411baa0 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -372,7 +372,7 @@ enum ArmSMEState : unsigned { bool SemaARM::CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, unsigned ArgIdx, unsigned EltBitWidth, - unsigned VecBitWidth) { + unsigned ContainerBitWidth) { // Function that checks whether the operand (ArgIdx) is an immediate // that is one of a given set of values. auto CheckImmediateInSet = [&](std::initializer_list<int64_t> Set, @@ -445,17 +445,17 @@ bool SemaARM::CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, break; case ImmCheckType::ImmCheckLaneIndex: if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, - (VecBitWidth / EltBitWidth) - 1)) + (ContainerBitWidth / EltBitWidth) - 1)) return true; break; case ImmCheckType::ImmCheckLaneIndexCompRotate: - if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, - (VecBitWidth / (2 * EltBitWidth)) - 1)) + if (SemaRef.BuiltinConstantArgRange( + TheCall, ArgIdx, 0, (ContainerBitWidth / (2 * EltBitWidth)) - 1)) return true; break; case ImmCheckType::ImmCheckLaneIndexDot: - if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, - (VecBitWidth / (4 * EltBitWidth)) - 1)) + if (SemaRef.BuiltinConstantArgRange( + TheCall, ArgIdx, 0, (ContainerBitWidth / (4 * EltBitWidth)) - 1)) return true; break; case ImmCheckType::ImmCheckComplexRot90_270: @@ -515,13 +515,13 @@ bool SemaARM::PerformNeonImmChecks( bool HasError = false; for (const auto &I : ImmChecks) { - auto [ArgIdx, CheckTy, ElementSizeInBits, VecSizeInBits] = I; + auto [ArgIdx, CheckTy, ElementBitWidth, VecBitWidth] = I; if (OverloadType >= 0) - ElementSizeInBits = NeonTypeFlags(OverloadType).getEltSizeInBits(); + ElementBitWidth = NeonTypeFlags(OverloadType).getEltSizeInBits(); - HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementSizeInBits, - VecSizeInBits); + HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, + VecBitWidth); } return HasError; @@ -532,9 +532,9 @@ bool SemaARM::PerformSVEImmChecks( bool HasError = false; for (const auto &I : ImmChecks) { - auto [ArgIdx, CheckTy, ElementSizeInBits] = I; + auto [ArgIdx, CheckTy, ElementBitWidth] = I; HasError |= - CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementSizeInBits, 128); + CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, 128); } return HasError; diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 44485e7..42aa68d 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -307,8 +307,8 @@ void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) { Annotate(MD); return; } - static const llvm::StringSet<> CapturingMethods{"insert", "push", - "push_front", "push_back"}; + static const llvm::StringSet<> CapturingMethods{ + "insert", "insert_or_assign", "push", "push_front", "push_back"}; if (!CapturingMethods.contains(MD->getName())) return; Annotate(MD); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index ce846ae..28dcfaa 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -70,6 +70,7 @@ #include "clang/Sema/SemaOpenCL.h" #include "clang/Sema/SemaPPC.h" #include "clang/Sema/SemaRISCV.h" +#include "clang/Sema/SemaSPIRV.h" #include "clang/Sema/SemaSystemZ.h" #include "clang/Sema/SemaWasm.h" #include "clang/Sema/SemaX86.h" @@ -1934,6 +1935,8 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, case llvm::Triple::mips64: case llvm::Triple::mips64el: return MIPS().CheckMipsBuiltinFunctionCall(TI, BuiltinID, TheCall); + case llvm::Triple::spirv: + return SPIRV().CheckSPIRVBuiltinFunctionCall(BuiltinID, TheCall); case llvm::Triple::systemz: return SystemZ().CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall); case llvm::Triple::x86: diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index ac36663..ac5d51a1 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1401,6 +1401,8 @@ CanThrowResult Sema::canThrow(const Stmt *S) { case Stmt::OpenACCWaitConstructClass: case Stmt::OpenACCInitConstructClass: case Stmt::OpenACCShutdownConstructClass: + case Stmt::OpenACCSetConstructClass: + case Stmt::OpenACCUpdateConstructClass: // These expressions can never throw. return CT_Cannot; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 562c98c..ae40895 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16592,6 +16592,13 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, << TInfo->getTypeLoc().getSourceRange(); } + if (TInfo->getType()->isArrayType()) { + DiagRuntimeBehavior(TInfo->getTypeLoc().getBeginLoc(), E, + PDiag(diag::warn_second_parameter_to_va_arg_array) + << TInfo->getType() + << TInfo->getTypeLoc().getSourceRange()); + } + // Check for va_arg where arguments of the given type will be promoted // (i.e. this va_arg is guaranteed to have undefined behavior). QualType PromoteType; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 5909457..0dd5f46 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2030,13 +2030,8 @@ canInitializeArrayWithEmbedDataString(ArrayRef<Expr *> ExprList, if (InitType->isArrayType()) { const ArrayType *InitArrayType = InitType->getAsArrayTypeUnsafe(); - QualType InitElementTy = InitArrayType->getElementType(); - QualType EmbedExprElementTy = EE->getDataStringLiteral()->getType(); - const bool TypesMatch = - Context.typesAreCompatible(InitElementTy, EmbedExprElementTy) || - (InitElementTy->isCharType() && EmbedExprElementTy->isCharType()); - if (TypesMatch) - return true; + StringLiteral *SL = EE->getDataStringLiteral(); + return IsStringInit(SL, InitArrayType, Context) == SIF_None; } return false; } diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 42bbdf1..51a95f9 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -463,6 +463,14 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind, return false; } } + case OpenACCClauseKind::DefaultAsync: { + switch (DirectiveKind) { + case OpenACCDirectiveKind::Set: + return true; + default: + return false; + } + } } default: @@ -490,12 +498,9 @@ bool checkAlreadyHasClauseOfKind( bool checkValidAfterDeviceType( SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause, const SemaOpenACC::OpenACCParsedClause &NewClause) { - // This is only a requirement on compute, combined, data and loop constructs - // so far, so this is fine otherwise. - if (!isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind()) && - !isOpenACCCombinedDirectiveKind(NewClause.getDirectiveKind()) && - NewClause.getDirectiveKind() != OpenACCDirectiveKind::Loop && - NewClause.getDirectiveKind() != OpenACCDirectiveKind::Data) + // This is implemented for everything but 'routine', so treat as 'fine' for + // that. + if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Routine) return false; // OpenACC3.3: Section 2.4: Clauses that precede any device_type clause are @@ -570,6 +575,21 @@ bool checkValidAfterDeviceType( default: break; } + } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Set || + NewClause.getDirectiveKind() == OpenACCDirectiveKind::Init || + NewClause.getDirectiveKind() == OpenACCDirectiveKind::Shutdown) { + // There are no restrictions on 'set', 'init', or 'shutdown'. + return false; + } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Update) { + // OpenACC3.3 section 2.14.4: Only the async and wait clauses may follow a + // device_type clause. + switch (NewClause.getClauseKind()) { + case OpenACCClauseKind::Async: + case OpenACCClauseKind::Wait: + return false; + default: + break; + } } S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type) << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind() @@ -587,7 +607,8 @@ bool isDirectiveKindImplemented(OpenACCDirectiveKind DK) { isOpenACCCombinedDirectiveKind(DK) || isOpenACCDataDirectiveKind(DK) || DK == OpenACCDirectiveKind::Loop || DK == OpenACCDirectiveKind::Wait || DK == OpenACCDirectiveKind::Init || - DK == OpenACCDirectiveKind::Shutdown; + DK == OpenACCDirectiveKind::Shutdown || + DK == OpenACCDirectiveKind::Set; } class SemaOpenACCClauseVisitor { @@ -700,18 +721,11 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute'/'combined'/'data' - // constructs, and 'compute'/'combined'/'data' constructs are the only - // constructs that can do anything with this yet, so skip/treat as - // unimplemented in this case. - if (!isDirectiveKindImplemented(Clause.getDirectiveKind())) - return isNotImplemented(); - // There is no prose in the standard that says duplicates aren't allowed, // but this diagnostic is present in other compilers, as well as makes - // sense. Prose DOES exist for 'data' and 'host_data', 'enter data' and 'exit - // data' both don't, but other implmementations do this. OpenACC issue 519 - // filed for the latter two. + // sense. Prose DOES exist for 'data' and 'host_data', 'set', 'enter data' and + // 'exit data' both don't, but other implmementations do this. OpenACC issue + // 519 filed for the latter two. Prose also exists for 'update'. // GCC allows this on init/shutdown, presumably for good reason, so we do too. if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Init && Clause.getDirectiveKind() != OpenACCDirectiveKind::Shutdown && @@ -722,14 +736,14 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause( // isn't really much to do here. // If the 'if' clause is true, it makes the 'self' clause have no effect, - // diagnose that here. - // TODO OpenACC: When we add these two to other constructs, we might not - // want to warn on this (for example, 'update'). - const auto *Itr = - llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>); - if (Itr != ExistingClauses.end()) { - SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict); - SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); + // diagnose that here. This only applies on compute/combined constructs. + if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Update) { + const auto *Itr = + llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>); + if (Itr != ExistingClauses.end()) { + SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict); + SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); + } } return OpenACCIfClause::Create(Ctx, Clause.getBeginLoc(), @@ -739,16 +753,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute' constructs, and - // 'compute' constructs are the only construct that can do anything with - // this yet, so skip/treat as unimplemented in this case. - if (!isDirectiveKindImplemented(Clause.getDirectiveKind())) - return isNotImplemented(); - - // TODO OpenACC: When we implement this for 'update', this takes a - // 'var-list' instead of a condition expression, so semantics/handling has - // to happen differently here. - // There is no prose in the standard that says duplicates aren't allowed, // but this diagnostic is present in other compilers, as well as makes // sense. @@ -756,9 +760,12 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause( return nullptr; // If the 'if' clause is true, it makes the 'self' clause have no effect, - // diagnose that here. - // TODO OpenACC: When we add these two to other constructs, we might not - // want to warn on this (for example, 'update'). + // diagnose that here. This only applies on compute/combined constructs. + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Update) + return OpenACCSelfClause::Create(Ctx, Clause.getBeginLoc(), + Clause.getLParenLoc(), Clause.getVarList(), + Clause.getEndLoc()); + const auto *Itr = llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCIfClause>); if (Itr != ExistingClauses.end()) { @@ -935,13 +942,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute'/'combined'/'data' - // constructs, and 'compute'/'combined'/'data' constructs are the only - // construct that can do anything with this yet, so skip/treat as - // unimplemented in this case. - if (!isDirectiveKindImplemented(Clause.getDirectiveKind())) - return isNotImplemented(); - // There is no prose in the standard that says duplicates aren't allowed, // but this diagnostic is present in other compilers, as well as makes // sense. @@ -963,6 +963,12 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause( if (!isDirectiveKindImplemented(Clause.getDirectiveKind())) return isNotImplemented(); + // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the + // same directive. + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set && + checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause)) + return nullptr; + assert(Clause.getNumIntExprs() == 1 && "Invalid number of expressions for device_num"); return OpenACCDeviceNumClause::Create( @@ -970,6 +976,20 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause( Clause.getEndLoc()); } +OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultAsyncClause( + SemaOpenACC::OpenACCParsedClause &Clause) { + // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the + // same directive. + if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause)) + return nullptr; + + assert(Clause.getNumIntExprs() == 1 && + "Invalid number of expressions for default_async"); + return OpenACCDefaultAsyncClause::Create( + Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0], + Clause.getEndLoc()); +} + OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause( SemaOpenACC::OpenACCParsedClause &Clause) { // ActOnVar ensured that everything is a valid variable reference, so there @@ -1156,13 +1176,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute'/'combined'/'data' - // constructs, and 'compute'/'combined'/'data' constructs are the only - // construct that can do anything with this yet, so skip/treat as - // unimplemented in this case. - if (!isDirectiveKindImplemented(Clause.getDirectiveKind())) - return isNotImplemented(); - return OpenACCWaitClause::Create( Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getDevNumExpr(), Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc()); @@ -1170,13 +1183,16 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute', 'combined', 'data' and - // 'loop' constructs, and 'compute'/'combined'/'data'/'loop' constructs are - // the only construct that can do anything with this yet, so skip/treat as - // unimplemented in this case. - if (!isDirectiveKindImplemented(Clause.getDirectiveKind())) + // Restrictions implemented properly on everything except 'routine'. + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Routine) return isNotImplemented(); + // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the + // same directive. + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set && + checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause)) + return nullptr; + // TODO OpenACC: Once we get enough of the CodeGen implemented that we have // a source for the list of valid architectures, we need to warn on unknown // identifiers here. @@ -1709,8 +1725,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitFinalizeClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitIfPresentClause( SemaOpenACC::OpenACCParsedClause &Clause) { - if (!isDirectiveKindImplemented(Clause.getDirectiveKind())) - return isNotImplemented(); // There isn't anything to do here, this is only valid on one construct, and // has no associated rules. return OpenACCIfPresentClause::Create(Ctx, Clause.getBeginLoc(), @@ -1900,6 +1914,8 @@ bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) { case OpenACCDirectiveKind::Wait: case OpenACCDirectiveKind::Init: case OpenACCDirectiveKind::Shutdown: + case OpenACCDirectiveKind::Set: + case OpenACCDirectiveKind::Update: llvm_unreachable("Doesn't have an associated stmt"); default: case OpenACCDirectiveKind::Invalid: @@ -2328,6 +2344,8 @@ void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, case OpenACCDirectiveKind::HostData: case OpenACCDirectiveKind::Init: case OpenACCDirectiveKind::Shutdown: + case OpenACCDirectiveKind::Set: + case OpenACCDirectiveKind::Update: // Nothing to do here, there is no real legalization that needs to happen // here as these constructs do not take any arguments. break; @@ -3661,6 +3679,24 @@ bool SemaOpenACC::ActOnStartStmtDirective( return Diag(StartLoc, diag::err_acc_construct_one_clause_of) << K << GetListOfClauses({OpenACCClauseKind::UseDevice}); + // OpenACC3.3 2.14.3: At least one default_async, device_num, or device_type + // clause must appear. + if (K == OpenACCDirectiveKind::Set && + llvm::find_if( + Clauses, + llvm::IsaPred<OpenACCDefaultAsyncClause, OpenACCDeviceNumClause, + OpenACCDeviceTypeClause, OpenACCIfClause>) == + Clauses.end()) + return Diag(StartLoc, diag::err_acc_construct_one_clause_of) + << K + << GetListOfClauses({OpenACCClauseKind::DefaultAsync, + OpenACCClauseKind::DeviceNum, + OpenACCClauseKind::DeviceType, + OpenACCClauseKind::If}); + + // TODO: OpenACC: 'Update' construct needs to have one of 'self', 'host', or + // 'device'. Implement here. + return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true); } @@ -3724,6 +3760,14 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective( return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc, EndLoc, Clauses); } + case OpenACCDirectiveKind::Set: { + return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc, + EndLoc, Clauses); + } + case OpenACCDirectiveKind::Update: { + return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc, + EndLoc, Clauses); + } } llvm_unreachable("Unhandled case in directive handling?"); } @@ -3739,6 +3783,7 @@ StmtResult SemaOpenACC::ActOnAssociatedStmt( case OpenACCDirectiveKind::Wait: case OpenACCDirectiveKind::Init: case OpenACCDirectiveKind::Shutdown: + case OpenACCDirectiveKind::Set: llvm_unreachable( "these don't have associated statements, so shouldn't get here"); case OpenACCDirectiveKind::Parallel: diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index fff49b7..7589701 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6977,11 +6977,26 @@ void Sema::AddOverloadCandidate( /// have linkage. So that all entities of the same should share one /// linkage. But in clang, different entities of the same could have /// different linkage. - NamedDecl *ND = Function; - if (auto *SpecInfo = Function->getTemplateSpecializationInfo()) + const NamedDecl *ND = Function; + bool IsImplicitlyInstantiated = false; + if (auto *SpecInfo = Function->getTemplateSpecializationInfo()) { ND = SpecInfo->getTemplate(); - - if (ND->getFormalLinkage() == Linkage::Internal) { + IsImplicitlyInstantiated = SpecInfo->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation; + } + + /// Don't remove inline functions with internal linkage from the overload + /// set if they are declared in a GMF, in violation of C++ [basic.link]p17. + /// However: + /// - Inline functions with internal linkage are a common pattern in + /// headers to avoid ODR issues. + /// - The global module is meant to be a transition mechanism for C and C++ + /// headers, and the current rules as written work against that goal. + const bool IsInlineFunctionInGMF = + Function->isFromGlobalModule() && + (IsImplicitlyInstantiated || Function->isInlined()); + + if (ND->getFormalLinkage() == Linkage::Internal && !IsInlineFunctionInGMF) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_module_mismatched; return; diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp new file mode 100644 index 0000000..d2de648 --- /dev/null +++ b/clang/lib/Sema/SemaSPIRV.cpp @@ -0,0 +1,57 @@ +//===- SemaSPIRV.cpp - Semantic Analysis for SPIRV constructs--------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This implements Semantic Analysis for SPIRV constructs. +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaSPIRV.h" +#include "clang/Basic/TargetBuiltins.h" +#include "clang/Sema/Sema.h" + +namespace clang { + +SemaSPIRV::SemaSPIRV(Sema &S) : SemaBase(S) {} + +bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, + CallExpr *TheCall) { + switch (BuiltinID) { + case SPIRV::BI__builtin_spirv_distance: { + if (SemaRef.checkArgCount(TheCall, 2)) + return true; + + ExprResult A = TheCall->getArg(0); + QualType ArgTyA = A.get()->getType(); + auto *VTyA = ArgTyA->getAs<VectorType>(); + if (VTyA == nullptr) { + SemaRef.Diag(A.get()->getBeginLoc(), + diag::err_typecheck_convert_incompatible) + << ArgTyA + << SemaRef.Context.getVectorType(ArgTyA, 2, VectorKind::Generic) << 1 + << 0 << 0; + return true; + } + + ExprResult B = TheCall->getArg(1); + QualType ArgTyB = B.get()->getType(); + auto *VTyB = ArgTyB->getAs<VectorType>(); + if (VTyB == nullptr) { + SemaRef.Diag(A.get()->getBeginLoc(), + diag::err_typecheck_convert_incompatible) + << ArgTyB + << SemaRef.Context.getVectorType(ArgTyB, 2, VectorKind::Generic) << 1 + << 0 << 0; + return true; + } + + QualType RetTy = VTyA->getElementType(); + TheCall->setType(RetTy); + break; + } + } + return false; +} +} // namespace clang diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index d9149f7..25a07d0 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -625,6 +625,15 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, if (getCurScope()->isInOpenACCComputeConstructScope()) setFunctionHasBranchProtectedScope(); + // OpenACC3.3 2.14.4: + // The update directive is executable. It must not appear in place of the + // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or + // C++. + if (isa<OpenACCUpdateConstruct>(SubStmt)) { + Diag(SubStmt->getBeginLoc(), diag::err_acc_update_as_body) << /*Label*/ 4; + SubStmt = new (Context) NullStmt(SubStmt->getBeginLoc()); + } + // Otherwise, things are good. Fill in the declaration and return it. LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); TheDecl->setStmt(LS); @@ -1019,6 +1028,15 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, Diags.Report(IfLoc, diag::warn_consteval_if_always_true) << Immediate; } + // OpenACC3.3 2.14.4: + // The update directive is executable. It must not appear in place of the + // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or + // C++. + if (isa<OpenACCUpdateConstruct>(thenStmt)) { + Diag(thenStmt->getBeginLoc(), diag::err_acc_update_as_body) << /*if*/ 0; + thenStmt = new (Context) NullStmt(thenStmt->getBeginLoc()); + } + return BuildIfStmt(IfLoc, StatementKind, LParenLoc, InitStmt, Cond, RParenLoc, thenStmt, ElseLoc, elseStmt); } @@ -1297,6 +1315,16 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, getCurFunction()->SwitchStack.pop_back(); if (!BodyStmt) return StmtError(); + + // OpenACC3.3 2.14.4: + // The update directive is executable. It must not appear in place of the + // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or + // C++. + if (isa<OpenACCUpdateConstruct>(BodyStmt)) { + Diag(BodyStmt->getBeginLoc(), diag::err_acc_update_as_body) << /*switch*/ 3; + BodyStmt = new (Context) NullStmt(BodyStmt->getBeginLoc()); + } + SS->setBody(BodyStmt, SwitchLoc); Expr *CondExpr = SS->getCond(); @@ -1774,6 +1802,15 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) CommaVisitor(*this).Visit(CondVal.second); + // OpenACC3.3 2.14.4: + // The update directive is executable. It must not appear in place of the + // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or + // C++. + if (isa<OpenACCUpdateConstruct>(Body)) { + Diag(Body->getBeginLoc(), diag::err_acc_update_as_body) << /*while*/ 1; + Body = new (Context) NullStmt(Body->getBeginLoc()); + } + if (isa<NullStmt>(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); @@ -1803,6 +1840,15 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc())) CommaVisitor(*this).Visit(Cond); + // OpenACC3.3 2.14.4: + // The update directive is executable. It must not appear in place of the + // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or + // C++. + if (isa<OpenACCUpdateConstruct>(Body)) { + Diag(Body->getBeginLoc(), diag::err_acc_update_as_body) << /*do*/ 2; + Body = new (Context) NullStmt(Body->getBeginLoc()); + } + return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 5e7a3c8..ce672b0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1228,7 +1228,7 @@ bool Sema::AttachTypeConstraint(AutoTypeLoc TL, NonTypeTemplateParmDecl *NewConstrainedParm, NonTypeTemplateParmDecl *OrigConstrainedParm, SourceLocation EllipsisLoc) { - if (NewConstrainedParm->getType() != TL.getType() || + if (NewConstrainedParm->getType().getNonPackExpansionType() != TL.getType() || TL.getAutoKeyword() != AutoTypeKeyword::Auto) { Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), diag::err_unsupported_placeholder_constraint) @@ -1530,9 +1530,19 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, Param->setAccess(AS_public); if (AutoTypeLoc TL = TInfo->getTypeLoc().getContainedAutoTypeLoc()) - if (TL.isConstrained()) - if (AttachTypeConstraint(TL, Param, Param, D.getEllipsisLoc())) + if (TL.isConstrained()) { + if (D.getEllipsisLoc().isInvalid() && + T->containsUnexpandedParameterPack()) { + assert(TL.getConceptReference()->getTemplateArgsAsWritten()); + for (auto &Loc : + TL.getConceptReference()->getTemplateArgsAsWritten()->arguments()) + Invalid |= DiagnoseUnexpandedParameterPack( + Loc, UnexpandedParameterPackContext::UPPC_TypeConstraint); + } + if (!Invalid && + AttachTypeConstraint(TL, Param, Param, D.getEllipsisLoc())) Invalid = true; + } if (Invalid) Param->setInvalidDecl(); @@ -4547,6 +4557,9 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, const TemplateArgumentListInfo *TemplateArgs) { assert(NamedConcept && "A concept template id without a template?"); + if (NamedConcept->isInvalidDecl()) + return ExprError(); + llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; if (CheckTemplateArgumentList( NamedConcept, ConceptNameInfo.getLoc(), diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index fad20b3..1c1f6e3 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -857,7 +857,10 @@ private: if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>( TemplateParams->getParam(Index))) { if (!NTTP->isExpandedParameterPack()) - if (auto *Expansion = dyn_cast<PackExpansionType>(NTTP->getType())) + // FIXME: CWG2982 suggests a type-constraint forms a non-deduced + // context, however it is not yet resolved. + if (auto *Expansion = dyn_cast<PackExpansionType>( + S.Context.getUnconstrainedType(NTTP->getType()))) ExtraDeductions.push_back(Expansion->getPattern()); } // FIXME: Also collect the unexpanded packs in any type and template diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 5d43d98..d00ad5a 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4169,6 +4169,24 @@ public: SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, {}); } + StmtResult RebuildOpenACCSetConstruct(SourceLocation BeginLoc, + SourceLocation DirLoc, + SourceLocation EndLoc, + ArrayRef<OpenACCClause *> Clauses) { + return getSema().OpenACC().ActOnEndStmtDirective( + OpenACCDirectiveKind::Set, BeginLoc, DirLoc, SourceLocation{}, + SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, {}); + } + + StmtResult RebuildOpenACCUpdateConstruct(SourceLocation BeginLoc, + SourceLocation DirLoc, + SourceLocation EndLoc, + ArrayRef<OpenACCClause *> Clauses) { + return getSema().OpenACC().ActOnEndStmtDirective( + OpenACCDirectiveKind::Update, BeginLoc, DirLoc, SourceLocation{}, + SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, {}); + } + StmtResult RebuildOpenACCWaitConstruct( SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef<Expr *> QueueIdExprs, @@ -11629,22 +11647,48 @@ template <typename Derived> void OpenACCClauseTransform<Derived>::VisitSelfClause( const OpenACCSelfClause &C) { - if (C.hasConditionExpr()) { - Expr *Cond = const_cast<Expr *>(C.getConditionExpr()); - Sema::ConditionResult Res = - Self.TransformCondition(Cond->getExprLoc(), /*Var=*/nullptr, Cond, - Sema::ConditionKind::Boolean); + // If this is an 'update' 'self' clause, this is actually a var list instead. + if (ParsedClause.getDirectiveKind() == OpenACCDirectiveKind::Update) { + llvm::SmallVector<Expr *> InstantiatedVarList; + for (Expr *CurVar : C.getVarList()) { + ExprResult Res = Self.TransformExpr(CurVar); - if (Res.isInvalid() || !Res.get().second) - return; + if (!Res.isUsable()) + continue; - ParsedClause.setConditionDetails(Res.get().second); - } + Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getClauseKind(), + Res.get()); - NewClause = OpenACCSelfClause::Create( - Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), - ParsedClause.getLParenLoc(), ParsedClause.getConditionExpr(), - ParsedClause.getEndLoc()); + if (Res.isUsable()) + InstantiatedVarList.push_back(Res.get()); + } + + ParsedClause.setVarListDetails(InstantiatedVarList, + /*IsReadOnly=*/false, /*IsZero=*/false); + + NewClause = OpenACCSelfClause::Create( + Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), + ParsedClause.getLParenLoc(), ParsedClause.getVarList(), + ParsedClause.getEndLoc()); + } else { + + if (C.hasConditionExpr()) { + Expr *Cond = const_cast<Expr *>(C.getConditionExpr()); + Sema::ConditionResult Res = + Self.TransformCondition(Cond->getExprLoc(), /*Var=*/nullptr, Cond, + Sema::ConditionKind::Boolean); + + if (Res.isInvalid() || !Res.get().second) + return; + + ParsedClause.setConditionDetails(Res.get().second); + } + + NewClause = OpenACCSelfClause::Create( + Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), + ParsedClause.getLParenLoc(), ParsedClause.getConditionExpr(), + ParsedClause.getEndLoc()); + } } template <typename Derived> @@ -11901,6 +11945,29 @@ void OpenACCClauseTransform<Derived>::VisitDeviceNumClause ( } template <typename Derived> +void OpenACCClauseTransform<Derived>::VisitDefaultAsyncClause( + const OpenACCDefaultAsyncClause &C) { + Expr *IntExpr = const_cast<Expr *>(C.getIntExpr()); + assert(IntExpr && "default_async clause constructed with invalid int expr"); + + ExprResult Res = Self.TransformExpr(IntExpr); + if (!Res.isUsable()) + return; + + Res = Self.getSema().OpenACC().ActOnIntExpr(OpenACCDirectiveKind::Invalid, + C.getClauseKind(), + C.getBeginLoc(), Res.get()); + if (!Res.isUsable()) + return; + + ParsedClause.setIntExprDetails(Res.get()); + NewClause = OpenACCDefaultAsyncClause::Create( + Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), + ParsedClause.getLParenLoc(), ParsedClause.getIntExprs()[0], + ParsedClause.getEndLoc()); +} + +template <typename Derived> void OpenACCClauseTransform<Derived>::VisitVectorLengthClause( const OpenACCVectorLengthClause &C) { Expr *IntExpr = const_cast<Expr *>(C.getIntExpr()); @@ -12422,6 +12489,39 @@ StmtResult TreeTransform<Derived>::TransformOpenACCShutdownConstruct( C->getBeginLoc(), C->getDirectiveLoc(), C->getEndLoc(), TransformedClauses); } +template <typename Derived> +StmtResult +TreeTransform<Derived>::TransformOpenACCSetConstruct(OpenACCSetConstruct *C) { + getSema().OpenACC().ActOnConstruct(C->getDirectiveKind(), C->getBeginLoc()); + + llvm::SmallVector<OpenACCClause *> TransformedClauses = + getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), + C->clauses()); + if (getSema().OpenACC().ActOnStartStmtDirective( + C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses)) + return StmtError(); + + return getDerived().RebuildOpenACCSetConstruct( + C->getBeginLoc(), C->getDirectiveLoc(), C->getEndLoc(), + TransformedClauses); +} + +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformOpenACCUpdateConstruct( + OpenACCUpdateConstruct *C) { + getSema().OpenACC().ActOnConstruct(C->getDirectiveKind(), C->getBeginLoc()); + + llvm::SmallVector<OpenACCClause *> TransformedClauses = + getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), + C->clauses()); + if (getSema().OpenACC().ActOnStartStmtDirective( + C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses)) + return StmtError(); + + return getDerived().RebuildOpenACCUpdateConstruct( + C->getBeginLoc(), C->getDirectiveLoc(), C->getEndLoc(), + TransformedClauses); +} template <typename Derived> StmtResult |