[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cfe-commits
Subject:    Re: [PATCH] Refactor: Move remove-cstr-calls from a standalone executable to a clang-tidy check
From:       Richard <legalize () xmission ! com>
Date:       2015-02-28 20:50:49
Message-ID: 50d04bcef9295855c3095dcae8e67cd4 () localhost ! localdomain
[Download RAW message or body]

Use isa<> instead of dyn_cast<>.
Move the check from namespace clang::tidy into namespace clang::tidy::reada=
bility


http://reviews.llvm.org/D7318

Files:
  CMakeLists.txt
  clang-tidy/readability/CMakeLists.txt
  clang-tidy/readability/ReadabilityTidyModule.cpp
  clang-tidy/readability/RemoveCStrCall.cpp
  clang-tidy/readability/RemoveCStrCall.h
  remove-cstr-calls/CMakeLists.txt
  remove-cstr-calls/Makefile
  remove-cstr-calls/RemoveCStrCalls.cpp
  test/CMakeLists.txt
  test/clang-tidy/readability-remove-cstr-call.cpp
  test/remove-cstr-calls/basic.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/

["D7318.20937.patch" (text/x-patch)]

Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -2,7 +2,6 @@
 add_subdirectory(clang-modernize)
 add_subdirectory(clang-rename)
 add_subdirectory(modularize)
-add_subdirectory(remove-cstr-calls)
 if(CLANG_ENABLE_STATIC_ANALYZER)
 add_subdirectory(clang-tidy)
 endif()
Index: clang-tidy/readability/CMakeLists.txt
===================================================================
--- clang-tidy/readability/CMakeLists.txt
+++ clang-tidy/readability/CMakeLists.txt
@@ -8,6 +8,7 @@
   NamespaceCommentCheck.cpp
   ReadabilityTidyModule.cpp
   RedundantSmartptrGet.cpp
+  RemoveCStrCall.cpp
   ShrinkToFitCheck.cpp
 
   LINK_LIBS
Index: clang-tidy/readability/ReadabilityTidyModule.cpp
===================================================================
--- clang-tidy/readability/ReadabilityTidyModule.cpp
+++ clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -15,6 +15,7 @@
 #include "ElseAfterReturnCheck.h"
 #include "FunctionSize.h"
 #include "RedundantSmartptrGet.h"
+#include "RemoveCStrCall.h"
 #include "ShrinkToFitCheck.h"
 
 namespace clang {
@@ -34,6 +35,8 @@
         "readability-function-size");
     CheckFactories.registerCheck<RedundantSmartptrGet>(
         "readability-redundant-smartptr-get");
+    CheckFactories.registerCheck<RemoveCStrCall>(
+        "readability-remove-cstr-call");
     CheckFactories.registerCheck<ShrinkToFitCheck>(
         "readability-shrink-to-fit");
   }
Index: clang-tidy/readability/RemoveCStrCall.cpp
===================================================================
--- /dev/null
+++ clang-tidy/readability/RemoveCStrCall.cpp
@@ -0,0 +1,145 @@
+//===- RemoveCStrCall.cpp - Check for redundant c_str call ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements a check for redundant calls of c_str() on strings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RemoveCStrCall.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang;
+using namespace clang::ast_matchers;
+
+namespace {
+
+template <typename T>
+StringRef getText(const ast_matchers::MatchFinder::MatchResult &Result, T const &Node) {
+    return Lexer::getSourceText(
+            CharSourceRange::getTokenRange(Node.getSourceRange()),
+            *Result.SourceManager, Result.Context->getLangOpts());
+}
+
+// Return true if expr needs to be put in parens when it is an argument of a
+// prefix unary operator, e.g. when it is a binary or ternary operator
+// syntactically.
+bool needParensAfterUnaryOperator(const Expr &ExprNode) {
+  if (isa<clang::BinaryOperator>(&ExprNode) ||
+      isa<clang::ConditionalOperator>(&ExprNode)) {
+    return true;
+  }
+  if (const CXXOperatorCallExpr *op =
+      dyn_cast<CXXOperatorCallExpr>(&ExprNode)) {
+    return op->getNumArgs() == 2 &&
+        op->getOperator() != OO_PlusPlus &&
+        op->getOperator() != OO_MinusMinus &&
+        op->getOperator() != OO_Call &&
+        op->getOperator() != OO_Subscript;
+  }
+  return false;
+}
+
+// Format a pointer to an expression: prefix with '*' but simplify
+// when it already begins with '&'.  Return empty string on failure.
+std::string formatDereference(const ast_matchers::MatchFinder::MatchResult &Result,
+                              const Expr &ExprNode) {
+  if (const auto Op = dyn_cast<clang::UnaryOperator>(&ExprNode)) {
+    if (Op->getOpcode() == UO_AddrOf) {
+      // Strip leading '&'.
+      return getText(Result, *Op->getSubExpr()->IgnoreParens());
+    }
+  }
+  const std::string Text = getText(Result, ExprNode);
+  if (Text.empty()) return std::string();
+  // Add leading '*'.
+  if (needParensAfterUnaryOperator(ExprNode)) {
+    return std::string("*(") + Text + ")";
+  }
+  return std::string("*") + Text;
+}
+
+const char *const StringConstructor =
+    "::std::basic_string<char, std::char_traits<char>, std::allocator<char> >"
+    "::basic_string";
+
+const char *const StringCStrMethod =
+    "::std::basic_string<char, std::char_traits<char>, std::allocator<char> >"
+    "::c_str";
+
+} // end namespace
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void RemoveCStrCall::registerMatchers(ast_matchers::MatchFinder *Finder)
+{
+  Finder->addMatcher(
+      constructExpr(
+          hasDeclaration(methodDecl(hasName(StringConstructor))),
+          argumentCountIs(2),
+          // The first argument must have the form x.c_str() or p->c_str()
+          // where the method is string::c_str().  We can use the copy
+          // constructor of string instead (or the compiler might share
+          // the string object).
+          hasArgument(
+              0,
+              id("call", memberCallExpr(
+                  callee(id("member", memberExpr())),
+                  callee(methodDecl(hasName(StringCStrMethod))),
+                  on(id("arg", expr()))))),
+          // The second argument is the alloc object which must not be
+          // present explicitly.
+          hasArgument(
+              1,
+              defaultArgExpr())),
+      this);
+    Finder->addMatcher(
+      constructExpr(
+          // Implicit constructors of these classes are overloaded
+          // wrt. string types and they internally make a StringRef
+          // referring to the argument.  Passing a string directly to
+          // them is preferred to passing a char pointer.
+          hasDeclaration(methodDecl(anyOf(
+              hasName("::llvm::StringRef::StringRef"),
+              hasName("::llvm::Twine::Twine")))),
+          argumentCountIs(1),
+          // The only argument must have the form x.c_str() or p->c_str()
+          // where the method is string::c_str().  StringRef also has
+          // a constructor from string which is more efficient (avoids
+          // strlen), so we can construct StringRef from the string
+          // directly.
+          hasArgument(
+              0,
+              id("call", memberCallExpr(
+                  callee(id("member", memberExpr())),
+                  callee(methodDecl(hasName(StringCStrMethod))),
+                  on(id("arg", expr())))))),
+      this);
+}
+
+void RemoveCStrCall::check(const ast_matchers::MatchFinder::MatchResult &Result)
+{
+    const CallExpr *Call = Result.Nodes.getStmtAs<CallExpr>("call");
+    const Expr *Arg = Result.Nodes.getStmtAs<Expr>("arg");
+    const bool Arrow = Result.Nodes.getStmtAs<MemberExpr>("member")->isArrow();
+    // Replace the "call" node with the "arg" node, prefixed with '*'
+    // if the call was using '->' rather than '.'.
+    const std::string ArgText = Arrow ?
+            formatDereference(Result, *Arg) :
+            static_cast<std::string>(getText(Result, *Arg));
+    if (ArgText.empty()) return;
+
+    diag(Call->getLocStart(), "redundant call to `c_str()`")
+            << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/readability/RemoveCStrCall.h
===================================================================
--- /dev/null
+++ clang-tidy/readability/RemoveCStrCall.h
@@ -0,0 +1,32 @@
+//===--- RemoveCStrCall.h - clang-tidy --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REMOVE_C_STR_CALL_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REMOVE_C_STR_CALL_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// \brief Finds unnecessary calls to std::string::c_str().
+class RemoveCStrCall : public ClangTidyCheck {
+public:
+    RemoveCStrCall(StringRef Name, ClangTidyContext *Context)
+            : ClangTidyCheck(Name, Context) {}
+    void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+    void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REMOVE_C_STR_CALL_H
Index: remove-cstr-calls/CMakeLists.txt
===================================================================
--- remove-cstr-calls/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  Support
-  )
-
-add_clang_executable(remove-cstr-calls
-  RemoveCStrCalls.cpp
-  )
-
-target_link_libraries(remove-cstr-calls
-  clangAST
-  clangASTMatchers
-  clangBasic
-  clangFrontend
-  clangLex
-  clangTooling
-  clangToolingCore
-  )
Index: remove-cstr-calls/Makefile
===================================================================
--- remove-cstr-calls/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-##===- tools/extra/remove-cstr-calls/Makefile --------------*- Makefile -*-===##
-#
-#                     The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-CLANG_LEVEL := ../../..
-
-TOOLNAME = remove-cstr-calls
-NO_INSTALL = 1
-
-# No plugins, optimize startup time.
-TOOL_NO_EXPORTS = 1
-
-include $(CLANG_LEVEL)/../../Makefile.config
-LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
-USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
-           clangToolingCore.a clangRewriteFrontend.a clangRewrite.a \
-           clangParse.a clangSema.a clangAnalysis.a \
-           clangAST.a clangASTMatchers.a clangEdit.a clangLex.a clangBasic.a
-
-include $(CLANG_LEVEL)/Makefile
Index: remove-cstr-calls/RemoveCStrCalls.cpp
===================================================================
--- remove-cstr-calls/RemoveCStrCalls.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-//===- examples/Tooling/RemoveCStrCalls.cpp - Redundant c_str call removal ===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file implements a tool that prints replacements that remove redundant
-//  calls of c_str() on strings.
-//
-//  Usage:
-//  remove-cstr-calls <cmake-output-dir> <file1> <file2> ...
-//
-//  Where <cmake-output-dir> is a CMake build directory in which a file named
-//  compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
-//  CMake to get this output).
-//
-//  <file1> ... specify the paths of files in the CMake source tree. This path
-//  is looked up in the compile command database. If the path of a file is
-//  absolute, it needs to point into CMake's source tree. If the path is
-//  relative, the current working directory needs to be in the CMake source
-//  tree and the file must be in a subdirectory of the current working
-//  directory. "./" prefixes in the relative files will be automatically
-//  removed, but the rest of a relative path must be a suffix of a path in
-//  the compile command line database.
-//
-//  For example, to use remove-cstr-calls on all files in a subtree of the
-//  source tree, use:
-//
-//    /path/in/subtree $ find . -name '*.cpp'|
-//        xargs remove-cstr-calls /path/to/build
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Tooling/CompilationDatabase.h"
-#include "clang/Tooling/Refactoring.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/raw_ostream.h"
-#include <system_error>
-
-using namespace clang;
-using namespace clang::ast_matchers;
-using namespace llvm;
-using clang::tooling::newFrontendActionFactory;
-using clang::tooling::Replacement;
-using clang::tooling::CompilationDatabase;
-
-// FIXME: Pull out helper methods in here into more fitting places.
-
-// Returns the text that makes up 'node' in the source.
-// Returns an empty string if the text cannot be found.
-template <typename T>
-static std::string getText(const SourceManager &SourceManager, const T &Node) {
-  SourceLocation StartSpellingLocation =
-      SourceManager.getSpellingLoc(Node.getLocStart());
-  SourceLocation EndSpellingLocation =
-      SourceManager.getSpellingLoc(Node.getLocEnd());
-  if (!StartSpellingLocation.isValid() || !EndSpellingLocation.isValid()) {
-    return std::string();
-  }
-  bool Invalid = true;
-  const char *Text =
-      SourceManager.getCharacterData(StartSpellingLocation, &Invalid);
-  if (Invalid) {
-    return std::string();
-  }
-  std::pair<FileID, unsigned> Start =
-      SourceManager.getDecomposedLoc(StartSpellingLocation);
-  std::pair<FileID, unsigned> End =
-      SourceManager.getDecomposedLoc(Lexer::getLocForEndOfToken(
-          EndSpellingLocation, 0, SourceManager, LangOptions()));
-  if (Start.first != End.first) {
-    // Start and end are in different files.
-    return std::string();
-  }
-  if (End.second < Start.second) {
-    // Shuffling text with macros may cause this.
-    return std::string();
-  }
-  return std::string(Text, End.second - Start.second);
-}
-
-// Return true if expr needs to be put in parens when it is an argument of a
-// prefix unary operator, e.g. when it is a binary or ternary operator
-// syntactically.
-static bool needParensAfterUnaryOperator(const Expr &ExprNode) {
-  if (dyn_cast<clang::BinaryOperator>(&ExprNode) ||
-      dyn_cast<clang::ConditionalOperator>(&ExprNode)) {
-    return true;
-  }
-  if (const CXXOperatorCallExpr *op =
-      dyn_cast<CXXOperatorCallExpr>(&ExprNode)) {
-    return op->getNumArgs() == 2 &&
-        op->getOperator() != OO_PlusPlus &&
-        op->getOperator() != OO_MinusMinus &&
-        op->getOperator() != OO_Call &&
-        op->getOperator() != OO_Subscript;
-  }
-  return false;
-}
-
-// Format a pointer to an expression: prefix with '*' but simplify
-// when it already begins with '&'.  Return empty string on failure.
-static std::string formatDereference(const SourceManager &SourceManager,
-                              const Expr &ExprNode) {
-  if (const clang::UnaryOperator *Op =
-      dyn_cast<clang::UnaryOperator>(&ExprNode)) {
-    if (Op->getOpcode() == UO_AddrOf) {
-      // Strip leading '&'.
-      return getText(SourceManager, *Op->getSubExpr()->IgnoreParens());
-    }
-  }
-  const std::string Text = getText(SourceManager, ExprNode);
-  if (Text.empty()) return std::string();
-  // Add leading '*'.
-  if (needParensAfterUnaryOperator(ExprNode)) {
-    return std::string("*(") + Text + ")";
-  }
-  return std::string("*") + Text;
-}
-
-namespace {
-class FixCStrCall : public ast_matchers::MatchFinder::MatchCallback {
- public:
-  FixCStrCall(tooling::Replacements *Replace)
-      : Replace(Replace) {}
-
-  virtual void run(const ast_matchers::MatchFinder::MatchResult &Result) {
-    const CallExpr *Call =
-        Result.Nodes.getStmtAs<CallExpr>("call");
-    const Expr *Arg =
-        Result.Nodes.getStmtAs<Expr>("arg");
-    const bool Arrow =
-        Result.Nodes.getStmtAs<MemberExpr>("member")->isArrow();
-    // Replace the "call" node with the "arg" node, prefixed with '*'
-    // if the call was using '->' rather than '.'.
-    const std::string ArgText = Arrow ?
-        formatDereference(*Result.SourceManager, *Arg) :
-        getText(*Result.SourceManager, *Arg);
-    if (ArgText.empty()) return;
-
-    Replace->insert(Replacement(*Result.SourceManager, Call, ArgText));
-  }
-
- private:
-  tooling::Replacements *Replace;
-};
-} // end namespace
-
-const char *StringConstructor =
-    "::std::basic_string<char, std::char_traits<char>, std::allocator<char> >"
-    "::basic_string";
-
-const char *StringCStrMethod =
-    "::std::basic_string<char, std::char_traits<char>, std::allocator<char> >"
-    "::c_str";
-
-cl::opt<std::string> BuildPath(
-  cl::Positional,
-  cl::desc("<build-path>"));
-
-cl::list<std::string> SourcePaths(
-  cl::Positional,
-  cl::desc("<source0> [... <sourceN>]"),
-  cl::OneOrMore);
-
-int main(int argc, const char **argv) {
-  llvm::sys::PrintStackTraceOnErrorSignal();
-  std::unique_ptr<CompilationDatabase> Compilations(
-      tooling::FixedCompilationDatabase::loadFromCommandLine(argc, argv));
-  cl::ParseCommandLineOptions(argc, argv);
-  if (!Compilations) {
-    std::string ErrorMessage;
-    Compilations =
-        CompilationDatabase::loadFromDirectory(BuildPath, ErrorMessage);
-    if (!Compilations)
-      llvm::report_fatal_error(ErrorMessage);
-  }
-  tooling::RefactoringTool Tool(*Compilations, SourcePaths);
-  ast_matchers::MatchFinder Finder;
-  FixCStrCall Callback(&Tool.getReplacements());
-  Finder.addMatcher(
-      constructExpr(
-          hasDeclaration(methodDecl(hasName(StringConstructor))),
-          argumentCountIs(2),
-          // The first argument must have the form x.c_str() or p->c_str()
-          // where the method is string::c_str().  We can use the copy
-          // constructor of string instead (or the compiler might share
-          // the string object).
-          hasArgument(
-              0,
-              id("call", memberCallExpr(
-                  callee(id("member", memberExpr())),
-                  callee(methodDecl(hasName(StringCStrMethod))),
-                  on(id("arg", expr()))))),
-          // The second argument is the alloc object which must not be
-          // present explicitly.
-          hasArgument(
-              1,
-              defaultArgExpr())),
-      &Callback);
-  Finder.addMatcher(
-      constructExpr(
-          // Implicit constructors of these classes are overloaded
-          // wrt. string types and they internally make a StringRef
-          // referring to the argument.  Passing a string directly to
-          // them is preferred to passing a char pointer.
-          hasDeclaration(methodDecl(anyOf(
-              hasName("::llvm::StringRef::StringRef"),
-              hasName("::llvm::Twine::Twine")))),
-          argumentCountIs(1),
-          // The only argument must have the form x.c_str() or p->c_str()
-          // where the method is string::c_str().  StringRef also has
-          // a constructor from string which is more efficient (avoids
-          // strlen), so we can construct StringRef from the string
-          // directly.
-          hasArgument(
-              0,
-              id("call", memberCallExpr(
-                  callee(id("member", memberExpr())),
-                  callee(methodDecl(hasName(StringCStrMethod))),
-                  on(id("arg", expr())))))),
-      &Callback);
-  return Tool.runAndSave(newFrontendActionFactory(&Finder).get());
-}
Index: test/CMakeLists.txt
===================================================================
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -42,7 +42,6 @@
   clang-tidy
   modularize
   pp-trace
-  remove-cstr-calls
 
   # Unit tests
   ExtraToolsUnitTests
Index: test/clang-tidy/readability-remove-cstr-call.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/readability-remove-cstr-call.cpp
@@ -0,0 +1,39 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s readability-remove-cstr-call %t
+// REQUIRES: shell
+
+namespace std {
+template<typename T> class allocator {};
+template<typename T> class char_traits {};
+template<typename C, typename T, typename A> struct basic_string {
+  basic_string();
+  basic_string(const C *p, const A& a = A());
+  const C *c_str() const;
+};
+typedef basic_string<char, std::char_traits<char>, std::allocator<char> > string;
+}
+namespace llvm {
+struct StringRef {
+  StringRef(const char *p);
+  StringRef(const std::string &);
+};
+}
+
+void f1(const std::string &s) {
+  f1(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to `c_str()` [readability-remove-cstr-call]
+  // CHECK-FIXES: {{^ *}}f1(s);{{$}}
+}
+void f2(const llvm::StringRef r) {
+  std::string s;
+  f2(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to `c_str()` [readability-remove-cstr-call]
+  // CHECK-FIXES: {{^ *}}std::string s;{{$}}
+  // CHECK-FIXES-NEXT: {{^  *}}f2(s);{{$}}
+}
+void f3(const llvm::StringRef &r) {
+  std::string s;
+  f3(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to `c_str()` [readability-remove-cstr-call]
+  // CHECK-FIXES: {{^ *}}std::string s;{{$}}
+  // CHECK-FIXES-NEXT: {{^  *}}f3(s);{{$}}
+}
Index: test/remove-cstr-calls/basic.cpp
===================================================================
--- test/remove-cstr-calls/basic.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
-// RUN: remove-cstr-calls . %t.cpp --
-// RUN: FileCheck -input-file=%t.cpp %s
-// REQUIRES: shell
-
-namespace std {
-template<typename T> class allocator {};
-template<typename T> class char_traits {};
-template<typename C, typename T, typename A> struct basic_string {
-  basic_string();
-  basic_string(const C *p, const A& a = A());
-  const C *c_str() const;
-};
-typedef basic_string<char, std::char_traits<char>, std::allocator<char> > string;
-}
-namespace llvm {
-struct StringRef {
-  StringRef(const char *p);
-  StringRef(const std::string &);
-};
-}
-
-void f1(const std::string &s) {
-  f1(s.c_str());
-  // CHECK: void f1
-  // CHECK-NEXT: f1(s)
-}
-void f2(const llvm::StringRef r) {
-  std::string s;
-  f2(s.c_str());
-  // CHECK: std::string s; 
-  // CHECK-NEXT: f2(s)
-}
-void f3(const llvm::StringRef &r) {
-  std::string s;
-  f3(s.c_str());
-  // CHECK: std::string s;
-  // CHECK: f3(s)
-}


_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic