diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e7c204fef2a09e..8af1bed7b67f1c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10830,6 +10830,8 @@ def err_omp_interop_type_not_found : Error< def err_omp_declare_variant_incompat_types : Error< "variant in '#pragma omp declare variant' with type %0 is incompatible with" " type %1%select{| with appended arguments}2">; +def err_omp_declare_variant_same_base_function : Error< + "variant in '#pragma omp declare variant' is the same as the base function">; def warn_omp_declare_variant_marked_as_declare_variant : Warning< "variant function in '#pragma omp declare variant' is itself marked as '#pragma omp declare variant'" >, InGroup; diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 79823fcf148b7c..64647f59fcb5f4 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -7171,6 +7171,13 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, return None; } + if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) { + Diag(VariantRef->getExprLoc(), + diag::err_omp_declare_variant_same_base_function) + << VariantRef->getSourceRange(); + return None; + } + // Check if function types are compatible in C. if (!LangOpts.CPlusPlus) { QualType NewType = diff --git a/clang/test/OpenMP/declare_variant_messages.c b/clang/test/OpenMP/declare_variant_messages.c index 66ead8909ad8f9..a049285cdb01c2 100644 --- a/clang/test/OpenMP/declare_variant_messages.c +++ b/clang/test/OpenMP/declare_variant_messages.c @@ -113,6 +113,15 @@ int bar(void) { return after_use(); } +// expected-error@+1 {{variant in '#pragma omp declare variant' is the same as the base function}} +#pragma omp declare variant (self) \ + match(construct={dispatch}, device={arch(arm)}) +void self(int n); + +void self_test(int n, int d_no) { + #pragma omp dispatch device(d_no) nowait + self(n); +} #pragma omp declare variant(after_use_variant) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-warning {{'#pragma omp declare variant' cannot be applied for function after first usage; the original function might be used}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} int after_use(void);