alexfh created this revision.
alexfh added reviewers: sbenza, bkramer.
alexfh added a subscriber: cfe-commits.

This patch fixes an assertion failure on some matchers containing
templateArgument() on some code in some configurations. I couldn't come up with 
a
consistent repro, since the failure depens on the order of elements in a map.
http://reviews.llvm.org/D18136 contains a matcher that causes the issue at least
on some configurations.

The fix turned out to require non-trivial amount of code, very similar to
TemplateArgument::structurallyEquals. I'd prefer to use
TemplateArgument::Profile, if it was possible without ASTContext. Another
alternative would be to add operator< for TemplateArgument, but since it's only
needed in DynTypedNode, I decided to make this code private to DynTypedNode.

http://reviews.llvm.org/D19144

Files:
  include/clang/AST/ASTTypeTraits.h
  lib/AST/ASTTypeTraits.cpp
  unittests/AST/ASTTypeTraitsTest.cpp

Index: unittests/AST/ASTTypeTraitsTest.cpp
===================================================================
--- unittests/AST/ASTTypeTraitsTest.cpp
+++ unittests/AST/ASTTypeTraitsTest.cpp
@@ -180,5 +180,65 @@
   EXPECT_FALSE(Node < Node);
 }
 
+TEST(DynTypedNode, TemplateArgumentNull) {
+  TemplateArgument T;
+  DynTypedNode Node = DynTypedNode::create(T);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, TemplateArgumentQualType) {
+  QualType QT;
+  TemplateArgument T(QT);
+  DynTypedNode Node = DynTypedNode::create(T);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, TemplateArgumentNullPtr) {
+  QualType QT;
+  TemplateArgument T(QT, true);
+  DynTypedNode Node = DynTypedNode::create(T);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, TemplateArgumentExpr) {
+  BuiltinType Void(BuiltinType::Void);
+  QualType QT(&Void, 0);
+  NoInitExpr E(QT);
+  TemplateArgument T(&E);
+  DynTypedNode Node = DynTypedNode::create(T);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, TemplateArgumentTemplate) {
+  TemplateName TN;
+  TemplateArgument T(TN);
+  DynTypedNode Node = DynTypedNode::create(T);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, TemplateArgumentTemplateExpansion) {
+  TemplateName TN;
+  TemplateArgument T(TN, llvm::Optional<unsigned>(0u));
+  DynTypedNode Node = DynTypedNode::create(T);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, TemplateArgumentPack) {
+  TemplateArgument TP[1];
+  TemplateArgument T(TP);
+  DynTypedNode Node = DynTypedNode::create(T);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+// FIXME: Figure out how to test TemplateArgument of the Declaration and
+// Integral kinds.
+
 }  // namespace ast_type_traits
 }  // namespace clang
Index: lib/AST/ASTTypeTraits.cpp
===================================================================
--- lib/AST/ASTTypeTraits.cpp
+++ lib/AST/ASTTypeTraits.cpp
@@ -150,5 +150,54 @@
   return SourceRange();
 }
 
+bool DynTypedNode::TemplateArgumentLess(const TemplateArgument &LHS,
+                                        const TemplateArgument &RHS) {
+  if (LHS.getKind() != RHS.getKind()) return LHS.getKind() < RHS.getKind();
+
+  switch (LHS.getKind()) {
+    case TemplateArgument::Null:
+      return false;
+
+    case TemplateArgument::Type:
+      return LHS.getAsType().getAsOpaquePtr() <
+             RHS.getAsType().getAsOpaquePtr();
+
+    case TemplateArgument::Expression:
+      return LHS.getAsExpr() < RHS.getAsExpr();
+
+    case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion:
+      return LHS.getAsTemplateOrTemplatePattern().getAsVoidPointer() <
+             RHS.getAsTemplateOrTemplatePattern().getAsVoidPointer();
+
+    case TemplateArgument::NullPtr:
+      return LHS.getNullPtrType().getAsOpaquePtr() <
+             RHS.getNullPtrType().getAsOpaquePtr();
+
+    case TemplateArgument::Pack: {
+      if (LHS.pack_size() != RHS.pack_size())
+        return LHS.pack_size() < RHS.pack_size();
+      auto PackA = LHS.getPackAsArray();
+      auto PackB = RHS.getPackAsArray();
+      for (unsigned I = 0, E = PackA.size(); I != E; ++I)
+        if (!PackA[I].structurallyEquals(PackB[I]))
+          return TemplateArgumentLess(PackA[I], PackB[I]);
+      return false;
+    }
+
+    case TemplateArgument::Declaration:
+      return (LHS.getAsDecl() ? LHS.getAsDecl()->getCanonicalDecl() : nullptr) <
+             (RHS.getAsDecl() ? RHS.getAsDecl()->getCanonicalDecl() : nullptr);
+
+    case TemplateArgument::Integral:
+      return std::make_pair(LHS.getIntegralType().getAsOpaquePtr(),
+                            LHS.getAsIntegral()) <
+             std::make_pair(RHS.getIntegralType().getAsOpaquePtr(),
+                            RHS.getAsIntegral());
+
+  }
+  llvm_unreachable("Unsupported or invalid TemplateArgument kind");
+}
+
 } // end namespace ast_type_traits
 } // end namespace clang
Index: include/clang/AST/ASTTypeTraits.h
===================================================================
--- include/clang/AST/ASTTypeTraits.h
+++ include/clang/AST/ASTTypeTraits.h
@@ -296,6 +296,10 @@
                             NNSLB.getOpaqueData());
     }
 
+    if (ASTNodeKind::getFromNodeKind<TemplateArgument>().isSame(NodeKind))
+      return TemplateArgumentLess(getUnchecked<TemplateArgument>(),
+                                  Other.getUnchecked<TemplateArgument>());
+
     assert(getMemoizationData() && Other.getMemoizationData());
     return getMemoizationData() < Other.getMemoizationData();
   }
@@ -316,6 +320,10 @@
       return getUnchecked<NestedNameSpecifierLoc>() ==
              Other.getUnchecked<NestedNameSpecifierLoc>();
 
+    if (ASTNodeKind::getFromNodeKind<TemplateArgument>().isSame(NodeKind))
+      return getUnchecked<TemplateArgument>().structurallyEquals(
+          Other.getUnchecked<TemplateArgument>());
+
     assert(getMemoizationData() && Other.getMemoizationData());
     return getMemoizationData() == Other.getMemoizationData();
   }
@@ -428,6 +436,9 @@
     }
   };
 
+  static bool TemplateArgumentLess(const TemplateArgument &LHS,
+                                   const TemplateArgument &RHS);
+
   ASTNodeKind NodeKind;
 
   /// \brief Stores the data of the node.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to