aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/CMakeLists.txt1
-rw-r--r--clang/lib/Sema/Sema.cpp2
-rw-r--r--clang/lib/Sema/SemaARM.cpp24
-rw-r--r--clang/lib/Sema/SemaAttr.cpp4
-rw-r--r--clang/lib/Sema/SemaChecking.cpp3
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp7
-rw-r--r--clang/lib/Sema/SemaInit.cpp9
-rw-r--r--clang/lib/Sema/SemaOpenACC.cpp163
-rw-r--r--clang/lib/Sema/SemaOverload.cpp23
-rw-r--r--clang/lib/Sema/SemaSPIRV.cpp57
-rw-r--r--clang/lib/Sema/SemaStmt.cpp46
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp19
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp5
-rw-r--r--clang/lib/Sema/TreeTransform.h126
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