fgross updated this revision to Diff 109795.
fgross added a comment.

Changed comment, added some clang-tidy test cases.


https://reviews.llvm.org/D36308

Files:
  include/clang/ASTMatchers/ASTMatchersInternal.h
  test/clang-tidy/misc-use-after-move.cpp
  test/clang-tidy/performance-inefficient-string-concatenation.cpp
  test/clang-tidy/readability-redundant-smartptr-get.cpp
  test/clang-tidy/readability-uniqueptr-delete-release.cpp
  unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: test/clang-tidy/readability-uniqueptr-delete-release.cpp
===================================================================
--- test/clang-tidy/readability-uniqueptr-delete-release.cpp
+++ test/clang-tidy/readability-uniqueptr-delete-release.cpp
@@ -24,6 +24,11 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects [readability-uniqueptr-delete-release]
   // CHECK-FIXES: {{^}}  P = nullptr;
 
+  auto P2 = P;
+  delete P2.release();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects [readability-uniqueptr-delete-release]
+  // CHECK-FIXES: {{^}}  P2 = nullptr;
+
   std::unique_ptr<int> Array[20];
   delete Array[4].release();
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete
Index: test/clang-tidy/readability-redundant-smartptr-get.cpp
===================================================================
--- test/clang-tidy/readability-redundant-smartptr-get.cpp
+++ test/clang-tidy/readability-redundant-smartptr-get.cpp
@@ -97,6 +97,12 @@
   // CHECK-MESSAGES: int i = *ip.get();
   // CHECK-FIXES: int i = *ip;
 
+  auto ip2 = ip;
+  i = *ip2.get();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+  // CHECK-MESSAGES: i = *ip2.get();
+  // CHECK-FIXES: i = *ip2;
+
   std::unique_ptr<int> uu;
   std::shared_ptr<double> *ss;
   bool bb = uu.get() == nullptr;
Index: test/clang-tidy/performance-inefficient-string-concatenation.cpp
===================================================================
--- test/clang-tidy/performance-inefficient-string-concatenation.cpp
+++ test/clang-tidy/performance-inefficient-string-concatenation.cpp
@@ -19,6 +19,8 @@
 int main() {
   std::string mystr1, mystr2;
   std::wstring mywstr1, mywstr2;
+  auto myautostr1 = mystr1;
+  auto myautostr2 = mystr2;
 
   for (int i = 0; i < 10; ++i) {
     f(mystr1 + mystr2 + mystr1);
@@ -33,6 +35,8 @@
     // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
     mywstr1 = mywstr2 + mywstr2 + mywstr2;
     // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: string concatenation
+    myautostr1 = myautostr1 + myautostr2;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
 
     mywstr1 = mywstr2 + mywstr2;
     mystr1 = mystr2 + mystr2;
Index: test/clang-tidy/misc-use-after-move.cpp
===================================================================
--- test/clang-tidy/misc-use-after-move.cpp
+++ test/clang-tidy/misc-use-after-move.cpp
@@ -723,6 +723,11 @@
     std::move(container);
     container.clear();
     container.empty();
+
+    auto container2 = container;
+    std::move(container2);
+    container2.clear();
+    container2.empty();
   }
   {
     std::deque<int> container;
Index: unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1184,6 +1184,10 @@
   EXPECT_TRUE(matches("int v[] = { 2, 3 }; void f() { for (int i : v) {} }",
                       autoType()));
 
+  EXPECT_TRUE(matches("auto i = 2;", varDecl(hasType(isInteger()))));
+  EXPECT_TRUE(matches("struct X{}; auto x = X{};",
+                      varDecl(hasType(recordDecl(hasName("X"))))));
+
   // FIXME: Matching against the type-as-written can't work here, because the
   //        type as written was not deduced.
   //EXPECT_TRUE(matches("auto a = 1;",
Index: include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersInternal.h
+++ include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -741,24 +741,34 @@
   /// matcher matches on it.
   bool matchesSpecialized(const Type &Node, ASTMatchFinder *Finder,
                           BoundNodesTreeBuilder *Builder) const {
+
+    // DeducedType does not have declarations of its own, so
+    // match the deduced type instead.
+    const Type *EffectiveType = &Node;
+    if (const auto *S = dyn_cast<DeducedType>(&Node)) {
+      EffectiveType = S->getDeducedType().getTypePtrOrNull();
+      if (!EffectiveType)
+        return false;
+    }
+
     // First, for any types that have a declaration, extract the declaration and
     // match on it.
-    if (const auto *S = dyn_cast<TagType>(&Node)) {
+    if (const auto *S = dyn_cast<TagType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<InjectedClassNameType>(&Node)) {
+    if (const auto *S = dyn_cast<InjectedClassNameType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<TemplateTypeParmType>(&Node)) {
+    if (const auto *S = dyn_cast<TemplateTypeParmType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<TypedefType>(&Node)) {
+    if (const auto *S = dyn_cast<TypedefType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<UnresolvedUsingType>(&Node)) {
+    if (const auto *S = dyn_cast<UnresolvedUsingType>(EffectiveType)) {
       return matchesDecl(S->getDecl(), Finder, Builder);
     }
-    if (const auto *S = dyn_cast<ObjCObjectType>(&Node)) {
+    if (const auto *S = dyn_cast<ObjCObjectType>(EffectiveType)) {
       return matchesDecl(S->getInterface(), Finder, Builder);
     }
 
@@ -770,14 +780,14 @@
     //   template<typename T> struct X { T t; } class A {}; X<A> a;
     // The following matcher will match, which otherwise would not:
     //   fieldDecl(hasType(pointerType())).
-    if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(&Node)) {
+    if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(EffectiveType)) {
       return matchesSpecialized(S->getReplacementType(), Finder, Builder);
     }
 
     // For template specialization types, we want to match the template
     // declaration, as long as the type is still dependent, and otherwise the
     // declaration of the instantiated tag type.
-    if (const auto *S = dyn_cast<TemplateSpecializationType>(&Node)) {
+    if (const auto *S = dyn_cast<TemplateSpecializationType>(EffectiveType)) {
       if (!S->isTypeAlias() && S->isSugared()) {
         // If the template is non-dependent, we want to match the instantiated
         // tag type.
@@ -796,7 +806,7 @@
     // FIXME: We desugar elaborated types. This makes the assumption that users
     // do never want to match on whether a type is elaborated - there are
     // arguments for both sides; for now, continue desugaring.
-    if (const auto *S = dyn_cast<ElaboratedType>(&Node)) {
+    if (const auto *S = dyn_cast<ElaboratedType>(EffectiveType)) {
       return matchesSpecialized(S->desugar(), Finder, Builder);
     }
     return false;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to