-
Notifications
You must be signed in to change notification settings - Fork 769
cpp version mismatch diagnostics + tests #2297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cpp version mismatch diagnostics + tests #2297
Conversation
//===----------------------------------------------------------------------===// | ||
// ----------------------------------------------------------------------------- | ||
#include <CL/sycl.hpp> | ||
#include <iostream> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need an kernel doing something for this test, do you? An empty kernel is sufficient.
#include <iostream> | |
namespace sycl = cl::sycl; | |
int main() { | |
sycl::queue().submit([&](sycl::handler& cgh) { | |
cgh.parallel_for<class task>(sycl::nd_range<1>(16,16), | |
[=](auto item) { | |
});}); | |
} | |
BTW: Why don't we write out an empty integration header if `-fsycl-int-header` is provided but there is no kernel in the source file? I can see this causing an issue if users set up their build system but some files don't (yet) have a kernel. Than the required include file is missing. |
// RUN: FileCheck -input-file=sycl_ihdr_a.h %s | ||
// CHECK: #define STD_CPP_VERSION | ||
// CHECK-NEXT: #if __cplusplus != STD_CPP_VERSION | ||
// CHECK-NEXT: #error "C++ version for host compilation does not match C++ version used for device compilation" | ||
// CHECK-NEXT: #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do integration header testing in FE tests. Such tests are placed in clang/test/CodeGenSYCL .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Capturing llvm-lit test transfer into a separate issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the problem with llvm-lit?
clang/lib/Sema/SemaSYCL.cpp
Outdated
@@ -2728,6 +2728,23 @@ static void emitKernelNameType(QualType T, ASTContext &Ctx, raw_ostream &OS, | |||
emitWithoutAnonNamespaces(OS, T.getCanonicalType().getAsString(TypePolicy)); | |||
} | |||
|
|||
int SYCLIntegrationHeader::getCppVersion() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't clang already have similar stuff?
@erichkeane , don't you know?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we have exactly this function, but we DO similar logic for the __cpluplus macro in the preprocessor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I understand the motivation here, I think that there isn't a good way about this.
The __cplusplus macro is inconsistent between compilers that otherwise would be compatible (such as, we SHOULD be OK with a slightly older version of Clang where C++2a was 201911L).
Additionally, IS there a problem if the host is a slightly newer/older version?
Finally, this is going to be a maintenance headache (the rarity of is change, every 3 years, is going to result in us forgetting to update this) and massively error prone, and doesn't do what we need it to do.
I just think this is a bad idea.
clang/lib/Sema/SemaSYCL.cpp
Outdated
@@ -2728,6 +2728,23 @@ static void emitKernelNameType(QualType T, ASTContext &Ctx, raw_ostream &OS, | |||
emitWithoutAnonNamespaces(OS, T.getCanonicalType().getAsString(TypePolicy)); | |||
} | |||
|
|||
int SYCLIntegrationHeader::getCppVersion() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we have exactly this function, but we DO similar logic for the __cpluplus macro in the preprocessor.
clang/lib/Sema/SemaSYCL.cpp
Outdated
if (cpp_version != -1) { | ||
O << "#define STD_CPP_VERSION "; | ||
O << cpp_version << "\n"; | ||
O << "#if __cplusplus != STD_CPP_VERSION\n"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually pretty risky when using other compilers. MSVC for example used a 1997 date until just recently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handling windows resolve and/or linux specifiers in a separate issue/ticket
Signed-off-by: Joey Genfi <joey.genfi@intel.com>
// RUN: FileCheck -input-file=sycl_ihdr_a.h %s | ||
// CHECK: #define STD_CPP_VERSION | ||
// CHECK-NEXT: #if __cplusplus != STD_CPP_VERSION | ||
// CHECK-NEXT: #error "C++ version for host compilation does not match C++ version used for device compilation" | ||
// CHECK-NEXT: #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the problem with llvm-lit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I understand the motivation here, I think that there isn't a good way about this.
The __cplusplus macro is inconsistent between compilers that otherwise would be compatible (such as, we SHOULD be OK with a slightly older version of Clang where C++2a was 201911L).
Additionally, IS there a problem if the host is a slightly newer/older version?
Finally, this is going to be a maintenance headache (the rarity of is change, every 3 years, is going to result in us forgetting to update this) and massively error prone, and doesn't do what we need it to do.
I just think this is a bad idea.
I'm not going to approve this patch unless these concerns are resolved.
@JoeyGIntel Could you please resolve concern mentioned above? |
Signed-off-by: Joey Genfi <joey.genfi@intel.com>
@JoeyGIntel, please, fix pre-commit checks. |
@JoeyGIntel, sycl tests LGTM. Please address the review comments and fix the fails. |
@@ -210,8 +210,7 @@ bool Sema::isKnownGoodSYCLDecl(const Decl *D) { | |||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { | |||
const IdentifierInfo *II = FD->getIdentifier(); | |||
const DeclContext *DC = FD->getDeclContext(); | |||
if (II && II->isStr("__spirv_ocl_printf") && | |||
!FD->isDefined() && | |||
if (II && II->isStr("__spirv_ocl_printf") && !FD->isDefined() && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated change.
ClangFormat probably did this when you ran it locally. If you are using the script for clang-format, please only run it for your changes i.e. the diff.
@@ -2298,8 +2297,7 @@ void Sema::finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller, | |||
bool NotDefinedNoAttr = !Callee->isDefined() && !HasAttr; | |||
|
|||
if (NotDefinedNoAttr && !Callee->getBuiltinID()) { | |||
Diag(Loc, diag::err_sycl_restrict) | |||
<< Sema::KernelCallUndefinedFunction; | |||
Diag(Loc, diag::err_sycl_restrict) << Sema::KernelCallUndefinedFunction; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated change.
@@ -0,0 +1,38 @@ | |||
// >> ---- device compilation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this test is only to check the content of integration header, please move this test to clang/test/CodeGenSYCL. The test will need to be modified when you move it. You can check test integration_header.cpp (in CodeGenSYCL) to see how to use the 'fake' headers and kernel calls. License information can also be removed.
O << CppVersion << "\n"; | ||
O << "#if (__cplusplus <= 201112L) && (STD_CPP_VERSION >= 201401L) \n"; | ||
O << "#error \"C++ version (std=c++11 or less) for host compilation cannot " | ||
"be matched with C++ version (std=c++14 or greater) for device " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change 'cannot be matched' to 'is incompatible'?
@erichkeane can you take a look at the latest patch. It has been modified to throw the error only when host version is C++11 (or less) and device version is C++14 (or greater) |
This doesn't solve the problem actually. The issue is that MSVC until recently (and on hosts we want to support), made this number always 1997. It still supported a large amount of C++17 features at that point. |
|
||
// >> ---- code generation checks | ||
// RUN: FileCheck -input-file=sycl_ihdr_a.h %s | ||
// CHECK: #define STD_CPP_VERSION |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a good reason to extract this into a macro instead of just putting it right into the conditional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean just call getCppVersion(S)
in conditional? I don't see why that can't be done. @JoeyGIntel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, we ALREADY know if STD_CPP_VERSION >= 201401L, so emitting it int-header is foolish. We should just omit this enitre set of code if that isn't the case .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AND, it simplifies the patch a ton, you don't even NEED getCppVersion anymore, since you can just do:
if (LangOpts.CPlusPlus14) {
os << "#if (__cplusplus <=201112L)\n";
os << " #error ...\n";
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this idea a lot!
// RUN: FileCheck -input-file=sycl_ihdr_a.h %s | ||
// CHECK: #define STD_CPP_VERSION | ||
// CHECK-NEXT: #if (__cplusplus <= 201112L) && (STD_CPP_VERSION >= 201401L) | ||
// CHECK-NEXT: #error "C++ version (std=c++11 or less) for host compilation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wording needs work, but this is perhaps less harmful if it is a pragma-warning (assuming this isn't included as a system header).
Hmm...How can we resolve this then? For MSVC, how do we detect if host and device C++ versions are incompatible if MSVC (and other compilers if any) doesn't maintain this consistently? |
That is why I said initially (I think...) that there just isn't a good way to implement this. Even the current implementation is going to just NOT WORK on any pre-2019 MSVC. We could detect that and just bail (#if _MSVC && __cplusplus==1997xxxx), but I'm still unconvinced this problem is sufficiently motivated. |
In theory it is possible to use |
Thanks for explanation. I think we need to check for >=C++14 when generating the integration header (device) and <= C++11 when using the integration header (host). For the former, @erichkeane suggested using LangOpts.CPlusPlus14. Don't know off the top of my head, how clang sets this. Might be interesting to see how MSVC is handled by clang for this LangOpt. |
@JoeyGIntel What is the motivation for this patch? What issues are we seeing? |
This actually doesn't work for the compilers from microsoft BEFORE the switch to correctly reporting __cplusplus, right? The ones I'm concerned about are when __cplusplus reported 199711L despite having sufficient C++14 or C++17 support. However, properly using the _MSC_VER value would require figuring out the first version of MSVC that we believe matches the required list of supported features. |
The LangOpts c++ versions are all set if AT LEAST that set is supported. For example, CPlusPlus17 ALSO sets CPlusPlus14, CPlusPlus11 and CPlusPlus. So checking CPlusPlus14 is sufficient to check for AT LEAST C++14. |
This functionality was added in SPIR-V 1.2 and allows using an <id> to set the execution modes SubgroupsPerWorkgroupId, LocalSizeId, and LocalSizeHintI, and others. Original commit: KhronosGroup/SPIRV-LLVM-Translator@10b0aab
fix path to markdown results in benchmarks workflow
Summary
Adding auto-generated C++ version mismatch diagnostics to the integration header generation files to allow version mismatch detection for separate compilation flows.
Detail
An issue occurs when the C++ version used for the device compilation equals C++14 and the version used during the host compilation equals C++11. For example, when the representation of an object in one C++ version by a compiler is different from that of another C++ version for the same object.
With this fix, the two versions (device C++ version and host C++ version) will be captured in the auto-generated integration header. When the integration header is run during the host compilation, the versions will be compared and a diagnostic can be reported.
This change set specifically covers cases where: C++ version (std=C++11 or less) for host compilation cannot be matched with C++ version (std=C++14 or greater) for device compilation.