In this patch we provide additional and comprehensive tests for the ODR
handling strategies. This is the continuation of
https://reviews.llvm.org/D59692.
Details
- Reviewers
shafik a_sidorin balazske a.sidorin - Commits
- rGc65628a49ad3: [ASTImporter][NFC] Add comprehensive tests for ODR violation handling strategies
rL372564: [ASTImporter][NFC] Add comprehensive tests for ODR violation handling strategies
rC372564: [ASTImporter][NFC] Add comprehensive tests for ODR violation handling strategies
Diff Detail
- Repository
- rL LLVM
Event Timeline
clang/unittests/AST/ASTImporterODRStrategiesTest.cpp | ||
---|---|---|
1 ↗ | (On Diff #217899) | Change the file name here? |
clang/unittests/AST/ASTImporterODRStrategiesTest.cpp | ||
---|---|---|
36 ↗ | (On Diff #218625) | Probably for (non-member?) functions there is no possibility for conflicting definition (for same prototype)? This can be the case if the function body is different but this is not checked now. For functions no name conflict happens because of overload, at least if C++ is used. I think the tests here with functions are not needed or only for C language. (Do all these pass?) |
128 ↗ | (On Diff #218625) | Is this better? struct VariableTemplate { using DeclTy = VarTemplateDecl; static constexpr auto *Prototype = "template <class T> extern T X;"; static constexpr auto *ConflictingPrototype = "template <class T> extern float X;"; static constexpr auto *Definition = R"( template <class T> T X; template <> int X<int>; )"; static constexpr auto *ConflictingDefinition = R"( template <class T> T X; template <> float X<int>; )"; static constexpr auto *ConflictingProtoDef = R"( template <class T> float X; template <> float X<int>; )"; // There is no matcher for varTemplateDecl so use a work-around. BindableMatcher<Decl> getPattern() { return namedDecl(hasName("X"), unless(isImplicit()), has(templateTypeParmDecl())); } }; |
151 ↗ | (On Diff #218625) | FunctionTemplate and FunctionTemplateSpec are missing? |
clang/unittests/AST/ASTImporterODRStrategiesTest.cpp | ||
---|---|---|
36 ↗ | (On Diff #218625) | We do check these only with lang C. That is handled with the getLang() function, each test use that language which is provided by the getLang() function. ConflictingDefinition is needed, because we test cases like this (in ImportConflictingDefAfterProto): void X(int); // TU1 void X(double a) {}; // TU2 This is handled differently by the distinct strategies. I.e. the conflicting definition is not imported when the strategy is Conservative. When it is Liberal then it is imported. |
128 ↗ | (On Diff #218625) | I did not want to get this from our fork, becuase template <> int X<int>; seems to be a specialization of a variable template, and that confuses me. Also, structural equivalency is completely wrong with variable templates, so they are here only for the sake of completeness, the tests which use them are all disabled. |
151 ↗ | (On Diff #218625) | Yes, because FunctionTemplates overload with each other. So they are imported always "liberally". There is no point to liberally import conflicting FunctionTemplateSpecializations. Perhaps we should remove struct ClassTemplateSpec as well from here (?). @shafik , what do you think about this? |
OK
Probably the ClassTemplateSpec can not be handled in liberal way because the AST data structure for template specializations do not allow multiple instances with same argument values?
Yes exactly, that is the case. The implementation holds the specializations in a set, and the key within the set is a hash calculated from the arguments of the specialization.
All specializations are implemented like this, this includes variabletemplatespecializations too.
clang/unittests/AST/ASTImporterODRStrategiesTest.cpp | ||
---|---|---|
118 ↗ | (On Diff #218625) | Note this is not well-formed b/c it is not initialized, see godbolt |
clang/unittests/AST/ASTImporterODRStrategiesTest.cpp | ||
---|---|---|
118 ↗ | (On Diff #218625) | But it would be ok combined w/ a specialization: template <> constexpr int X<int> = 0; |
clang/unittests/AST/ASTImporterODRStrategiesTest.cpp | ||
---|---|---|
151 ↗ | (On Diff #218625) | What you say about FunctionTemplateSpecializations and ClassTemplateSpecializations seems to make sense, importing them liberally would require more than work in the importer. |
clang/unittests/AST/ASTImporterODRStrategiesTest.cpp | ||
---|---|---|
118 ↗ | (On Diff #218625) | Ok, I changed the template to have an init expression: template <class T> constexpr T X = 0; |
151 ↗ | (On Diff #218625) | I have added FunctionTemplate, FunctionTemplateSpec and VarTemplateSpec. FunctionTemplate decls overload with each other. Thus, they are imported always "liberally". I have added a test for that. Class and variable template specializations/instantiatons are always imported conservatively, because the AST holds the specializations in a set, and the key within the set is a hash calculated from the arguments of the specialization. Function template specializations are different. They are all "full" |
- Initialize the variable template in test
- Clean up tests for fun templates and for specializations
I have reorganized the tests to group the ones which test ODR violation strategy independent behaviour.
clang/unittests/AST/ASTImporterODRStrategiesTest.cpp | ||
---|---|---|
274 ↗ | (On Diff #220130) | This should be called ImportedF instead of PrevF? |
- PrevF->ImportedF, remove braces
clang/unittests/AST/ASTImporterODRStrategiesTest.cpp | ||
---|---|---|
274 ↗ | (On Diff #220130) | Ok, renamed to ImportedF. |
@martong This is failing on windows buildbots: http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/19808