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&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('genericSelectionExpr0')"><a name="genericSelectionExpr0Anchor">genericSelectionExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1GenericSelectionExpr.html";>GenericSelectionExpr</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="genericSelectionExpr0"><pre>Matches C11 _Generic expression.
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('gnuNullExpr0')"><a name="gnuNullExpr0Anchor">gnuNullExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1GNUNullExpr.html";>GNUNullExpr</a>&gt;...</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

Reply via email to