ABataev updated this revision to Diff 232917.
ABataev added a comment.
Herald added subscribers: s.egerton, simoncook, fedor.sergeev, aheejin,
rampitec.
Reworked attribute translationto try to reuse the context matching and scoring
functionality with Sema.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D70973/new/
https://reviews.llvm.org/D70973
Files:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/OpenMPKinds.h
clang/include/clang/Sema/Sema.h
clang/lib/Basic/OpenMPKinds.cpp
clang/lib/CodeGen/CGOpenMPRuntime.cpp
clang/lib/CodeGen/CGOpenMPRuntime.h
clang/lib/Parse/ParseOpenMP.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/OpenMP/declare_variant_ast_print.c
clang/test/OpenMP/declare_variant_ast_print.cpp
clang/test/OpenMP/declare_variant_device_kind_codegen.cpp
clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp
clang/test/OpenMP/declare_variant_messages.c
clang/test/OpenMP/declare_variant_messages.cpp
clang/test/OpenMP/declare_variant_mixed_codegen.cpp
Index: clang/test/OpenMP/declare_variant_mixed_codegen.cpp
===================================================================
--- clang/test/OpenMP/declare_variant_mixed_codegen.cpp
+++ clang/test/OpenMP/declare_variant_mixed_codegen.cpp
@@ -1,7 +1,8 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-linux -fexceptions -fcxx-exceptions -emit-pch -o %t -fopenmp-version=50 %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-linux -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -fopenmp-version=50 | FileCheck %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-linux -fexceptions -fcxx-exceptions -emit-pch -o %t -fopenmp-version=50 %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-linux -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t %s -emit-llvm -o - -fopenmp-version=50 | FileCheck %s
+
+// expected-warning@138 {{unknown 'ccpu' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
// CHECK-NOT: ret i32 {{1|4|81|84}}
// CHECK-DAG: @_Z3barv = {{.*}}alias i32 (), i32 ()* @_Z3foov
@@ -38,15 +39,15 @@
int bar() { return 1; }
int bazzz();
-#pragma omp declare variant(bazzz) match(implementation = {vendor(llvm)}, device={kind(host)})
+#pragma omp declare variant(bazzz) match(implementation = {vendor(llvm)}, device={kind("host")})
int baz() { return 1; }
int test();
-#pragma omp declare variant(test) match(implementation = {vendor(llvm)}, device={kind(cpu)})
+#pragma omp declare variant(test) match(implementation = {vendor("llvm")}, device={kind(cpu)})
int call() { return 1; }
static int stat_unused_();
-#pragma omp declare variant(stat_unused_) match(implementation = {vendor(llvm)}, device={kind(cpu)})
+#pragma omp declare variant(stat_unused_) match(implementation = {vendor("llvm")}, device={kind("cpu")})
static int stat_unused() { return 1; }
static int stat_used_();
@@ -134,4 +135,7 @@
#pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm)}, device={kind(fpga)})
int fn2() { return 87; }
+#pragma omp declare variant(fn_variant2) match(device = {kind("ccpu")})
+int wrong_kind() { return 87; }
+
#endif // HEADER
Index: clang/test/OpenMP/declare_variant_messages.cpp
===================================================================
--- clang/test/OpenMP/declare_variant_messages.cpp
+++ clang/test/OpenMP/declare_variant_messages.cpp
@@ -30,25 +30,25 @@
#pragma omp declare variant(foofoo <int>) match(xxx = {vvv} xxx) // expected-error {{expected ','}} expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} expected-error {{context selector set 'xxx' is used already in the same 'omp declare variant' directive}} expected-note {{previously context selector set 'xxx' used here}}
#pragma omp declare variant(foofoo <int>) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
#pragma omp declare variant(foofoo <int>) match(implementation={xxx}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}}
-#pragma omp declare variant(foofoo <int>) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foofoo <int>) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foofoo <int>) match(implementation={vendor()}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <int>) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
+#pragma omp declare variant(foofoo <int>) match(implementation={vendor(}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
+#pragma omp declare variant(foofoo <int>) match(implementation={vendor()}) // expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}}
-#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}}
-#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(2 ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}}
+#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
+#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(2 ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error 2 {{expected ')'}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(foofoo <int>()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integral constant expression}} expected-note {{non-constexpr function 'foofoo<int>' cannot be used in a constant expression}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(5): ibm), vendor(llvm)}) // expected-error {{context trait selector 'vendor' is used already in the same 'implementation' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'vendor' used here}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}}
#pragma omp declare variant(foofoo <int>) match(device={xxx}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}}
-#pragma omp declare variant(foofoo <int>) match(device={kind}) // expected-error {{expected '(' after 'kind'}} expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foofoo <int>) match(device={kind()}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score cpu)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score( ibm)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score(2 gpu)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score(foofoo <int>()) ibm)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score(5): host), kind(llvm)}) // expected-error {{context trait selector 'kind' is used already in the same 'device' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'kind' used here}} expected-error {{expected ')' or ',' after 'score'}} expected-note {{to match this '('}} expected-error {{expected ')'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} expected-error {{unknown 'llvm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score(5): nohost), vendor(llvm)}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
+#pragma omp declare variant(foofoo <int>) match(device={kind}) // expected-error {{expected '(' after 'kind'}} expected-error {{expected ')'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}}
+#pragma omp declare variant(foofoo <int>) match(device={kind()}) // expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score cpu)}) // expected-error {{expected ')' or ',' after 'kind of device'}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score( ibm)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-error {{use of undeclared identifier 'ibm'}} expected-note 2 {{expected context trait string expression or identifier in 'kind' context selector}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score(2 gpu)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error 3 {{expected ')'}} expected-note 2 {{to match this '('}} expected-error {{expected expression}} expected-error {{trait expression must have a string type, not 'int'}} expected-error {{trait expression must be a constant string expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score(foofoo <int>()) ibm)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error {{trait expression must have a string type, not 'int'}} expected-error {{trait expression must be a constant string expression}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}} expected-warning {{unknown 'ibm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score(5): host), kind(llvm)}) // expected-error {{context trait selector 'kind' is used already in the same 'device' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'kind' used here}} expected-note {{to match this '('}} expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error 2 {{expected ')'}} expected-error {{expected expression}} expected-error {{trait expression must have a string type, not 'int'}} expected-error {{trait expression must be a constant string expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}} expected-warning {{unknown 'llvm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score(5): nohost), vendor(llvm)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-error {{trait expression must have a string type, not 'int'}} expected-error {{trait expression must be a constant string expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
int bar();
#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
@@ -74,21 +74,22 @@
#pragma omp declare variant(foofoo <T>) match(xxx = {vvv} xxx) // expected-error {{expected ','}} expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} expected-error {{context selector set 'xxx' is used already in the same 'omp declare variant' directive}} expected-note {{previously context selector set 'xxx' used here}}
#pragma omp declare variant(foofoo <T>) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}}
-#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}}
-#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(C ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}}
+#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
+#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(C ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error 2 {{expected ')'}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(foofoo <int>()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integral constant expression}} expected-note {{non-constexpr function 'foofoo<int>' cannot be used in a constant expression}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(C+5): ibm), vendor(llvm)}) // expected-error {{context trait selector 'vendor' is used already in the same 'implementation' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'vendor' used here}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}}
#pragma omp declare variant(foofoo <int>) match(device={xxx}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}}
-#pragma omp declare variant(foofoo <int>) match(device={kind}) // expected-error {{expected '(' after 'kind'}} expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foofoo <int>) match(device={kind()}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score cpu)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score( ibm)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score(C gpu)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score(foofoo <int>()) ibm)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score(C+5): host), kind(llvm)}) // expected-error {{context trait selector 'kind' is used already in the same 'device' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'kind' used here}} expected-error {{expected ')' or ',' after 'score'}} expected-note {{to match this '('}} expected-error {{expected ')'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} expected-error {{unknown 'llvm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foofoo <int>) match(device={kind(score(C+5): nohost), vendor(llvm)}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
+#pragma omp declare variant(foofoo <int>) match(device={kind}) // expected-error {{expected '(' after 'kind'}} expected-error {{expected ')'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}}
+#pragma omp declare variant(foofoo <int>) match(device={kind()}) // expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}}
+#pragma omp declare variant(foofoo <int>) match(device={kind((C))})
+#pragma omp declare variant(foofoo <int>) match(device={kind(score cpu)}) // expected-error {{expected ')' or ',' after 'kind of device'}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score( ibm)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-error {{use of undeclared identifier 'ibm'}} expected-note 2 {{expected context trait string expression or identifier in 'kind' context selector}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score(C gpu)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error 3 {{expected ')'}} expected-note 2 {{to match this '('}} expected-error {{expected expression}} expected-error {{unknown type name 'C'}} expected-note 2 {{expected context trait string expression or identifier in 'kind' context selector}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score(foofoo <int>()) ibm)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error {{trait expression must have a string type, not 'int'}} expected-error {{trait expression must be a constant string expression}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}} expected-warning {{unknown 'ibm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score(C+5): host), kind(llvm)}) // expected-error {{context trait selector 'kind' is used already in the same 'device' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'kind' used here}} expected-note {{to match this '('}} expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error 2 {{expected ')'}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}} expected-warning {{unknown 'llvm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foofoo <int>) match(device={kind(score(C+5): nohost), vendor((C)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
template <typename T, int C>
T barbar();
Index: clang/test/OpenMP/declare_variant_messages.c
===================================================================
--- clang/test/OpenMP/declare_variant_messages.c
+++ clang/test/OpenMP/declare_variant_messages.c
@@ -27,25 +27,25 @@
#pragma omp declare variant(foo) match(xxx={vvv} xxx) // expected-error {{expected ','}} expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} expected-error {{context selector set 'xxx' is used already in the same 'omp declare variant' directive}} expected-note {{previously context selector set 'xxx' used here}}
#pragma omp declare variant(foo) match(xxx={vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
#pragma omp declare variant(foo) match(implementation={xxx}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}}
-#pragma omp declare variant(foo) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foo) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foo) match(implementation={vendor()}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}}
+#pragma omp declare variant(foo) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected expression}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
+#pragma omp declare variant(foo) match(implementation={vendor(}) // expected-error {{expected expression}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
+#pragma omp declare variant(foo) match(implementation={vendor()}) // expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
#pragma omp declare variant(foo) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}}
-#pragma omp declare variant(foo) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}}
-#pragma omp declare variant(foo) match(implementation={vendor(score(2 ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}}
+#pragma omp declare variant(foo) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected expression}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
+#pragma omp declare variant(foo) match(implementation={vendor(score(2 ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error 2 {{expected ')'}} expected-error {{expected expression}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} expected-note {{expected context trait string expression or identifier in 'vendor' context selector}}
#pragma omp declare variant(foo) match(implementation={vendor(score(foo()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integer constant expression}}
#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm), vendor(llvm)}) // expected-error {{context trait selector 'vendor' is used already in the same 'implementation' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'vendor' used here}}
#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}}
#pragma omp declare variant(foo) match(device={xxx}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}}
-#pragma omp declare variant(foo) match(device={kind}) // expected-error {{expected '(' after 'kind'}} expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foo) match(device={kind(}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp declare variant(foo) match(device={kind()}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}}
-#pragma omp declare variant(foo) match(device={kind(score cpu)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foo) match(device={kind(score( ibm)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foo) match(device={kind(score(2 gpu)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foo) match(device={kind(score(foo()) ibm)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foo) match(device={kind(score(5): host), kind(llvm)}) // expected-error {{context trait selector 'kind' is used already in the same 'device' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'kind' used here}} expected-error {{expected ')' or ',' after 'score'}} expected-note {{to match this '('}} expected-error {{expected ')'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} expected-error {{unknown 'llvm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}
-#pragma omp declare variant(foo) match(device={kind(score(5): nohost), vendor(llvm)}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}}
+#pragma omp declare variant(foo) match(device={kind}) // expected-error {{expected '(' after 'kind'}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}}
+#pragma omp declare variant(foo) match(device={kind(}) // expected-error {{expected expression}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}}
+#pragma omp declare variant(foo) match(device={kind()}) // expected-error {{expected expression}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}}
+#pragma omp declare variant(foo) match(device={kind(score cpu)}) // expected-error {{expected ')' or ',' after 'kind of device'}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foo) match(device={kind(score( ibm)}) // expected-error 4 {{expected ')'}} expected-note {{to match this '('}} expected-note 2 {{expected context trait string expression or identifier in 'kind' context selector}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected expression}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foo) match(device={kind(score(2 gpu)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error 3 {{expected ')'}} expected-note 2 {{to match this '('}} expected-error {{trait expression must be a constant string expression}} expected-error {{trait expression must have a string type, not 'int'}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}} expected-error {{expected expression}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foo) match(device={kind(score(foo()) ibm)}) // expected-error {{expected ')' or ',' after 'kind of device'}} expected-error {{expected ')'}} expected-error {{trait expression must have a string type, not 'int'}} expected-error {{trait expression must be a constant string expression}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}} expected-warning {{unknown 'ibm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foo) match(device={kind(score(5): host), kind(llvm)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-error {{expected expression}} expected-error {{context trait selector 'kind' is used already in the same 'device' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'kind' used here}} expected-note {{to match this '('}} expected-error 2 {{expected ')'}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}} expected-error {{trait expression must have a string type, not 'int'}} expected-error {{trait expression must be a constant string expression}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}} expected-warning {{unknown 'llvm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
+#pragma omp declare variant(foo) match(device={kind(score(5): nohost), vendor(llvm)}) // expected-error 2 {{expected ')' or ',' after 'kind of device'}} expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-note {{expected context trait string expression or identifier in 'kind' context selector}} expected-error {{expected expression}} expected-error {{trait expression must have a string type, not 'int'}} expected-error {{trait expression must be a constant string expression}} expected-warning {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set ignored}}
int bar(void);
// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}}
Index: clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp
===================================================================
--- clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp
+++ clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp
@@ -38,7 +38,7 @@
int bar() { return 1; }
int bazzz();
-#pragma omp declare variant(bazzz) match(implementation = {vendor(llvm)})
+#pragma omp declare variant(bazzz) match(implementation = {vendor("llvm")})
int baz() { return 1; }
int test();
@@ -101,7 +101,7 @@
int prio1() { return 82; }
#pragma omp declare variant(prio) match(implementation = {vendor(llvm)})
-#pragma omp declare variant(prio1) match(implementation = {vendor(score(1): llvm)})
+#pragma omp declare variant(prio1) match(implementation = {vendor(score(1): "llvm")})
int prio_() { return 1; }
static int prio2() { return 83; }
Index: clang/test/OpenMP/declare_variant_device_kind_codegen.cpp
===================================================================
--- clang/test/OpenMP/declare_variant_device_kind_codegen.cpp
+++ clang/test/OpenMP/declare_variant_device_kind_codegen.cpp
@@ -76,14 +76,14 @@
#define WRONG host, nohost
#endif // HOST
#ifdef CPU
-#define CORRECT cpu
+#define CORRECT "cpu"
#define SUBSET host, cpu
#define WRONG cpu, gpu
#endif // CPU
#ifdef NOHOST
#define CORRECT nohost
#define SUBSET nohost, cpu
-#define WRONG nohost, host
+#define WRONG nohost, "host"
#endif // NOHOST
int foo() { return 2; }
Index: clang/test/OpenMP/declare_variant_ast_print.cpp
===================================================================
--- clang/test/OpenMP/declare_variant_ast_print.cpp
+++ clang/test/OpenMP/declare_variant_ast_print.cpp
@@ -17,9 +17,9 @@
// CHECK-NEXT: return int();
// CHECK-NEXT: }
-// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(5):ibm)},device={kind(fpga)})
-// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(0):unknown)})
-// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(0):llvm)},device={kind(cpu)})
+// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(5):"ibm")},device={kind("fpga")})
+// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(0):"unknown")})
+// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(0):"llvm")},device={kind("cpu")})
// CHECK-NEXT: int bar();
#pragma omp declare variant(foofoo <int>) match(xxx = {})
#pragma omp declare variant(foofoo <int>) match(xxx = {vvv})
@@ -28,9 +28,9 @@
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(5): ibm)}, device={kind(fpga)})
int bar();
-// CHECK: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(C + 5):ibm, xxx)},device={kind(cpu, host)})
-// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(0):unknown)})
-// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(0):llvm)},device={kind(cpu)})
+// CHECK: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(C + 5):"ibm", "xxx", "ibm")},device={kind("cpu", "host")})
+// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(0):"unknown")})
+// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(0):"llvm")},device={kind("cpu")})
// CHECK-NEXT: template <typename T, int C> T barbar();
#pragma omp declare variant(foofoo <T>) match(xxx = {})
#pragma omp declare variant(foofoo <T>) match(xxx = {vvv})
@@ -44,9 +44,9 @@
template <typename T, int C>
T barbar();
-// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(3 + 5):ibm, xxx)},device={kind(cpu, host)})
-// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(0):unknown)})
-// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(0):llvm)},device={kind(cpu)})
+// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(3 + 5):"ibm", "xxx", "ibm")},device={kind("cpu", "host")})
+// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(0):"unknown")})
+// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(0):"llvm")},device={kind("cpu")})
// CHECK-NEXT: template<> int barbar<int, 3>();
// CHECK-NEXT: int baz() {
@@ -66,8 +66,8 @@
void h_ref(C *hp, C *hp2, C *hq, C *lin) {
}
-// CHECK: #pragma omp declare variant(h_ref<C>) match(implementation={vendor(score(0):unknown)},device={kind(nohost)})
-// CHECK-NEXT: #pragma omp declare variant(h_ref<C>) match(implementation={vendor(score(0):llvm)},device={kind(gpu)})
+// CHECK: #pragma omp declare variant(h_ref<C>) match(implementation={vendor(score(0):"unknown")},device={kind("nohost")})
+// CHECK-NEXT: #pragma omp declare variant(h_ref<C>) match(implementation={vendor(score(0):"llvm")},device={kind("gpu")})
// CHECK-NEXT: template <class C> void h(C *hp, C *hp2, C *hq, C *lin) {
// CHECK-NEXT: }
#pragma omp declare variant(h_ref <C>) match(xxx = {})
@@ -77,8 +77,8 @@
void h(C *hp, C *hp2, C *hq, C *lin) {
}
-// CHECK: #pragma omp declare variant(h_ref<float>) match(implementation={vendor(score(0):unknown)},device={kind(nohost)})
-// CHECK-NEXT: #pragma omp declare variant(h_ref<float>) match(implementation={vendor(score(0):llvm)},device={kind(gpu)})
+// CHECK: #pragma omp declare variant(h_ref<float>) match(implementation={vendor(score(0):"unknown")},device={kind("nohost")})
+// CHECK-NEXT: #pragma omp declare variant(h_ref<float>) match(implementation={vendor(score(0):"llvm")},device={kind("gpu")})
// CHECK-NEXT: template<> void h<float>(float *hp, float *hp2, float *hq, float *lin) {
// CHECK-NEXT: }
@@ -86,8 +86,8 @@
// CHECK-NEXT: h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
// CHECK-NEXT: }
#pragma omp declare variant(h_ref <double>) match(xxx = {})
-#pragma omp declare variant(h_ref <double>) match(implementation={vendor(ibm)},device={kind(cpu,gpu)})
-#pragma omp declare variant(h_ref <double>) match(implementation={vendor(unknown)})
+#pragma omp declare variant(h_ref <double>) match(implementation={vendor(ibm)},device={kind("cpu","gpu")})
+#pragma omp declare variant(h_ref <double>) match(implementation={vendor("unknown")})
template <>
void h(double *hp, double *hp2, double *hq, double *lin) {
h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
@@ -97,20 +97,20 @@
int fn();
// CHECK: int fn(int);
int fn(int);
-// CHECK: #pragma omp declare variant(fn) match(implementation={vendor(score(0):unknown)},device={kind(cpu, gpu)})
-// CHECK-NEXT: #pragma omp declare variant(fn) match(implementation={vendor(score(0):llvm)})
+// CHECK: #pragma omp declare variant(fn) match(implementation={vendor(score(0):"unknown")},device={kind("cpu", "gpu")})
+// CHECK-NEXT: #pragma omp declare variant(fn) match(implementation={vendor(score(0):"llvm")})
// CHECK-NEXT: int overload();
#pragma omp declare variant(fn) match(xxx = {})
#pragma omp declare variant(fn) match(implementation={vendor(llvm)})
-#pragma omp declare variant(fn) match(implementation={vendor(unknown)},device={kind(cpu,gpu)})
+#pragma omp declare variant(fn) match(implementation={vendor(unknown)},device={kind(cpu,"gpu""")})
int overload(void);
// CHECK: int fn_deduced_variant() {
// CHECK-NEXT: return 0;
// CHECK-NEXT: }
auto fn_deduced_variant() { return 0; }
-// CHECK: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(score(0):unknown)},device={kind(gpu, nohost)})
-// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(score(0):llvm)},device={kind(cpu, host)})
+// CHECK: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(score(0):"unknown")},device={kind("gpu", "nohost")})
+// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(score(0):"llvm")},device={kind("cpu", "host")})
// CHECK-NEXT: int fn_deduced();
#pragma omp declare variant(fn_deduced_variant) match(xxx = {})
#pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(llvm)},device={kind(cpu,host)})
@@ -119,8 +119,8 @@
// CHECK: int fn_deduced_variant1();
int fn_deduced_variant1();
-// CHECK: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(score(0):unknown)},device={kind(cpu, host)})
-// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(score(0):ibm)},device={kind(gpu, nohost)})
+// CHECK: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(score(0):"unknown")},device={kind("cpu", "host")})
+// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(score(0):"ibm")},device={kind("gpu", "nohost")})
// CHECK-NEXT: int fn_deduced1() {
// CHECK-NEXT: return 0;
// CHECK-NEXT: }
@@ -140,11 +140,11 @@
// CHECK-NEXT: }
// CHECK-NEXT: void bar(int) {
// CHECK-NEXT: }
-// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(score(0):unknown)},device={kind(nohost)})
-// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::bar) match(implementation={vendor(score(0):ibm)},device={kind(cpu)})
+// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(score(0):"unknown")},device={kind("nohost")})
+// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::bar) match(implementation={vendor(score(0):"ibm")},device={kind("cpu")})
// CHECK-NEXT: void foo1() {
// CHECK-NEXT: }
-// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(score(0):unknown)},device={kind(cpu, host)})
+// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(score(0):"unknown")},device={kind("cpu", "host")})
// CHECK-NEXT: void xxx();
// CHECK-NEXT: } s;
struct SpecialFuncs {
@@ -164,7 +164,7 @@
void xxx();
} s;
-// CHECK: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(score(0):unknown)},device={kind(cpu, host)})
+// CHECK: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(score(0):"unknown")},device={kind("cpu", "host")})
// CHECK-NEXT: void SpecialFuncs::xxx() {
// CHECK-NEXT: }
void SpecialFuncs::xxx() {}
@@ -172,8 +172,8 @@
// CHECK: static void static_f_variant() {
// CHECK-NEXT: }
static void static_f_variant() {}
-// CHECK: #pragma omp declare variant(static_f_variant) match(implementation={vendor(score(0):unknown)})
-// CHECK-NEXT: #pragma omp declare variant(static_f_variant) match(implementation={vendor(score(0):llvm)},device={kind(fpga)})
+// CHECK: #pragma omp declare variant(static_f_variant) match(implementation={vendor(score(0):"unknown")})
+// CHECK-NEXT: #pragma omp declare variant(static_f_variant) match(implementation={vendor(score(0):"llvm")},device={kind("fpga")})
// CHECK-NEXT: static void static_f() {
// CHECK-NEXT: }
#pragma omp declare variant(static_f_variant) match(xxx = {})
@@ -192,7 +192,7 @@
// CHECK: int fn_linkage_variant();
// CHECK: extern "C" {
-// CHECK: #pragma omp declare variant(fn_linkage_variant) match(implementation={vendor(score(0):xxx)},device={kind(cpu, host)})
+// CHECK: #pragma omp declare variant(fn_linkage_variant) match(implementation={vendor(score(0):"xxx")},device={kind("cpu", "host")})
// CHECK: int fn_linkage();
// CHECK: }
int fn_linkage_variant();
@@ -202,9 +202,9 @@
}
// CHECK: extern "C" int fn_linkage_variant1()
-// CHECK: #pragma omp declare variant(fn_linkage_variant1) match(implementation={vendor(score(0):xxx)},device={kind(cpu, host)})
+// CHECK: #pragma omp declare variant(fn_linkage_variant1) match(implementation={vendor(score(0):"xxx")},device={kind("cpu", "host")})
// CHECK: int fn_linkage1();
extern "C" int fn_linkage_variant1();
-#pragma omp declare variant(fn_linkage_variant1) match(implementation = {vendor(xxx)},device={kind(cpu,host)})
+#pragma omp declare variant(fn_linkage_variant1) match(implementation = {vendor(xxx)},device={kind("cpu","host")})
int fn_linkage1();
Index: clang/test/OpenMP/declare_variant_ast_print.c
===================================================================
--- clang/test/OpenMP/declare_variant_ast_print.c
+++ clang/test/OpenMP/declare_variant_ast_print.c
@@ -10,17 +10,17 @@
#pragma omp declare variant(foo) match(xxx={vvv})
#pragma omp declare variant(foo) match(implementation={vendor(llvm)}, device={kind(fpga)})
#pragma omp declare variant(foo) match(implementation={vendor(llvm), xxx})
-#pragma omp declare variant(foo) match(implementation={vendor(unknown)}, device={kind(gpu)})
-#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm, xxx, ibm)}, device={kind(cpu, nohost)})
+#pragma omp declare variant(foo) match(implementation={vendor(unknown)}, device={kind("gpu")})
+#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm, "xxx", ibm)}, device={kind(cpu, nohost)})
#pragma omp declare variant(foo) match(device={kind(host)})
-#pragma omp declare variant(foo) match(device={kind(nohost), xxx})
+#pragma omp declare variant(foo) match(device={kind("nohost"), xxx})
int bar(void);
// CHECK: int foo();
-// CHECK-NEXT: #pragma omp declare variant(foo) match(device={kind(nohost)})
-// CHECK-NEXT: #pragma omp declare variant(foo) match(device={kind(host)})
-// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(5):ibm, xxx)},device={kind(cpu, nohost)})
-// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0):unknown)},device={kind(gpu)})
-// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0):llvm)})
-// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0):llvm)},device={kind(fpga)})
+// CHECK-NEXT: #pragma omp declare variant(foo) match(device={kind("nohost")})
+// CHECK-NEXT: #pragma omp declare variant(foo) match(device={kind("host")})
+// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(5):"ibm", "xxx", "ibm")},device={kind("cpu", "nohost")})
+// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0):"unknown")},device={kind("gpu")})
+// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0):"llvm")})
+// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0):"llvm")},device={kind("fpga")})
// CHECK-NEXT: int bar();
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -404,30 +404,30 @@
*std::next(Attr.ctxSelectorSets_begin(), I));
auto Ctx = static_cast<OpenMPContextSelectorKind>(
*std::next(Attr.ctxSelectors_begin(), I));
- switch (CtxSet) {
- case OMP_CTX_SET_implementation:
- switch (Ctx) {
- case OMP_CTX_vendor:
- Data.emplace_back(CtxSet, Ctx, Score, Attr.implVendors());
- break;
- case OMP_CTX_kind:
- case OMP_CTX_unknown:
- llvm_unreachable("Unexpected context selector kind.");
+ SmallVector<ExprResult, 4> Values;
+ switch (Ctx) {
+ case OMP_CTX_vendor:
+ assert(CtxSet == OMP_CTX_SET_implementation &&
+ "Expected implementation context selector set.");
+ for (Expr *Val : Attr.implVendors()) {
+ ExprResult ER = Subst(Val);
+ if (ER.isUsable())
+ Values.push_back(ER);
}
break;
- case OMP_CTX_SET_device:
- switch (Ctx) {
- case OMP_CTX_kind:
- Data.emplace_back(CtxSet, Ctx, Score, Attr.deviceKinds());
- break;
- case OMP_CTX_vendor:
- case OMP_CTX_unknown:
- llvm_unreachable("Unexpected context selector kind.");
+ case OMP_CTX_kind:
+ assert(CtxSet == OMP_CTX_SET_device &&
+ "Expected device context selector set.");
+ for (Expr *Val : Attr.deviceKinds()) {
+ ExprResult ER = Subst(Val);
+ if (ER.isUsable())
+ Values.push_back(ER);
}
break;
- case OMP_CTX_SET_unknown:
- llvm_unreachable("Unexpected context selector set kind.");
+ case OMP_CTX_unknown:
+ llvm_unreachable("Unexpected context selector kind.");
}
+ Data.emplace_back(CtxSet, Ctx, Score, Values);
}
S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first,
DeclVarData.getValue().second,
Index: clang/lib/Sema/SemaOpenMP.cpp
===================================================================
--- clang/lib/Sema/SemaOpenMP.cpp
+++ clang/lib/Sema/SemaOpenMP.cpp
@@ -29,6 +29,8 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/PointerEmbeddedInt.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ConvertUTF.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -5382,6 +5384,136 @@
return std::make_pair(FD, cast<Expr>(DRE));
}
+static llvm::Optional<std::string>
+tryConverStringLiteralToString(const StringLiteral *SL) {
+ std::string Name;
+ switch (SL->getKind()) {
+ case StringLiteral::Ascii:
+ case StringLiteral::UTF8:
+ Name = SL->getString();
+ break;
+ case StringLiteral::UTF16:
+ if (!llvm::convertUTF16ToUTF8String(
+ llvm::makeArrayRef(SL->getBytes().begin(), SL->getBytes().end()),
+ Name))
+ return llvm::None;
+ break;
+ case StringLiteral::UTF32:
+ llvm_unreachable("UTF32 is unsupported.");
+ case StringLiteral::Wide: {
+ std::wstring WideString;
+ for (int I = 0, E = SL->getLength(); I < E; ++I)
+ WideString += static_cast<wchar_t>(SL->getCodeUnit(I));
+ if (!llvm::convertWideToUTF8(WideString, Name))
+ return llvm::None;
+ break;
+ }
+ }
+ return Name;
+}
+
+static ExprResult performImplicitStringConversion(
+ Sema &S, Expr *E,
+ llvm::function_ref<bool(Sema &S, StringRef)> Checker =
+ [](Sema &S, StringRef) { return true; }) {
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ E->isInstantiationDependent())
+ return E;
+ E = S.DefaultFunctionArrayLvalueConversion(E).get();
+ if (!E)
+ return ExprError();
+ class StringConverter : public Sema::ContextualImplicitConverter {
+ public:
+ StringConverter()
+ : Sema::ContextualImplicitConverter(/*Suppress=*/false,
+ /*SuppressConversion=*/true) {}
+
+ bool match(QualType ConvType) override {
+ if (ConvType->isArrayType() || ConvType->isPointerType()) {
+ const Type *ElTy = ConvType->getPointeeOrArrayElementType();
+ return ElTy->isWideCharType() || ElTy->isCharType() ||
+ ElTy->isChar8Type() || ElTy->isChar16Type();
+ }
+ return false;
+ }
+
+ Sema::SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
+ QualType T) override {
+ return S.Diag(Loc, diag::err_omp_trait_not_string) << T;
+ }
+
+ Sema::SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
+ QualType T) override {
+ return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
+ }
+
+ Sema::SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S,
+ SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) override {
+ return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
+ }
+
+ Sema::SemaDiagnosticBuilder noteExplicitConv(Sema &S,
+ CXXConversionDecl *Conv,
+ QualType ConvTy) override {
+ return S.Diag(Conv->getLocation(), diag::note_omp_trait_conversion_here)
+ << ConvTy;
+ }
+
+ Sema::SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+ QualType T) override {
+ return S.Diag(Loc, diag::err_omp_trait_ambiguous_conversion) << T;
+ }
+
+ Sema::SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
+ QualType ConvTy) override {
+ return S.Diag(Conv->getLocation(), diag::note_omp_trait_conversion_here)
+ << ConvTy;
+ }
+
+ Sema::SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) override {
+ llvm_unreachable("conversion functions are permitted");
+ }
+ } Converter;
+
+ ExprResult ER =
+ S.PerformContextualImplicitConversion(E->getBeginLoc(), E, Converter);
+ if (!ER.isUsable())
+ return ExprError();
+ E = ER.get();
+ Expr::EvalResult Res;
+ if (!E->EvaluateAsRValue(Res, S.Context) || !Res.Val.isLValue()) {
+ S.Diag(E->getExprLoc(), diag::err_omp_trait_not_constant_string)
+ << E->getSourceRange();
+ return ExprError();
+ }
+ const auto *SL = dyn_cast_or_null<StringLiteral>(
+ Res.Val.getLValueBase().dyn_cast<const Expr *>());
+ if (!SL) {
+ S.Diag(E->getExprLoc(), diag::err_omp_trait_not_constant_string)
+ << E->getSourceRange();
+ return ExprError();
+ }
+ llvm::Optional<std::string> Value = tryConverStringLiteralToString(SL);
+ if (!Value) {
+ S.Diag(E->getExprLoc(), diag::err_omp_trait_not_constant_string)
+ << E->getSourceRange();
+ return ExprError();
+ }
+ // Normalize.
+ std::string ResString = StringRef(*Value).lower();
+ if (!Checker(S, ResString))
+ return ExprError();
+ return StringLiteral::Create(S.Context, ResString, StringLiteral::Ascii,
+ /*Pascal=*/false,
+ S.getASTContext().getStringLiteralArrayType(
+ S.getASTContext().CharTy, (*Value).length()),
+ E->getExprLoc());
+}
+
void Sema::ActOnOpenMPDeclareVariantDirective(
FunctionDecl *FD, Expr *VariantRef, SourceRange SR,
ArrayRef<OMPCtxSelectorData> Data) {
@@ -5390,7 +5522,7 @@
SmallVector<Expr *, 4> CtxScores;
SmallVector<unsigned, 4> CtxSets;
SmallVector<unsigned, 4> Ctxs;
- SmallVector<StringRef, 4> ImplVendors, DeviceKinds;
+ SmallVector<Expr *, 4> ImplVendors, DeviceKinds;
bool IsError = false;
for (const OMPCtxSelectorData &D : Data) {
OpenMPContextSelectorSetKind CtxSet = D.CtxSet;
@@ -5424,19 +5556,46 @@
else
Score = ActOnIntegerConstant(SourceLocation(), 0).get();
}
- switch (Ctx) {
- case OMP_CTX_vendor:
- assert(CtxSet == OMP_CTX_SET_implementation &&
- "Expected implementation context selector set.");
- ImplVendors.append(D.Names.begin(), D.Names.end());
- break;
- case OMP_CTX_kind:
- assert(CtxSet == OMP_CTX_SET_device &&
- "Expected device context selector set.");
- DeviceKinds.append(D.Names.begin(), D.Names.end());
- break;
- case OMP_CTX_unknown:
- llvm_unreachable("Unknown context selector kind.");
+ for (ExprResult ER : D.Names) {
+ switch (Ctx) {
+ case OMP_CTX_vendor:
+ assert(CtxSet == OMP_CTX_SET_implementation &&
+ "Expected implementation context selector set.");
+ ER = performImplicitStringConversion(*this, ER.get());
+ if (!ER.isUsable()) {
+ IsError = true;
+ continue;
+ }
+ ImplVendors.push_back(ER.get());
+ break;
+ case OMP_CTX_kind:
+ assert(CtxSet == OMP_CTX_SET_device &&
+ "Expected device context selector set.");
+ ER = performImplicitStringConversion(
+ *this, ER.get(), [ER](Sema &S, StringRef Name) {
+ if (llvm::StringSwitch<bool>(Name)
+ .Case("host", false)
+ .Case("nohost", false)
+ .Case("cpu", false)
+ .Case("gpu", false)
+ .Case("fpga", false)
+ .Default(true)) {
+ S.Diag(ER.get()->getExprLoc(),
+ diag::warn_omp_wrong_device_kind_trait)
+ << Name << ER.get()->getSourceRange();
+ return false;
+ }
+ return true;
+ });
+ if (!ER.isUsable()) {
+ IsError = true;
+ continue;
+ }
+ DeviceKinds.push_back(ER.get());
+ break;
+ case OMP_CTX_unknown:
+ llvm_unreachable("Unknown context selector kind.");
+ }
}
IsError = IsError || !Score;
CtxSets.push_back(CtxSet);
@@ -5453,6 +5612,12 @@
}
}
+ExprResult Sema::ActOnOpenMPTraitId(SourceLocation Loc, StringRef TraitName) {
+ return StringLiteral::Create(
+ Context, TraitName, StringLiteral::Ascii, /*Pascal=*/false,
+ Context.getStringLiteralArrayType(Context.CharTy, TraitName.size()), Loc);
+}
+
void Sema::markOpenMPDeclareVariantFuncsReferenced(SourceLocation Loc,
FunctionDecl *Func,
bool MightBeOdrUse) {
Index: clang/lib/Parse/ParseOpenMP.cpp
===================================================================
--- clang/lib/Parse/ParseOpenMP.cpp
+++ clang/lib/Parse/ParseOpenMP.cpp
@@ -808,6 +808,52 @@
return ScoreExpr;
}
+/// Tries to parse trait constraint as an identifier or constant string literal
+/// expression.
+/// '(' [ 'score' '(' <score _expr> ')' ':' ] <trait> { ',' <trait> } ')'
+static void
+parseTraitStringExpression(Parser &P, OpenMPContextSelectorSetKind CSSKind,
+ OpenMPContextSelectorKind CSKind, bool WithScore,
+ StringRef FullDescriptionForPuncMsg,
+ SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
+ // Parse '('.
+ BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
+ (void)T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPContextSelectorName(CSKind).data());
+ ExprResult Score;
+ if (WithScore)
+ Score = parseContextScore(P);
+ SmallVector<ExprResult, 4> Traits;
+ const Token &Tok = P.getCurToken();
+ SourceLocation PrevLoc;
+ do {
+ PrevLoc = Tok.getLocation();
+ // Parse trait value, which is constant expression of string type or
+ // identifier.
+ ExprResult Trait;
+ if (Tok.isAnyIdentifier()) {
+ Sema::OMPCtxStringType Buffer;
+ StringRef TraitName = P.getPreprocessor().getSpelling(Tok, Buffer);
+ (void)P.ConsumeToken();
+ Trait = P.getActions().ActOnOpenMPTraitId(PrevLoc, TraitName);
+ } else {
+ Trait = P.ParseConstantExpression();
+ }
+ if (!Trait.isUsable())
+ P.Diag(PrevLoc, diag::note_omp_expected_context_selector_trait_string)
+ << getOpenMPContextSelectorName(CSKind);
+ else
+ Traits.push_back(Trait);
+ if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren))
+ P.Diag(Tok, diag::err_expected_punc) << FullDescriptionForPuncMsg;
+ } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end) &&
+ PrevLoc.getRawEncoding() != Tok.getLocation().getRawEncoding());
+ // Parse ')'.
+ (void)T.consumeClose();
+ if (!Traits.empty())
+ Data.emplace_back(CSSKind, CSKind, Score, Traits);
+}
+
/// Parse context selector for 'implementation' selector set:
/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> }
/// ')'
@@ -840,39 +886,10 @@
OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
(void)P.ConsumeToken();
switch (CSKind) {
- case OMP_CTX_vendor: {
- // Parse '('.
- BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
- (void)T.expectAndConsume(diag::err_expected_lparen_after,
- CtxSelectorName.data());
- ExprResult Score = parseContextScore(P);
- llvm::UniqueVector<Sema::OMPCtxStringType> Vendors;
- do {
- // Parse <vendor>.
- StringRef VendorName;
- if (Tok.is(tok::identifier)) {
- Buffer.clear();
- VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
- (void)P.ConsumeToken();
- if (!VendorName.empty())
- Vendors.insert(VendorName);
- } else {
- P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
- << "vendor identifier"
- << "vendor"
- << "implementation";
- }
- if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
- P.Diag(Tok, diag::err_expected_punc)
- << (VendorName.empty() ? "vendor name" : VendorName);
- }
- } while (Tok.is(tok::identifier));
- // Parse ')'.
- (void)T.consumeClose();
- if (!Vendors.empty())
- Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors);
+ case OMP_CTX_vendor:
+ parseTraitStringExpression(P, OMP_CTX_SET_implementation, CSKind,
+ /*WithScore=*/true, "vendor name", Data);
break;
- }
case OMP_CTX_kind:
case OMP_CTX_unknown:
P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
@@ -916,48 +933,10 @@
OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
(void)P.ConsumeToken();
switch (CSKind) {
- case OMP_CTX_kind: {
- // Parse '('.
- BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
- (void)T.expectAndConsume(diag::err_expected_lparen_after,
- CtxSelectorName.data());
- llvm::UniqueVector<Sema::OMPCtxStringType> Kinds;
- do {
- // Parse <kind>.
- StringRef KindName;
- if (Tok.is(tok::identifier)) {
- Buffer.clear();
- KindName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
- SourceLocation SLoc = P.getCurToken().getLocation();
- (void)P.ConsumeToken();
- if (llvm::StringSwitch<bool>(KindName)
- .Case("host", false)
- .Case("nohost", false)
- .Case("cpu", false)
- .Case("gpu", false)
- .Case("fpga", false)
- .Default(true)) {
- P.Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName;
- } else {
- Kinds.insert(KindName);
- }
- } else {
- P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
- << "'host', 'nohost', 'cpu', 'gpu', or 'fpga'"
- << "kind"
- << "device";
- }
- if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
- P.Diag(Tok, diag::err_expected_punc)
- << (KindName.empty() ? "kind of device" : KindName);
- }
- } while (Tok.is(tok::identifier));
- // Parse ')'.
- (void)T.consumeClose();
- if (!Kinds.empty())
- Data.emplace_back(OMP_CTX_SET_device, CSKind, ExprResult(), Kinds);
+ case OMP_CTX_kind:
+ parseTraitStringExpression(P, OMP_CTX_SET_device, CSKind,
+ /*WithScore=*/false, "kind of device", Data);
break;
- }
case OMP_CTX_vendor:
case OMP_CTX_unknown:
P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
Index: clang/lib/CodeGen/CGOpenMPRuntime.h
===================================================================
--- clang/lib/CodeGen/CGOpenMPRuntime.h
+++ clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -14,6 +14,7 @@
#define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
#include "CGValue.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Type.h"
@@ -802,6 +803,17 @@
const OMPLoopDirective &D)>
SizeEmitter);
+ using DeclVariantAttrDataType =
+ llvm::DenseMap<const OMPDeclareVariantAttr *,
+ std::pair<bool, CompleteOMPContextSelectorData>>;
+ /// Declare variant attribute and its translated representation + bool flag
+ /// if it matches context.
+ DeclVariantAttrDataType DeclVariantAttrToCtxData;
+
+ /// Gets matching variant function for the associated declare variant
+ /// attributes.
+ const FunctionDecl *getDeclareVariantFunction(const FunctionDecl *FD);
+
public:
explicit CGOpenMPRuntime(CodeGenModule &CGM)
: CGOpenMPRuntime(CGM, ".", ".") {}
Index: clang/lib/CodeGen/CGOpenMPRuntime.cpp
===================================================================
--- clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -15,12 +15,15 @@
#include "CGOpenMPRuntime.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
+#include "clang/Basic/OpenMPKinds.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/AST/Decl.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Basic/BitmaskEnum.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SetOperations.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
@@ -11042,251 +11045,77 @@
return Address(Addr, Align);
}
-namespace {
-using OMPContextSelectorData =
- OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>;
-using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>;
-} // anonymous namespace
-
-/// Checks current context and returns true if it matches the context selector.
-template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx,
- typename... Arguments>
-static bool checkContext(const OMPContextSelectorData &Data,
- Arguments... Params) {
- assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown &&
- "Unknown context selector or context selector set.");
- return false;
-}
-
-/// Checks for implementation={vendor(<vendor>)} context selector.
-/// \returns true iff <vendor>="llvm", false otherwise.
-template <>
-bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(
- const OMPContextSelectorData &Data) {
- return llvm::all_of(Data.Names,
- [](StringRef S) { return !S.compare_lower("llvm"); });
-}
-
-/// Checks for device={kind(<kind>)} context selector.
-/// \returns true if <kind>="host" and compilation is for host.
-/// true if <kind>="nohost" and compilation is for device.
-/// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU.
-/// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN.
-/// false otherwise.
-template <>
-bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(
- const OMPContextSelectorData &Data, CodeGenModule &CGM) {
- for (StringRef Name : Data.Names) {
- if (!Name.compare_lower("host")) {
- if (CGM.getLangOpts().OpenMPIsDevice)
- return false;
- continue;
- }
- if (!Name.compare_lower("nohost")) {
- if (!CGM.getLangOpts().OpenMPIsDevice)
- return false;
+template <typename T>
+static void
+convertTraitsToUniqueStringsVector(T &&Range,
+ SmallVectorImpl<StringRef> &Values) {
+ llvm::StringSet<> UniqueStrings;
+ for (const Expr *Trait : Range) {
+ const auto *SL = cast<StringLiteral>(Trait);
+ if (!UniqueStrings.insert(SL->getString()).second)
continue;
- }
- switch (CGM.getTriple().getArch()) {
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- case llvm::Triple::aarch64_32:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- if (Name.compare_lower("cpu"))
- return false;
- break;
- case llvm::Triple::amdgcn:
- case llvm::Triple::nvptx:
- case llvm::Triple::nvptx64:
- if (Name.compare_lower("gpu"))
- return false;
- break;
- case llvm::Triple::UnknownArch:
- case llvm::Triple::arc:
- case llvm::Triple::avr:
- case llvm::Triple::bpfel:
- case llvm::Triple::bpfeb:
- case llvm::Triple::hexagon:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::msp430:
- case llvm::Triple::r600:
- case llvm::Triple::riscv32:
- case llvm::Triple::riscv64:
- case llvm::Triple::sparc:
- case llvm::Triple::sparcv9:
- case llvm::Triple::sparcel:
- case llvm::Triple::systemz:
- case llvm::Triple::tce:
- case llvm::Triple::tcele:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- case llvm::Triple::xcore:
- case llvm::Triple::le32:
- case llvm::Triple::le64:
- case llvm::Triple::amdil:
- case llvm::Triple::amdil64:
- case llvm::Triple::hsail:
- case llvm::Triple::hsail64:
- case llvm::Triple::spir:
- case llvm::Triple::spir64:
- case llvm::Triple::kalimba:
- case llvm::Triple::shave:
- case llvm::Triple::lanai:
- case llvm::Triple::wasm32:
- case llvm::Triple::wasm64:
- case llvm::Triple::renderscript32:
- case llvm::Triple::renderscript64:
- return false;
- }
- }
- return true;
-}
-
-bool matchesContext(CodeGenModule &CGM,
- const CompleteOMPContextSelectorData &ContextData) {
- for (const OMPContextSelectorData &Data : ContextData) {
- switch (Data.Ctx) {
- case OMP_CTX_vendor:
- assert(Data.CtxSet == OMP_CTX_SET_implementation &&
- "Expected implementation context selector set.");
- if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data))
- return false;
- break;
- case OMP_CTX_kind:
- assert(Data.CtxSet == OMP_CTX_SET_device &&
- "Expected device context selector set.");
- if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data,
- CGM))
- return false;
- break;
- case OMP_CTX_unknown:
- llvm_unreachable("Unknown context selector kind.");
- }
+ Values.push_back(SL->getString());
}
- return true;
}
static CompleteOMPContextSelectorData
translateAttrToContextSelectorData(ASTContext &C,
- const OMPDeclareVariantAttr *A) {
+ const OMPDeclareVariantAttr &A) {
CompleteOMPContextSelectorData Data;
- for (unsigned I = 0, E = A->scores_size(); I < E; ++I) {
- Data.emplace_back();
+ for (unsigned I = 0, E = A.scores_size(); I < E; ++I) {
auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
- *std::next(A->ctxSelectorSets_begin(), I));
+ *std::next(A.ctxSelectorSets_begin(), I));
auto Ctx = static_cast<OpenMPContextSelectorKind>(
- *std::next(A->ctxSelectors_begin(), I));
- Data.back().CtxSet = CtxSet;
- Data.back().Ctx = Ctx;
- const Expr *Score = *std::next(A->scores_begin(), I);
- Data.back().Score = Score->EvaluateKnownConstInt(C);
+ *std::next(A.ctxSelectors_begin(), I));
+ const Expr *Score = *std::next(A.scores_begin(), I);
+ SmallVector<StringRef, 8> Values;
switch (Ctx) {
case OMP_CTX_vendor:
assert(CtxSet == OMP_CTX_SET_implementation &&
"Expected implementation context selector set.");
- Data.back().Names =
- llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end());
+ convertTraitsToUniqueStringsVector(A.implVendors(), Values);
break;
case OMP_CTX_kind:
assert(CtxSet == OMP_CTX_SET_device &&
"Expected device context selector set.");
- Data.back().Names =
- llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end());
+ convertTraitsToUniqueStringsVector(A.deviceKinds(), Values);
break;
case OMP_CTX_unknown:
llvm_unreachable("Unknown context selector kind.");
}
+ Data.emplace_back(CtxSet, Ctx, Score->EvaluateKnownConstInt(C), Values);
}
return Data;
}
-static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS,
- const CompleteOMPContextSelectorData &RHS) {
- llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData;
- for (const OMPContextSelectorData &D : RHS) {
- auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx));
- Pair.getSecond().insert(D.Names.begin(), D.Names.end());
- }
- bool AllSetsAreEqual = true;
- for (const OMPContextSelectorData &D : LHS) {
- auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx));
- if (It == RHSData.end())
- return false;
- if (D.Names.size() > It->getSecond().size())
- return false;
- if (llvm::set_union(It->getSecond(), D.Names))
- return false;
- AllSetsAreEqual =
- AllSetsAreEqual && (D.Names.size() == It->getSecond().size());
- }
-
- return LHS.size() != RHS.size() || !AllSetsAreEqual;
-}
-
-static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS,
- const CompleteOMPContextSelectorData &RHS) {
- // Score is calculated as sum of all scores + 1.
- llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
- bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS);
- if (RHSIsSubsetOfLHS) {
- LHSScore = llvm::APSInt::get(0);
- } else {
- for (const OMPContextSelectorData &Data : LHS) {
- if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) {
- LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
- } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) {
- LHSScore += Data.Score.extend(LHSScore.getBitWidth());
- } else {
- LHSScore += Data.Score;
- }
- }
- }
- llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
- if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) {
- RHSScore = llvm::APSInt::get(0);
- } else {
- for (const OMPContextSelectorData &Data : RHS) {
- if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) {
- RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
- } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) {
- RHSScore += Data.Score.extend(RHSScore.getBitWidth());
- } else {
- RHSScore += Data.Score;
- }
- }
- }
- return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0;
-}
-
/// Finds the variant function that matches current context with its context
/// selector.
-static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM,
- const FunctionDecl *FD) {
+const FunctionDecl *
+CGOpenMPRuntime::getDeclareVariantFunction(const FunctionDecl *FD) {
if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
return FD;
// Iterate through all DeclareVariant attributes and check context selectors.
const OMPDeclareVariantAttr *TopMostAttr = nullptr;
- CompleteOMPContextSelectorData TopMostData;
for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
- CompleteOMPContextSelectorData Data =
- translateAttrToContextSelectorData(CGM.getContext(), A);
- if (!matchesContext(CGM, Data))
+ auto I = DeclVariantAttrToCtxData.find(A);
+ if (I == DeclVariantAttrToCtxData.end()) {
+ CompleteOMPContextSelectorData Data =
+ translateAttrToContextSelectorData(CGM.getContext(), *A);
+ I = DeclVariantAttrToCtxData.try_emplace(A).first;
+ I->getSecond().first =
+ matchesOpenMPContext(Data, CGM.getLangOpts(), CGM.getTriple());
+ if (I->getSecond().first)
+ I->getSecond().second.swap(Data);
+ }
+ // Check if the attribute does not match the context.
+ if (!I->getSecond().first)
continue;
// If the attribute matches the context, find the attribute with the highest
// score.
- if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) {
+ if (!TopMostAttr ||
+ !greaterOpenMPContextScore(DeclVariantAttrToCtxData[TopMostAttr].second,
+ I->getSecond().second))
TopMostAttr = A;
- TopMostData.swap(Data);
- }
}
if (!TopMostAttr)
return FD;
@@ -11302,7 +11131,7 @@
llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
if (Orig && !Orig->isDeclaration())
return false;
- const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D);
+ const FunctionDecl *NewFD = getDeclareVariantFunction(D);
// Emit original function if it does not have declare variant attribute or the
// context does not match.
if (NewFD == D)
Index: clang/lib/Basic/OpenMPKinds.cpp
===================================================================
--- clang/lib/Basic/OpenMPKinds.cpp
+++ clang/lib/Basic/OpenMPKinds.cpp
@@ -12,7 +12,11 @@
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
@@ -62,6 +66,194 @@
llvm_unreachable("Invalid OpenMP context selector kind");
}
+/// Checks current context and returns true if it matches the context selector.
+template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx,
+ typename... Arguments>
+static bool checkContext(const OMPContextSelectorData &Data,
+ Arguments... Params) {
+ assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown &&
+ "Unknown context selector or context selector set.");
+ return false;
+}
+
+/// Checks for implementation={vendor(<vendor>)} context selector.
+/// \returns true iff <vendor>="llvm", false otherwise.
+template <>
+bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(
+ const OMPContextSelectorData &Data) {
+ return llvm::all_of(Data.Names,
+ [](StringRef Name) { return !Name.compare("llvm"); });
+}
+
+/// Checks for device={kind(<kind>)} context selector.
+/// \returns true if <kind>="host" and compilation is for host.
+/// true if <kind>="nohost" and compilation is for device.
+/// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU.
+/// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN.
+/// false otherwise.
+template <>
+bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, bool, const llvm::Triple &>(
+ const OMPContextSelectorData &Data, bool IsOpenMPDevice,
+ const llvm::Triple &Triple) {
+ for (StringRef Name : Data.Names) {
+ if (!Name.compare("host")) {
+ if (IsOpenMPDevice)
+ return false;
+ continue;
+ }
+ if (!Name.compare_lower("nohost")) {
+ if (!IsOpenMPDevice)
+ return false;
+ continue;
+ }
+ switch (Triple.getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::aarch64_32:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ if (Name.compare_lower("cpu"))
+ return false;
+ break;
+ case llvm::Triple::amdgcn:
+ case llvm::Triple::nvptx:
+ case llvm::Triple::nvptx64:
+ if (Name.compare_lower("gpu"))
+ return false;
+ break;
+ case llvm::Triple::UnknownArch:
+ case llvm::Triple::arc:
+ case llvm::Triple::avr:
+ case llvm::Triple::bpfel:
+ case llvm::Triple::bpfeb:
+ case llvm::Triple::hexagon:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::msp430:
+ case llvm::Triple::r600:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcv9:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::systemz:
+ case llvm::Triple::tce:
+ case llvm::Triple::tcele:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::xcore:
+ case llvm::Triple::le32:
+ case llvm::Triple::le64:
+ case llvm::Triple::amdil:
+ case llvm::Triple::amdil64:
+ case llvm::Triple::hsail:
+ case llvm::Triple::hsail64:
+ case llvm::Triple::spir:
+ case llvm::Triple::spir64:
+ case llvm::Triple::kalimba:
+ case llvm::Triple::shave:
+ case llvm::Triple::lanai:
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ case llvm::Triple::renderscript32:
+ case llvm::Triple::renderscript64:
+ return false;
+ }
+ }
+ return true;
+}
+
+bool clang::matchesOpenMPContext(
+ const CompleteOMPContextSelectorData &ContextData, const LangOptions &LO,
+ const llvm::Triple &Triple) {
+ for (const OMPContextSelectorData &Data : ContextData) {
+ switch (Data.Ctx) {
+ case OMP_CTX_vendor:
+ assert(Data.CtxSet == OMP_CTX_SET_implementation &&
+ "Expected implementation context selector set.");
+ if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data))
+ return false;
+ break;
+ case OMP_CTX_kind:
+ assert(Data.CtxSet == OMP_CTX_SET_device &&
+ "Expected device context selector set.");
+ if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, bool,
+ const llvm::Triple &>(Data, LO.OpenMPIsDevice, Triple))
+ return false;
+ break;
+ case OMP_CTX_unknown:
+ llvm_unreachable("Unknown context selector kind.");
+ }
+ }
+ return true;
+}
+
+static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS,
+ const CompleteOMPContextSelectorData &RHS) {
+ llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData;
+ for (const OMPContextSelectorData &D : RHS) {
+ auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx));
+ Pair.getSecond().insert(D.Names.begin(), D.Names.end());
+ }
+ bool AllSetsAreEqual = true;
+ for (const OMPContextSelectorData &D : LHS) {
+ auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx));
+ if (It == RHSData.end())
+ return false;
+ if (D.Names.size() > It->getSecond().size())
+ return false;
+ if (llvm::set_union(It->getSecond(), D.Names))
+ return false;
+ AllSetsAreEqual =
+ AllSetsAreEqual && (D.Names.size() == It->getSecond().size());
+ }
+
+ return LHS.size() != RHS.size() || !AllSetsAreEqual;
+}
+
+bool clang::greaterOpenMPContextScore(
+ const CompleteOMPContextSelectorData &LHS,
+ const CompleteOMPContextSelectorData &RHS) {
+ // Score is calculated as sum of all scores + 1.
+ llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
+ bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS);
+ if (RHSIsSubsetOfLHS) {
+ LHSScore = llvm::APSInt::get(0);
+ } else {
+ for (const OMPContextSelectorData &Data : LHS) {
+ if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) {
+ LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
+ } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) {
+ LHSScore += Data.Score.extend(LHSScore.getBitWidth());
+ } else {
+ LHSScore += Data.Score;
+ }
+ }
+ }
+ llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
+ if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) {
+ RHSScore = llvm::APSInt::get(0);
+ } else {
+ for (const OMPContextSelectorData &Data : RHS) {
+ if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) {
+ RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
+ } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) {
+ RHSScore += Data.Score.extend(RHSScore.getBitWidth());
+ } else {
+ RHSScore += Data.Score;
+ }
+ }
+ }
+ return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0;
+}
+
OpenMPDirectiveKind clang::getOpenMPDirectiveKind(StringRef Str) {
return llvm::StringSwitch<OpenMPDirectiveKind>(Str)
#define OPENMP_DIRECTIVE(Name) .Case(#Name, OMPD_##Name)
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -9413,7 +9413,7 @@
/// Struct to store the context selectors info for declare variant directive.
using OMPCtxStringType = SmallString<8>;
using OMPCtxSelectorData =
- OpenMPCtxSelectorData<SmallVector<OMPCtxStringType, 4>, ExprResult>;
+ OpenMPCtxSelectorData<SmallVector<ExprResult, 4>, ExprResult>;
/// Checks if the variant/multiversion functions are compatible.
bool areMultiversionVariantFunctionsCompatible(
@@ -9424,6 +9424,9 @@
const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported,
bool ConstexprSupported, bool CLinkageMayDiffer);
+ /// Builds StringLiteral out of the specified trait name.
+ ExprResult ActOnOpenMPTraitId(SourceLocation Loc, StringRef TraitName);
+
/// Function tries to capture lambda's captured variables in the OpenMP region
/// before the original lambda is captured.
void tryCaptureOpenMPLambdas(ValueDecl *V);
Index: clang/include/clang/Basic/OpenMPKinds.h
===================================================================
--- clang/include/clang/Basic/OpenMPKinds.h
+++ clang/include/clang/Basic/OpenMPKinds.h
@@ -14,9 +14,16 @@
#ifndef LLVM_CLANG_BASIC_OPENMPKINDS_H
#define LLVM_CLANG_BASIC_OPENMPKINDS_H
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+ class Triple;
+} // namespace llvm
namespace clang {
+class LangOptions;
/// OpenMP context selector sets.
enum OpenMPContextSelectorSetKind {
@@ -57,6 +64,22 @@
Names(Names.begin(), Names.end()) {}
};
+/// Data types for handling context selectors.
+using OMPContextSelectorData =
+ OpenMPCtxSelectorData<llvm::SmallVector<llvm::StringRef, 4>, llvm::APSInt>;
+using CompleteOMPContextSelectorData =
+ llvm::SmallVector<OMPContextSelectorData, 4>;
+
+/// nalyzes current context and returns true if it matches specified set of
+/// context traits, false otherwise.
+bool matchesOpenMPContext(const CompleteOMPContextSelectorData &ContextData,
+ const LangOptions &LO, const llvm::Triple &Triple);
+
+/// Compares two context selector sets and returns true if the score of the \p
+/// LHS is greater or equal than the scoe of \p RHS.
+bool greaterOpenMPContextScore(const CompleteOMPContextSelectorData &LHS,
+ const CompleteOMPContextSelectorData &RHS);
+
/// OpenMP directives.
enum OpenMPDirectiveKind {
#define OPENMP_DIRECTIVE(Name) \
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9695,6 +9695,18 @@
def note_omp_marked_declare_variant_here : Note<"marked as 'declare variant' here">;
def err_omp_one_defaultmap_each_category: Error<
"at most one defaultmap clause for each variable-category can appear on the directive">;
+def err_omp_trait_not_string : Error<
+ "trait expression must have a string type, not %0">;
+def note_omp_trait_conversion_here : Note<
+ "conversion to a string type %0 declared here">;
+def err_omp_trait_ambiguous_conversion : Error<
+ "ambiguous conversion from type %0 to a string type">;
+def err_omp_trait_not_constant_string : Error<
+ "trait expression must be a constant string expression">;
+def warn_omp_wrong_device_kind_trait: Warning<
+ "unknown '%0' device kind trait in the 'device' context selector "
+ "set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga', set "
+ "ignored">, InGroup<SourceUsesOpenMP>;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1218,8 +1218,6 @@
def warn_omp_declare_variant_cs_name_expected : Warning<
"unknown context selector in '%0' context selector set of 'omp declare variant' directive, ignored">,
InGroup<OpenMPClauses>;
-def err_omp_declare_variant_item_expected : Error<
- "expected %0 in '%1' context selector of '%2' selector set of 'omp declare variant' directive">;
def err_omp_declare_variant_ctx_set_mutiple_use : Error<
"context selector set '%0' is used already in the same 'omp declare variant' directive">;
def note_omp_declare_variant_ctx_set_used_here : Note<
@@ -1232,9 +1230,8 @@
def warn_omp_more_one_device_type_clause : Warning<
"more than one 'device_type' clause is specified">,
InGroup<OpenMPClauses>;
-def err_omp_wrong_device_kind_trait : Error<
- "unknown '%0' device kind trait in the 'device' context selector set, expected"
- " one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'">;
+def note_omp_expected_context_selector_trait_string : Note<
+ "expected context trait string expression or identifier in '%0' context selector">;
// Pragma loop support.
def err_pragma_loop_missing_argument : Error<
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -3318,8 +3318,8 @@
VariadicExprArgument<"Scores">,
VariadicUnsignedArgument<"CtxSelectorSets">,
VariadicUnsignedArgument<"CtxSelectors">,
- VariadicStringArgument<"ImplVendors">,
- VariadicStringArgument<"DeviceKinds">
+ VariadicExprArgument<"ImplVendors">,
+ VariadicExprArgument<"DeviceKinds">
];
let AdditionalMembers = [{
void printScore(raw_ostream & OS, const PrintingPolicy &Policy, unsigned I) const {
@@ -3373,9 +3373,11 @@
OS << "vendor(";
printScore(OS, Policy, K);
if (implVendors_size() > 0) {
- OS << *implVendors(). begin();
- for (StringRef VendorName : llvm::drop_begin(implVendors(), 1))
- OS << ", " << VendorName;
+ (*implVendors().begin())->printPretty(OS, nullptr, Policy);
+ for (const Expr *VE : llvm::drop_begin(implVendors(), 1)) {
+ OS << ", ";
+ VE->printPretty(OS, nullptr, Policy);
+ }
}
OS << ")";
break;
@@ -3384,9 +3386,11 @@
"Expected device context selector set.");
OS << "kind(";
if (deviceKinds_size() > 0) {
- OS << *deviceKinds().begin();
- for (StringRef KindName : llvm::drop_begin(deviceKinds(), 1))
- OS << ", " << KindName;
+ (*deviceKinds().begin())->printPretty(OS, nullptr, Policy);
+ for (const Expr *KE : llvm::drop_begin(deviceKinds(), 1)) {
+ OS << ", ";
+ KE->printPretty(OS, nullptr, Policy);
+ }
}
OS << ")";
break;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits