ABataev updated this revision to Diff 233375. ABataev added a comment. Fixed formatting
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70973/new/ https://reviews.llvm.org/D70973 Files: clang/include/clang/AST/Decl.h 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/AST/Decl.cpp clang/lib/Basic/OpenMPKinds.cpp clang/lib/CodeGen/CGOpenMPRuntime.cpp 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@141 {{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 @@ -39,17 +40,17 @@ 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_no_emit() { 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_no_emit) match(implementation = {vendor(xxx)}, device={kind(gpu)}) +#pragma omp declare variant(stat_unused_) match(implementation = {vendor("llvm")}, device={kind("cpu")}) static int stat_unused() { return 1; } static int stat_used_(); @@ -137,6 +138,9 @@ #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; } + #pragma omp declare variant(stat_unused_no_emit) match(implementation = {vendor(xxx)}, device={kind(gpu)}) template <typename T> static T stat_unused_T() { return 88; } 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 @@ -409,30 +409,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 @@ -30,7 +30,9 @@ #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/PointerEmbeddedInt.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" +#include "llvm/Support/ConvertUTF.h" using namespace clang; using namespace llvm::omp; @@ -5393,6 +5395,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) { @@ -5401,7 +5533,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; @@ -5435,19 +5567,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); @@ -5464,6 +5623,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 @@ -824,6 +824,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> } /// ')' @@ -856,39 +902,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) @@ -932,48 +949,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.cpp =================================================================== --- clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -11044,259 +11044,6 @@ 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; - 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."); - } - } - return true; -} - -static CompleteOMPContextSelectorData -translateAttrToContextSelectorData(ASTContext &C, - const OMPDeclareVariantAttr *A) { - CompleteOMPContextSelectorData Data; - for (unsigned I = 0, E = A->scores_size(); I < E; ++I) { - Data.emplace_back(); - auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( - *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); - 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()); - 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()); - break; - case OMP_CTX_unknown: - llvm_unreachable("Unknown context selector kind."); - } - } - 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) { - 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)) - continue; - // If the attribute matches the context, find the attribute with the highest - // score. - if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) { - TopMostAttr = A; - TopMostData.swap(Data); - } - } - if (!TopMostAttr) - return FD; - return cast<FunctionDecl>( - cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) - ->getDecl()); -} - bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { const auto *D = cast<FunctionDecl>(GD.getDecl()); // If the original function is defined already, use its definition. @@ -11304,7 +11051,7 @@ llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); if (Orig && !Orig->isDeclaration()) return false; - const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); + const FunctionDecl *NewFD = D->getOpenMPDeclareVariantFunction(); // 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> @@ -63,6 +67,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; +} + OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) { // 'flush' clause cannot be specified explicitly, because this is an implicit // clause for 'flush' directive. If the 'flush' clause is explicitly specified Index: clang/lib/AST/Decl.cpp =================================================================== --- clang/lib/AST/Decl.cpp +++ clang/lib/AST/Decl.cpp @@ -2878,6 +2878,77 @@ 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; + Values.push_back(SL->getString()); + } +} + +static CompleteOMPContextSelectorData +translateAttrToContextSelectorData(ASTContext &C, + const OMPDeclareVariantAttr &A) { + CompleteOMPContextSelectorData Data; + for (unsigned I = 0, E = A.scores_size(); I < E; ++I) { + auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( + *std::next(A.ctxSelectorSets_begin(), I)); + auto Ctx = static_cast<OpenMPContextSelectorKind>( + *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."); + convertTraitsToUniqueStringsVector(A.implVendors(), Values); + break; + case OMP_CTX_kind: + assert(CtxSet == OMP_CTX_SET_device && + "Expected device context selector set."); + 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; +} + +FunctionDecl *FunctionDecl::getOpenMPDeclareVariantFunction() { + FunctionDecl *FD = this; + if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) + return FD; + // Iterate through all DeclareVariant attributes and check context selectors. + const OMPDeclareVariantAttr *TopMostAttr = nullptr; + CompleteOMPContextSelectorData BestData; + for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { + CompleteOMPContextSelectorData Data = + translateAttrToContextSelectorData(getASTContext(), *A); + // Check if the attribute does not match the context. + if (!matchesOpenMPContext(Data, getASTContext().getLangOpts(), + getASTContext().getTargetInfo().getTriple())) + continue; + // If the attribute matches the context, find the attribute with the highest + // score. + if (!TopMostAttr || !greaterOpenMPContextScore(BestData, Data)) { + TopMostAttr = A; + BestData.swap(Data); + } + } + if (!TopMostAttr) + return FD; + return cast<FunctionDecl>( + cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) + ->getDecl()); +} + Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { if (!hasBody(Definition)) return nullptr; Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -9434,7 +9434,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( @@ -9445,6 +9445,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,10 +14,17 @@ #ifndef LLVM_CLANG_BASIC_OPENMPKINDS_H #define LLVM_CLANG_BASIC_OPENMPKINDS_H +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" +namespace llvm { +class Triple; +} // namespace llvm + namespace clang { +class LangOptions; /// OpenMP context selector sets. enum OpenMPContextSelectorSetKind { @@ -58,6 +65,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>; + +/// Analyzes 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. using OpenMPDirectiveKind = llvm::omp::Directive; Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9718,6 +9718,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; Index: clang/include/clang/AST/Decl.h =================================================================== --- clang/include/clang/AST/Decl.h +++ clang/include/clang/AST/Decl.h @@ -2052,6 +2052,13 @@ return const_cast<FunctionDecl *>(this)->getDefinition(); } + /// Gets matching OpenMP variant function for the associated declare variant + /// attributes. + FunctionDecl *getOpenMPDeclareVariantFunction(); + const FunctionDecl *getOpenMPDeclareVariantFunction() const { + return const_cast<FunctionDecl *>(this)->getOpenMPDeclareVariantFunction(); + } + /// Retrieve the body (definition) of the function. The function body might be /// in any of the (re-)declarations of this function. The variant that accepts /// a FunctionDecl pointer will set that function declaration to the actual
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits