tmroeder updated this revision to Diff 311961. tmroeder added a comment. Explicitly instantiate the templates in the structural-equivalence test.
This seems to work correctly on Windows, and it avoids the need for the extra hooks in the test framework. So, this diff removes those hooks as well as the nullptr test. The latter is no longer needed either because the templates get explicitly instantiated, even under delayed template expansion. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D92600/new/ https://reviews.llvm.org/D92600 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/AST/ASTImporter.cpp clang/lib/AST/ASTStructuralEquivalence.cpp clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/lib/Analysis/ExprMutationAnalyzer.cpp clang/test/ASTMerge/generic-selection-expr/Inputs/generic.c clang/test/ASTMerge/generic-selection-expr/Inputs/generic.cpp clang/test/ASTMerge/generic-selection-expr/test.c clang/test/ASTMerge/generic-selection-expr/test.cpp clang/unittests/AST/ASTImporterTest.cpp clang/unittests/AST/StructuralEquivalenceTest.cpp clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -982,6 +982,11 @@ EXPECT_TRUE(matches("int* i = __null;", gnuNullExpr())); } +TEST_P(ASTMatchersTest, GenericSelectionExpr) { + EXPECT_TRUE(matches("void f() { (void)_Generic(1, int: 1, float: 2.0); }", + genericSelectionExpr())); +} + TEST_P(ASTMatchersTest, AtomicExpr) { EXPECT_TRUE(matches("void foo() { int *ptr; __atomic_load_n(ptr, 1); }", atomicExpr())); Index: clang/unittests/AST/StructuralEquivalenceTest.cpp =================================================================== --- clang/unittests/AST/StructuralEquivalenceTest.cpp +++ clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -1598,6 +1598,72 @@ EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSame) { + auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)", + "_Generic(0u, unsigned int: 0, float: 1)", Lang_C99, + genericSelectionExpr()); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSignsDiffer) { + auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)", + "_Generic(0, int: 0, float: 1)", Lang_C99, + genericSelectionExpr()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprOrderDiffers) { + auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)", + "_Generic(0u, float: 1, unsigned int: 0)", Lang_C99, + genericSelectionExpr()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) { + auto t = makeStmts( + R"( + template <typename T> + void f() { + T x; + (void)_Generic(x, int: 0, float: 1); + } + void g() { f<int>(); } + )", + R"( + template <typename T> + void f() { + T x; + (void)_Generic(x, int: 0, float: 1); + } + void g() { f<int>(); } + )", + Lang_CXX03, genericSelectionExpr()); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceStmtTest, + GenericSelectionExprDependentResultOrderDiffers) { + auto t = makeStmts( + R"( + template <typename T> + void f() { + T x; + (void)_Generic(x, float: 1, int: 0); + } + void g() { f<int>(); } + )", + R"( + template <typename T> + void f() { + T x; + (void)_Generic(x, int: 0, float: 1); + } + void g() { f<int>(); } + )", + Lang_CXX03, genericSelectionExpr()); + + EXPECT_FALSE(testStructuralMatch(t)); +} TEST_F(StructuralEquivalenceStmtTest, IntegerLiteral) { auto t = makeWrappedStmts("1", "1", Lang_CXX03, integerLiteral()); EXPECT_TRUE(testStructuralMatch(t)); Index: clang/unittests/AST/ASTImporterTest.cpp =================================================================== --- clang/unittests/AST/ASTImporterTest.cpp +++ clang/unittests/AST/ASTImporterTest.cpp @@ -279,6 +279,15 @@ functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger()))))); } +TEST_P(ImportExpr, ImportGenericSelectionExpr) { + MatchVerifier<Decl> Verifier; + + testImport( + "void declToImport() { int x; (void)_Generic(x, int: 0, float: 1); }", + Lang_C99, "", Lang_C99, Verifier, + functionDecl(hasDescendant(genericSelectionExpr()))); +} + TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) { MatchVerifier<Decl> Verifier; testImport( @@ -1087,6 +1096,36 @@ ToChooseExpr->isConditionDependent()); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportGenericSelectionExpr) { + Decl *From, *To; + std::tie(From, To) = getImportedDecl( + R"( + int declToImport() { + int x; + return _Generic(x, int: 0, default: 1); + } + )", + Lang_C99, "", Lang_C99); + + auto ToResults = + match(genericSelectionExpr().bind("expr"), To->getASTContext()); + auto FromResults = + match(genericSelectionExpr().bind("expr"), From->getASTContext()); + + const GenericSelectionExpr *FromGenericSelectionExpr = + selectFirst<GenericSelectionExpr>("expr", FromResults); + ASSERT_TRUE(FromGenericSelectionExpr); + + const GenericSelectionExpr *ToGenericSelectionExpr = + selectFirst<GenericSelectionExpr>("expr", ToResults); + ASSERT_TRUE(ToGenericSelectionExpr); + + EXPECT_EQ(FromGenericSelectionExpr->isResultDependent(), + ToGenericSelectionExpr->isResultDependent()); + EXPECT_EQ(FromGenericSelectionExpr->getResultIndex(), + ToGenericSelectionExpr->getResultIndex()); +} + TEST_P(ASTImporterOptionSpecificTestBase, ImportFunctionWithBackReferringParameter) { Decl *From, *To; Index: clang/test/ASTMerge/generic-selection-expr/test.cpp =================================================================== --- /dev/null +++ clang/test/ASTMerge/generic-selection-expr/test.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -std=c++03 -emit-pch -o %t.ast %S/Inputs/generic.cpp +// RUN: %clang_cc1 -std=c++03 -ast-merge %t.ast -fsyntax-only -verify %s +// expected-no-diagnostics Index: clang/test/ASTMerge/generic-selection-expr/test.c =================================================================== --- /dev/null +++ clang/test/ASTMerge/generic-selection-expr/test.c @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -std=c11 -emit-pch -o %t.ast %S/Inputs/generic.c +// RUN: %clang_cc1 -std=c11 -ast-merge %t.ast -fsyntax-only -verify %s +// expected-no-diagnostics Index: clang/test/ASTMerge/generic-selection-expr/Inputs/generic.cpp =================================================================== --- /dev/null +++ clang/test/ASTMerge/generic-selection-expr/Inputs/generic.cpp @@ -0,0 +1,5 @@ +template <typename T> +void f() { + T x; + _Static_assert(_Generic(x, float : 0, int : 1), "Incorrect semantics of _Generic"); +} Index: clang/test/ASTMerge/generic-selection-expr/Inputs/generic.c =================================================================== --- /dev/null +++ clang/test/ASTMerge/generic-selection-expr/Inputs/generic.c @@ -0,0 +1,6 @@ +void f() { + int x; + float y; + _Static_assert(_Generic(x, float : 0, int : 1), "Incorrect semantics of _Generic"); + _Static_assert(_Generic(y, float : 1, int : 0), "Incorrect semantics of _Generic"); +} Index: clang/lib/Analysis/ExprMutationAnalyzer.cpp =================================================================== --- clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -95,10 +95,6 @@ return Node.isPotentiallyEvaluated(); } -const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, - GenericSelectionExpr> - genericSelectionExpr; - AST_MATCHER_P(GenericSelectionExpr, hasControllingExpr, ast_matchers::internal::Matcher<Expr>, InnerMatcher) { return InnerMatcher.matches(*Node.getControllingExpr(), Finder, Builder); Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -239,6 +239,7 @@ REGISTER_MATCHER(functionProtoType); REGISTER_MATCHER(functionTemplateDecl); REGISTER_MATCHER(functionType); + REGISTER_MATCHER(genericSelectionExpr); REGISTER_MATCHER(gnuNullExpr); REGISTER_MATCHER(gotoStmt); REGISTER_MATCHER(has); Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -905,6 +905,8 @@ cxxNullPtrLiteralExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, ChooseExpr> chooseExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, GenericSelectionExpr> + genericSelectionExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator> Index: clang/lib/AST/ASTStructuralEquivalence.cpp =================================================================== --- clang/lib/AST/ASTStructuralEquivalence.cpp +++ clang/lib/AST/ASTStructuralEquivalence.cpp @@ -233,6 +233,24 @@ return E1->isExact() == E2->isExact() && E1->getValue() == E2->getValue(); } + bool IsStmtEquivalent(const GenericSelectionExpr *E1, + const GenericSelectionExpr *E2) { + for (auto Pair : zip_longest(E1->getAssocTypeSourceInfos(), + E2->getAssocTypeSourceInfos())) { + Optional<TypeSourceInfo *> Child1 = std::get<0>(Pair); + Optional<TypeSourceInfo *> Child2 = std::get<1>(Pair); + // Skip this case if there are a different number of associated types. + if (!Child1 || !Child2) + return false; + + if (!IsStructurallyEquivalent(Context, (*Child1)->getType(), + (*Child2)->getType())) + return false; + } + + return true; + } + bool IsStmtEquivalent(const ImplicitCastExpr *CastE1, const ImplicitCastExpr *CastE2) { return IsStructurallyEquivalent(Context, CastE1->getType(), Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -577,6 +577,7 @@ ExpectedStmt VisitVAArgExpr(VAArgExpr *E); ExpectedStmt VisitChooseExpr(ChooseExpr *E); ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); + ExpectedStmt VisitGenericSelectionExpr(GenericSelectionExpr *E); ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E); ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E); ExpectedStmt VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); @@ -6526,6 +6527,40 @@ return new (Importer.getToContext()) GNUNullExpr(*TypeOrErr, *BeginLocOrErr); } +ExpectedStmt +ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { + Error Err = Error::success(); + auto ToGenericLoc = importChecked(Err, E->getGenericLoc()); + auto *ToControllingExpr = importChecked(Err, E->getControllingExpr()); + auto ToDefaultLoc = importChecked(Err, E->getDefaultLoc()); + auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); + if (Err) + return std::move(Err); + + ArrayRef<const TypeSourceInfo *> FromAssocTypes(E->getAssocTypeSourceInfos()); + SmallVector<TypeSourceInfo *, 1> ToAssocTypes(FromAssocTypes.size()); + if (Error Err = ImportContainerChecked(FromAssocTypes, ToAssocTypes)) + return std::move(Err); + + ArrayRef<const Expr *> FromAssocExprs(E->getAssocExprs()); + SmallVector<Expr *, 1> ToAssocExprs(FromAssocExprs.size()); + if (Error Err = ImportContainerChecked(FromAssocExprs, ToAssocExprs)) + return std::move(Err); + + const ASTContext &ToCtx = Importer.getToContext(); + if (E->isResultDependent()) { + return GenericSelectionExpr::Create( + ToCtx, ToGenericLoc, ToControllingExpr, + llvm::makeArrayRef(ToAssocTypes), llvm::makeArrayRef(ToAssocExprs), + ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack()); + } + + return GenericSelectionExpr::Create( + ToCtx, ToGenericLoc, ToControllingExpr, llvm::makeArrayRef(ToAssocTypes), + llvm::makeArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, + E->containsUnexpandedParameterPack(), E->getResultIndex()); +} + ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { Error Err = Error::success(); Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2362,6 +2362,10 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr; +/// Matches C11 _Generic expression. +extern const internal::VariadicDynCastAllOfMatcher<Stmt, GenericSelectionExpr> + genericSelectionExpr; + /// Matches atomic builtins. /// Example matches __atomic_load_n(ptr, 1) /// \code Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -1704,6 +1704,11 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('genericSelectionExpr0')"><a name="genericSelectionExpr0Anchor">genericSelectionExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1GenericSelectionExpr.html">GenericSelectionExpr</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="genericSelectionExpr0"><pre>Matches C11 _Generic expression. +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('gnuNullExpr0')"><a name="gnuNullExpr0Anchor">gnuNullExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1GNUNullExpr.html">GNUNullExpr</a>>...</td></tr> <tr><td colspan="4" class="doc" id="gnuNullExpr0"><pre>Matches GNU __null expression. </pre></td></tr>
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits