aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 64352ab..160d735 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3115,6 +3115,10 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
cast<SYCLKernelEntryPointAttr>(NewAttribute)->setInvalidAttr();
++I;
continue;
+ } else if (isa<SYCLExternalAttr>(NewAttribute)) {
+ // SYCLExternalAttr may be added after a definition.
+ ++I;
+ continue;
}
S.Diag(NewAttribute->getLocation(),
@@ -4140,6 +4144,18 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S,
diag::note_carries_dependency_missing_first_decl) << 0/*Function*/;
}
+ // SYCL 2020 section 5.10.1, "SYCL functions and member functions linkage":
+ // When a function is declared with SYCL_EXTERNAL, that macro must be
+ // used on the first declaration of that function in the translation unit.
+ // Redeclarations of the function in the same translation unit may
+ // optionally use SYCL_EXTERNAL, but this is not required.
+ const SYCLExternalAttr *SEA = New->getAttr<SYCLExternalAttr>();
+ if (SEA && !Old->hasAttr<SYCLExternalAttr>()) {
+ Diag(SEA->getLocation(), diag::warn_sycl_external_missing_on_first_decl)
+ << SEA;
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
+
// (C++98 8.3.5p3):
// All declarations for a function shall agree exactly in both the
// return type and the parameter-type-list.
@@ -12325,6 +12341,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (NewFD->hasAttr<SYCLKernelEntryPointAttr>())
SYCL().CheckSYCLEntryPointFunctionDecl(NewFD);
+ if (NewFD->hasAttr<SYCLExternalAttr>())
+ SYCL().CheckSYCLExternalFunctionDecl(NewFD);
+
// Semantic checking for this function declaration (in isolation).
if (getLangOpts().CPlusPlus) {
@@ -12513,6 +12532,13 @@ void Sema::CheckMain(FunctionDecl *FD, const DeclSpec &DS) {
return;
}
+ if (FD->hasAttr<SYCLExternalAttr>()) {
+ Diag(FD->getLocation(), diag::err_sycl_external_invalid_main)
+ << FD->getAttr<SYCLExternalAttr>();
+ FD->setInvalidDecl();
+ return;
+ }
+
// Functions named main in hlsl are default entries, but don't have specific
// signatures they are required to conform to.
if (getLangOpts().HLSL)
@@ -16351,6 +16377,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation,
}
}
+ if (FD && !FD->isInvalidDecl() && FD->hasAttr<SYCLExternalAttr>()) {
+ SYCLExternalAttr *SEAttr = FD->getAttr<SYCLExternalAttr>();
+ if (FD->isDeletedAsWritten())
+ Diag(SEAttr->getLocation(),
+ diag::err_sycl_external_invalid_deleted_function)
+ << SEAttr;
+ }
+
{
// Do not call PopExpressionEvaluationContext() if it is a lambda because
// one is already popped when finishing the lambda in BuildLambdaExpr().