<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Reverted in <span style="font-family: Menlo; font-size: 11px;" class="">r275880</span>. Sorry about that. I’ll have to investigate why I didn’t get an email from the bot about the failure.<div class=""><br class=""></div><div class="">Thanks</div><div class="">Devin</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jul 18, 2016, at 11:59 AM, Hans Wennborg <<a href="mailto:hans@chromium.org" class="">hans@chromium.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Oops, as you suspected I failed at copy/paste. This is the bot that's<br class="">broken: <a href="http://bb.pgr.jp/builders/cmake-clang-x86_64-linux/builds/51780" class="">http://bb.pgr.jp/builders/cmake-clang-x86_64-linux/builds/51780</a><br class=""><br class="">On Mon, Jul 18, 2016 at 10:57 AM, Devin Coughlin <<a href="mailto:dcoughlin@apple.com" class="">dcoughlin@apple.com</a>> wrote:<br class=""><blockquote type="cite" class="">Hans,<br class=""><br class="">I’m happy to revert — but I think r275820 is very unlikely to have been the<br class="">root cause of the issue at<br class=""><a href="http://bb.pgr.jp/builders/cmake-llvm-x86_64-linux/builds/40225/" class="">http://bb.pgr.jp/builders/cmake-llvm-x86_64-linux/builds/40225/</a>. (The commit<br class="">is a change to the clang static analyzer and the bot failure seems to be in<br class="">LLVM CodeGen).<br class=""><br class="">Was this just a link mis-copy/paste? Is there another bot failing?<br class=""><br class="">Devin<br class=""><br class="">On Jul 18, 2016, at 10:50 AM, Hans Wennborg <<a href="mailto:hans@chromium.org" class="">hans@chromium.org</a>> wrote:<br class=""><br class="">It seems to have broken this buildbot:<br class=""><a href="http://bb.pgr.jp/builders/cmake-llvm-x86_64-linux/builds/40225/" class="">http://bb.pgr.jp/builders/cmake-llvm-x86_64-linux/builds/40225/</a><br class=""><br class="">I'm just about to create the 3.9 release branch, so it would be great<br class="">if this could fixed/figured out soon.<br class=""><br class="">Thanks,<br class="">Hans<br class=""><br class="">On Mon, Jul 18, 2016 at 10:23 AM, Devin Coughlin via cfe-commits<br class=""><cfe-commits@lists.llvm.org> wrote:<br class=""><br class="">Author: dcoughlin<br class="">Date: Mon Jul 18 12:23:30 2016<br class="">New Revision: 275820<br class=""><br class="">URL: http://llvm.org/viewvc/llvm-project?rev=275820&view=rev<br class="">Log:<br class="">[analyzer] Add checker modeling potential C++ self-assignment<br class=""><br class="">This checker checks copy and move assignment operators whether they are<br class="">protected against self-assignment. Since C++ core guidelines discourages<br class="">explicit checking for `&rhs==this` in general we take a different approach:<br class="">in<br class="">top-frame analysis we branch the exploded graph for two cases, where<br class="">&rhs==this<br class="">and &rhs!=this and let existing checkers (e.g. unix.Malloc) do the rest of<br class="">the<br class="">work. It is important that we check all copy and move assignment operator in<br class="">top<br class="">frame even if we checked them already since self-assignments may happen<br class="">undetected even in the same translation unit (e.g. using random indices for<br class="">an<br class="">array what may or may not be the same).<br class=""><br class="">A patch by Ádám Balogh!<br class=""><br class="">Differential Revision: https://reviews.llvm.org/D19311<br class=""><br class="">Added:<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp<br class=""> cfe/trunk/test/Analysis/self-assign.cpp<br class="">Modified:<br class=""> cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td<br class=""><br class="">cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt<br class=""> cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp<br class=""> cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp<br class=""> cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp<br class=""><br class="">Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td<br class="">URL:<br class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=275820&r1=275819&r2=275820&view=diff<br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original)<br class="">+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Mon Jul 18<br class="">12:23:30 2016<br class="">@@ -247,6 +247,10 @@ def NewDeleteLeaksChecker : Checker<"New<br class=""> HelpText<"Check for memory leaks. Traces memory managed by new/delete.">,<br class=""> DescFile<"MallocChecker.cpp">;<br class=""><br class="">+def CXXSelfAssignmentChecker : Checker<"SelfAssignment">,<br class="">+ HelpText<"Checks C++ copy and move assignment operators for self<br class="">assignment">,<br class="">+ DescFile<"CXXSelfAssignmentChecker.cpp">;<br class="">+<br class="">} // end: "cplusplus"<br class=""><br class="">let ParentPackage = CplusplusAlpha in {<br class=""><br class="">Modified:<br class="">cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h<br class="">URL:<br class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h?rev=275820&r1=275819&r2=275820&view=diff<br class="">==============================================================================<br class="">---<br class="">cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h<br class="">(original)<br class="">+++<br class="">cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h<br class="">Mon Jul 18 12:23:30 2016<br class="">@@ -331,6 +331,22 @@ public:<br class=""> BugReport &BR) override;<br class="">};<br class=""><br class="">+class CXXSelfAssignmentBRVisitor final<br class="">+ : public BugReporterVisitorImpl<CXXSelfAssignmentBRVisitor> {<br class="">+<br class="">+ bool Satisfied;<br class="">+<br class="">+public:<br class="">+ CXXSelfAssignmentBRVisitor() : Satisfied(false) {}<br class="">+<br class="">+ void Profile(llvm::FoldingSetNodeID &ID) const override {}<br class="">+<br class="">+ PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,<br class="">+ const ExplodedNode *Pred,<br class="">+ BugReporterContext &BRC,<br class="">+ BugReport &BR) override;<br class="">+};<br class="">+<br class="">namespace bugreporter {<br class=""><br class="">/// Attempts to add visitors to trace a null or undefined value back to its<br class=""><br class="">Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt<br class="">URL:<br class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=275820&r1=275819&r2=275820&view=diff<br class="">==============================================================================<br class="">--- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original)<br class="">+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Mon Jul 18 12:23:30<br class="">2016<br class="">@@ -22,6 +22,7 @@ add_clang_library(clangStaticAnalyzerChe<br class=""> CheckerDocumentation.cpp<br class=""> ChrootChecker.cpp<br class=""> ClangCheckers.cpp<br class="">+ CXXSelfAssignmentChecker.cpp<br class=""> DeadStoresChecker.cpp<br class=""> DebugCheckers.cpp<br class=""> DereferenceChecker.cpp<br class=""><br class="">Added: cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp<br class="">URL:<br class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp?rev=275820&view=auto<br class="">==============================================================================<br class="">--- cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp<br class="">(added)<br class="">+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp Mon<br class="">Jul 18 12:23:30 2016<br class="">@@ -0,0 +1,62 @@<br class="">+//=== CXXSelfAssignmentChecker.cpp -----------------------------*- C++<br class="">-*--===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+//<br class="">+// This file defines CXXSelfAssignmentChecker, which tests all custom<br class="">defined<br class="">+// copy and move assignment operators for the case of self assignment, thus<br class="">+// where the parameter refers to the same location where the this pointer<br class="">+// points to. The checker itself does not do any checks at all, but it<br class="">+// causes the analyzer to check every copy and move assignment operator<br class="">twice:<br class="">+// once for when 'this' aliases with the parameter and once for when it may<br class="">not.<br class="">+// It is the task of the other enabled checkers to find the bugs in these<br class="">two<br class="">+// different cases.<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+#include "ClangSACheckers.h"<br class="">+#include "clang/StaticAnalyzer/Core/Checker.h"<br class="">+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"<br class="">+<br class="">+using namespace clang;<br class="">+using namespace ento;<br class="">+<br class="">+namespace {<br class="">+<br class="">+class CXXSelfAssignmentChecker : public Checker<check::BeginFunction> {<br class="">+public:<br class="">+ CXXSelfAssignmentChecker();<br class="">+ void checkBeginFunction(CheckerContext &C) const;<br class="">+};<br class="">+}<br class="">+<br class="">+CXXSelfAssignmentChecker::CXXSelfAssignmentChecker() {}<br class="">+<br class="">+void CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext &C) const<br class="">{<br class="">+ if (!C.inTopFrame())<br class="">+ return;<br class="">+ const auto *LCtx = C.getLocationContext();<br class="">+ const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());<br class="">+ if (!MD)<br class="">+ return;<br class="">+ if (!MD->isCopyAssignmentOperator() && !MD->isMoveAssignmentOperator())<br class="">+ return;<br class="">+ auto &State = C.getState();<br class="">+ auto &SVB = C.getSValBuilder();<br class="">+ auto ThisVal =<br class="">+ State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));<br class="">+ auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx));<br class="">+ auto ParamVal = State->getSVal(Param);<br class="">+ ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal);<br class="">+ C.addTransition(SelfAssignState);<br class="">+ ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal);<br class="">+ C.addTransition(NonSelfAssignState);<br class="">+}<br class="">+<br class="">+void ento::registerCXXSelfAssignmentChecker(CheckerManager &Mgr) {<br class="">+ Mgr.registerChecker<CXXSelfAssignmentChecker>();<br class="">+}<br class=""><br class="">Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp<br class="">URL:<br class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=275820&r1=275819&r2=275820&view=diff<br class="">==============================================================================<br class="">--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)<br class="">+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Mon Jul 18 12:23:30<br class="">2016<br class="">@@ -3104,6 +3104,7 @@ bool GRBugReporter::generatePathDiagnost<br class=""> R->addVisitor(llvm::make_unique<NilReceiverBRVisitor>());<br class=""> R->addVisitor(llvm::make_unique<ConditionBRVisitor>());<br class=""><br class="">R->addVisitor(llvm::make_unique<LikelyFalsePositiveSuppressionBRVisitor>());<br class="">+ R->addVisitor(llvm::make_unique<CXXSelfAssignmentBRVisitor>());<br class=""><br class=""> BugReport::VisitorList visitors;<br class=""> unsigned origReportConfigToken, finalReportConfigToken;<br class=""><br class="">Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp<br class="">URL:<br class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=275820&r1=275819&r2=275820&view=diff<br class="">==============================================================================<br class="">--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)<br class="">+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Mon Jul 18<br class="">12:23:30 2016<br class="">@@ -1693,3 +1693,53 @@ UndefOrNullArgVisitor::VisitNode(const E<br class=""> }<br class=""> return nullptr;<br class="">}<br class="">+<br class="">+PathDiagnosticPiece *<br class="">+CXXSelfAssignmentBRVisitor::VisitNode(const ExplodedNode *Succ,<br class="">+ const ExplodedNode *Pred,<br class="">+ BugReporterContext &BRC, BugReport<br class="">&BR) {<br class="">+ if (Satisfied)<br class="">+ return nullptr;<br class="">+<br class="">+ auto Edge = Succ->getLocation().getAs<BlockEdge>();<br class="">+ if (!Edge.hasValue())<br class="">+ return nullptr;<br class="">+<br class="">+ auto Tag = Edge->getTag();<br class="">+ if (!Tag)<br class="">+ return nullptr;<br class="">+<br class="">+ if (Tag->getTagDescription() != "cplusplus.SelfAssignment")<br class="">+ return nullptr;<br class="">+<br class="">+ Satisfied = true;<br class="">+<br class="">+ const auto *Met =<br class="">+ dyn_cast<CXXMethodDecl>(Succ->getCodeDecl().getAsFunction());<br class="">+ assert(Met && "Not a C++ method.");<br class="">+ assert((Met->isCopyAssignmentOperator() ||<br class="">Met->isMoveAssignmentOperator()) &&<br class="">+ "Not a copy/move assignment operator.");<br class="">+<br class="">+ const auto *LCtx = Edge->getLocationContext();<br class="">+<br class="">+ const auto &State = Succ->getState();<br class="">+ auto &SVB = State->getStateManager().getSValBuilder();<br class="">+<br class="">+ const auto Param =<br class="">+ State->getSVal(State->getRegion(Met->getParamDecl(0), LCtx));<br class="">+ const auto This =<br class="">+ State->getSVal(SVB.getCXXThis(Met, LCtx->getCurrentStackFrame()));<br class="">+<br class="">+ auto L = PathDiagnosticLocation::create(Met, BRC.getSourceManager());<br class="">+<br class="">+ if (!L.isValid() || !L.asLocation().isValid())<br class="">+ return nullptr;<br class="">+<br class="">+ const auto Msg = "Assuming " + Met->getParamDecl(0)->getName() +<br class="">+ ((Param == This) ? " == " : " != ") + "*this";<br class="">+<br class="">+ auto *Piece = new PathDiagnosticEventPiece(L, Msg.str());<br class="">+ Piece->addRange(Met->getSourceRange());<br class="">+<br class="">+ return Piece;<br class="">+}<br class=""><br class="">Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp<br class="">URL:<br class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp?rev=275820&r1=275819&r2=275820&view=diff<br class="">==============================================================================<br class="">--- cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (original)<br class="">+++ cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp Mon Jul 18<br class="">12:23:30 2016<br class="">@@ -431,6 +431,13 @@ static bool shouldSkipFunction(const Dec<br class=""> // Count naming convention errors more aggressively.<br class=""> if (isa<ObjCMethodDecl>(D))<br class=""> return false;<br class="">+ // We also want to reanalyze all C++ copy and move assignment operators<br class="">to<br class="">+ // separately check the two cases where 'this' aliases with the parameter<br class="">and<br class="">+ // where it may not. (cplusplus.SelfAssignmentChecker)<br class="">+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {<br class="">+ if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())<br class="">+ return false;<br class="">+ }<br class=""><br class=""> // Otherwise, if we visited the function before, do not reanalyze it.<br class=""> return Visited.count(D);<br class="">@@ -442,9 +449,7 @@ AnalysisConsumer::getInliningModeForFunc<br class=""> // We want to reanalyze all ObjC methods as top level to report Retain<br class=""> // Count naming convention errors more aggressively. But we should tune<br class="">down<br class=""> // inlining when reanalyzing an already inlined function.<br class="">- if (Visited.count(D)) {<br class="">- assert(isa<ObjCMethodDecl>(D) &&<br class="">- "We are only reanalyzing ObjCMethods.");<br class="">+ if (Visited.count(D) && isa<ObjCMethodDecl>(D)) {<br class=""> const ObjCMethodDecl *ObjCM = cast<ObjCMethodDecl>(D);<br class=""> if (ObjCM->getMethodFamily() != OMF_init)<br class=""> return ExprEngine::Inline_Minimal;<br class=""><br class="">Added: cfe/trunk/test/Analysis/self-assign.cpp<br class="">URL:<br class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/self-assign.cpp?rev=275820&view=auto<br class="">==============================================================================<br class="">--- cfe/trunk/test/Analysis/self-assign.cpp (added)<br class="">+++ cfe/trunk/test/Analysis/self-assign.cpp Mon Jul 18 12:23:30 2016<br class="">@@ -0,0 +1,89 @@<br class="">+// RUN: %clang_cc1 -std=c++11 -analyze<br class="">-analyzer-checker=core,cplusplus,unix.Malloc,debug.ExprInspection %s -verify<br class="">-analyzer-output=text<br class="">+<br class="">+extern "C" char *strdup(const char* s);<br class="">+extern "C" void free(void* ptr);<br class="">+<br class="">+namespace std {<br class="">+template<class T> struct remove_reference { typedef T type; };<br class="">+template<class T> struct remove_reference<T&> { typedef T type; };<br class="">+template<class T> struct remove_reference<T&&> { typedef T type; };<br class="">+template<class T> typename remove_reference<T>::type&& move(T&& t);<br class="">+}<br class="">+<br class="">+void clang_analyzer_eval(int);<br class="">+<br class="">+class StringUsed {<br class="">+public:<br class="">+ StringUsed(const char *s = "") : str(strdup(s)) {}<br class="">+ StringUsed(const StringUsed &rhs) : str(strdup(rhs.str)) {}<br class="">+ ~StringUsed();<br class="">+ StringUsed& operator=(const StringUsed &rhs);<br class="">+ StringUsed& operator=(StringUsed &&rhs);<br class="">+ operator const char*() const;<br class="">+private:<br class="">+ char *str;<br class="">+};<br class="">+<br class="">+StringUsed::~StringUsed() {<br class="">+ free(str);<br class="">+}<br class="">+<br class="">+StringUsed& StringUsed::operator=(const StringUsed &rhs) { //<br class="">expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs ==<br class="">*this}} expected-note{{Assuming rhs != *this}}<br class="">+ clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}}<br class="">expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}<br class="">+ free(str); // expected-note{{Memory is released}}<br class="">+ str = strdup(rhs.str); // expected-warning{{Use of memory after it is<br class="">freed}} expected-note{{Use of memory after it is freed}}<br class="">+ return *this;<br class="">+}<br class="">+<br class="">+StringUsed& StringUsed::operator=(StringUsed &&rhs) { //<br class="">expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs !=<br class="">*this}}<br class="">+ clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}}<br class="">expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}<br class="">+ str = rhs.str;<br class="">+ rhs.str = nullptr; // FIXME: An improved leak checker should warn here<br class="">+ return *this;<br class="">+}<br class="">+<br class="">+StringUsed::operator const char*() const {<br class="">+ return str;<br class="">+}<br class="">+<br class="">+class StringUnused {<br class="">+public:<br class="">+ StringUnused(const char *s = "") : str(strdup(s)) {}<br class="">+ StringUnused(const StringUnused &rhs) : str(strdup(rhs.str)) {}<br class="">+ ~StringUnused();<br class="">+ StringUnused& operator=(const StringUnused &rhs);<br class="">+ StringUnused& operator=(StringUnused &&rhs);<br class="">+ operator const char*() const;<br class="">+private:<br class="">+ char *str;<br class="">+};<br class="">+<br class="">+StringUnused::~StringUnused() {<br class="">+ free(str);<br class="">+}<br class="">+<br class="">+StringUnused& StringUnused::operator=(const StringUnused &rhs) { //<br class="">expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs ==<br class="">*this}} expected-note{{Assuming rhs != *this}}<br class="">+ clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}}<br class="">expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}<br class="">+ free(str); // expected-note{{Memory is released}}<br class="">+ str = strdup(rhs.str); // expected-warning{{Use of memory after it is<br class="">freed}} expected-note{{Use of memory after it is freed}}<br class="">+ return *this;<br class="">+}<br class="">+<br class="">+StringUnused& StringUnused::operator=(StringUnused &&rhs) { //<br class="">expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs !=<br class="">*this}}<br class="">+ clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}}<br class="">expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}<br class="">+ str = rhs.str;<br class="">+ rhs.str = nullptr; // FIXME: An improved leak checker should warn here<br class="">+ return *this;<br class="">+}<br class="">+<br class="">+StringUnused::operator const char*() const {<br class="">+ return str;<br class="">+}<br class="">+<br class="">+<br class="">+int main() {<br class="">+ StringUsed s1 ("test"), s2;<br class="">+ s2 = s1;<br class="">+ s2 = std::move(s1);<br class="">+ return 0;<br class="">+}<br class=""><br class=""><br class="">_______________________________________________<br class="">cfe-commits mailing list<br class="">cfe-commits@lists.llvm.org<br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits<br class=""><br class=""><br class=""></blockquote></div></div></blockquote></div><br class=""></div></body></html>