Re: r342827 - Fix modules build with shared library.
Sorry for the unresponsiveness, I've been fire fighting for other stuffs. I'll look into this and try to get it fixed this week. On Tue, Nov 6, 2018 at 9:52 AM David Blaikie wrote: > Shuai - have you had a chance to look at this? > > On Mon, Oct 22, 2018 at 4:43 PM Richard Smith > wrote: > >> On Mon, 22 Oct 2018 at 14:57, David Blaikie via cfe-commits < >> cfe-commits@lists.llvm.org> wrote: >> >>> Richard - any further thoughts here (re: layering/dependencies, etc)? >>> Would love to get the layering oddity fixed rather than having it get more >>> embedded over time. >>> >> >> Here's the intended current directory layout and layering as I understand >> it: >> >> * include/clang/Analysis and lib/Analysis are the parts of the static >> analysis engine that are depended on by both Sema and StaticAnalyzer, and >> include common functionality / infrastructure >> * include/clang/Analysis/Analyses and lib/Analysis/Analyses are the >> specific Sema analyses (that don't depend on the static analyzer); >> StaticAnalyzer should not need to depend on this >> * the StaticAnalyzer library should contain all the pieces that are >> specific to the static analyzer >> * Sema should not depend on Tooling, but it's fine for StaticAnalyzer to >> depend on Tooling >> >> Compared to where we are today, there are two differences: >> >> 1) The implementations of the headers in include/clang/Analysis are in >> lib/Analysis, not in lib/Analysis/Analyses >> 2) ExprMutationAnalyzer is in lib/Analysis despite not being part of the >> common infrastructure depended on by Sema and StaticAnalyzer >> >> For point 1, we should change the lib/Analysis directory layout to match >> the headers. >> For point 2, we should find a home for this ExprMutationAnalyzer code >> that makes sense. Given that the intent is to use it from the static >> analyzer, that seems like a reasonable home for it, but libTooling would >> also make some sense (perhaps a new subdirectory Tooling/Analysis), since >> it's only performing AST matching, not a flow-sensitive / path-sensitive >> static analysis. >> >> On Tue, Oct 2, 2018 at 2:44 PM Shuai Wang via cfe-commits < >>> cfe-commits@lists.llvm.org> wrote: >>> >>>> On Mon, Oct 1, 2018 at 4:58 PM Richard Smith >>>> wrote: >>>> >>>>> On Mon, 1 Oct 2018 at 16:10, George Karpenkov via cfe-commits < >>>>> cfe-commits@lists.llvm.org> wrote: >>>>> >>>>>> Hi Richard, >>>>>> >>>>>> On Oct 1, 2018, at 2:50 PM, Richard Smith via cfe-commits < >>>>>> cfe-commits@lists.llvm.org> wrote: >>>>>> >>>>>> This looks like the wrong fix to me, but I don't really know enough >>>>>> about what's being done with ExprMutationAnalyzer to have an opinion on >>>>>> what the right fix is. >>>>>> >>>>>> Shuai, what is the goal here? Why is this code being moved to >>>>>> Analysis/? >>>>>> >>>>>> >>>>>> I’ve asked for this possibility, as I wanted to use it from the Clang >>>>>> static analyzer. >>>>>> >>>>>> Do you intend to call it from the compiler frontend at some point? I >>>>>> can see a code review for the move itself, but no discussion of a plan or >>>>>> overall direction being followed here. Did I miss it? >>>>>> >>>>>> We have historically decided to not use the tooling interfaces >>>>>> (ASTMatcher, ParentMap, etc) from the frontend, >>>>>> >>>>>> >>>>>> Clang analyzer uses ASTMatcher all over the place. >>>>>> >>>>>> because they're generally a poor fit for our goals (we aim for a >>>>>> largely-single-pass compilation with good locality, and the AST matchers >>>>>> make different design choices) >>>>>> >>>>>> >>>>>> That’s totally good for the analyzer though, right? >>>>>> >>>>> >>>>> Yes, that all seems fine for the static analyzer. >>>>> >>>>> >>>>>> In any case, in future it might make sense to move the analyzer out >>>>>> of Clang proper. >>>>>> But for know the only way to use clang-tidy utilities from the >>>>>> analyzer is to
Re: r342827 - Fix modules build with shared library.
On Mon, Oct 1, 2018 at 4:58 PM Richard Smith wrote: > On Mon, 1 Oct 2018 at 16:10, George Karpenkov via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> Hi Richard, >> >> On Oct 1, 2018, at 2:50 PM, Richard Smith via cfe-commits < >> cfe-commits@lists.llvm.org> wrote: >> >> This looks like the wrong fix to me, but I don't really know enough about >> what's being done with ExprMutationAnalyzer to have an opinion on what the >> right fix is. >> >> Shuai, what is the goal here? Why is this code being moved to Analysis/? >> >> >> I’ve asked for this possibility, as I wanted to use it from the Clang >> static analyzer. >> >> Do you intend to call it from the compiler frontend at some point? I can >> see a code review for the move itself, but no discussion of a plan or >> overall direction being followed here. Did I miss it? >> >> We have historically decided to not use the tooling interfaces >> (ASTMatcher, ParentMap, etc) from the frontend, >> >> >> Clang analyzer uses ASTMatcher all over the place. >> >> because they're generally a poor fit for our goals (we aim for a >> largely-single-pass compilation with good locality, and the AST matchers >> make different design choices) >> >> >> That’s totally good for the analyzer though, right? >> > > Yes, that all seems fine for the static analyzer. > > >> In any case, in future it might make sense to move the analyzer out of >> Clang proper. >> But for know the only way to use clang-tidy utilities from the analyzer >> is to move them into Clang. >> > > Right. I think we should try to maintain the idea that all the Clang > Static Analyzer-specific things are in lib/StaticAnalyzer, and lib/Analysis > only contains things depended on by the frontend. (That is: the things a > clang binary would use if we didn't link in the static analyzer) > > Given the above, I think the best approach would be to move this code out > of lib/Analysis and into somewhere in lib/StaticAnalyzer. There shouldn't > be any problem with clang-tidy using it from there, since it already > depends on the static analyzer. > I'm happy to do the move. Could you (or someone) help point out where exactly I should move it to though? > . If you want to change that, we'll need to discuss that decision. >> >> If the idea is to move this code into clang proper so that it can be used >> by various different tooling clients, we'd need to discuss the right place >> for it. Perhaps lib/Tooling/Analysis would make sense? >> >> >> On Mon, 1 Oct 2018 at 13:13, David Blaikie via cfe-commits < >> cfe-commits@lists.llvm.org> wrote: >> >>> I can't really reproduce this - when I try to build clang/llvm with >>> LLVM_ENABLE_MODULES in CMake I'm still seeing an error I reported March on >>> a cfe-dev thread - something to do with unique_ptr instantiations for >>> MappedBlockStream in the PDB parsing code. >>> >>> So, I'm wondering what error you hit, Eric/where/how, etc... >>> >>> On Sun, Sep 30, 2018 at 10:23 AM Eric Fiselier wrote: >>> +rsmith (actually this time) On Sun, Sep 30, 2018 at 12:09 PM Eric Fiselier wrote: > +rsmith > > Hi All, > > Sorry, I'm not actually sure why this fix is correct.I stole both the > fix and the comment from a similar one on L150 of the module map left by > Richard Smith. > > /Eric > > On Tue, Sep 25, 2018 at 8:36 PM Shuai Wang > wrote: > >> I'd like to understand this better as well, in particular what would >> be a proper fix? >> >> On Tue, Sep 25, 2018 at 2:15 PM David Blaikie >> wrote: >> >>> +Shuai Wang >>> >>> On Tue, Sep 25, 2018 at 2:14 PM David Blaikie >>> wrote: >>> Hey Eric - thanks for the fix - but could you explain the issue here in a bit more detail, as I'm a bit confused (& really interested in understanding any layering problems in LLVM - and fixing them/making sure they're fixed/holding the line/etc) What do you mean by "pull all of the AST matchers library into clang" - how does including a header ever add a link dependency? - Dave On Sat, Sep 22, 2018 at 5:49 PM Eric Fiselier via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: ericwf > Date: Sat Sep 22 17:48:05 2018 > New Revision: 342827 > > URL: http://llvm.org/viewvc/llvm-project?rev=342827=rev > Log: > Fix modules build with shared library. > > r341994 caused clangAnalysis to pull all of the AST matchers > library into clang. Due to inline key functions in the headers, > importing the AST matchers library gives a link dependency on the > AST matchers (and thus the AST), which clang should not > have. > > This patch works around the issues by excluding the offending > libclangAnalysis header in the
Re: r342827 - Fix modules build with shared library.
George wanted to use it from clang (or, at least can't use from anything from clang-tidy.) I was actually assuming the intended usage is from some tooling instead of the frontend itself, but I never checked with George. Personally I don't think ExprMutationAnalyzer should be used in anywhere other than toolings. I'm happy to move it around if current location is not desirable. On Mon, Oct 1, 2018 at 2:50 PM Richard Smith wrote: > This looks like the wrong fix to me, but I don't really know enough about > what's being done with ExprMutationAnalyzer to have an opinion on what the > right fix is. > > Shuai, what is the goal here? Why is this code being moved to Analysis/? > Do you intend to call it from the compiler frontend at some point? I can > see a code review for the move itself, but no discussion of a plan or > overall direction being followed here. Did I miss it? > > We have historically decided to not use the tooling interfaces > (ASTMatcher, ParentMap, etc) from the frontend, because they're generally a > poor fit for our goals (we aim for a largely-single-pass compilation with > good locality, and the AST matchers make different design choices). If you > want to change that, we'll need to discuss that decision. > > If the idea is to move this code into clang proper so that it can be used > by various different tooling clients, we'd need to discuss the right place > for it. Perhaps lib/Tooling/Analysis would make sense? > > On Mon, 1 Oct 2018 at 13:13, David Blaikie via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> I can't really reproduce this - when I try to build clang/llvm with >> LLVM_ENABLE_MODULES in CMake I'm still seeing an error I reported March on >> a cfe-dev thread - something to do with unique_ptr instantiations for >> MappedBlockStream in the PDB parsing code. >> >> So, I'm wondering what error you hit, Eric/where/how, etc... >> >> On Sun, Sep 30, 2018 at 10:23 AM Eric Fiselier wrote: >> >>> +rsmith (actually this time) >>> >>> On Sun, Sep 30, 2018 at 12:09 PM Eric Fiselier wrote: >>> +rsmith Hi All, Sorry, I'm not actually sure why this fix is correct.I stole both the fix and the comment from a similar one on L150 of the module map left by Richard Smith. /Eric On Tue, Sep 25, 2018 at 8:36 PM Shuai Wang wrote: > I'd like to understand this better as well, in particular what would > be a proper fix? > > On Tue, Sep 25, 2018 at 2:15 PM David Blaikie > wrote: > >> +Shuai Wang >> >> On Tue, Sep 25, 2018 at 2:14 PM David Blaikie >> wrote: >> >>> Hey Eric - thanks for the fix - but could you explain the issue here >>> in a bit more detail, as I'm a bit confused (& really interested in >>> understanding any layering problems in LLVM - and fixing them/making >>> sure >>> they're fixed/holding the line/etc) >>> >>> What do you mean by "pull all of the AST matchers library into >>> clang" - how does including a header ever add a link dependency? >>> >>> - Dave >>> >>> >>> On Sat, Sep 22, 2018 at 5:49 PM Eric Fiselier via cfe-commits < >>> cfe-commits@lists.llvm.org> wrote: >>> Author: ericwf Date: Sat Sep 22 17:48:05 2018 New Revision: 342827 URL: http://llvm.org/viewvc/llvm-project?rev=342827=rev Log: Fix modules build with shared library. r341994 caused clangAnalysis to pull all of the AST matchers library into clang. Due to inline key functions in the headers, importing the AST matchers library gives a link dependency on the AST matchers (and thus the AST), which clang should not have. This patch works around the issues by excluding the offending libclangAnalysis header in the modulemap. Modified: cfe/trunk/include/clang/module.modulemap Modified: cfe/trunk/include/clang/module.modulemap URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/module.modulemap?rev=342827=342826=342827=diff == --- cfe/trunk/include/clang/module.modulemap (original) +++ cfe/trunk/include/clang/module.modulemap Sat Sep 22 17:48:05 2018 @@ -5,6 +5,12 @@ module Clang_Analysis { textual header "Analysis/Analyses/ThreadSafetyOps.def" module * { export * } + + // FIXME: Exclude these headers to avoid pulling all of the AST matchers + // library into clang. Due to inline key functions in the headers, + // importing the AST matchers library gives a link dependency on the AST + // matchers (and thus the AST), which clang-format should not have. + exclude header
Re: r342827 - Fix modules build with shared library.
I'd like to understand this better as well, in particular what would be a proper fix? On Tue, Sep 25, 2018 at 2:15 PM David Blaikie wrote: > +Shuai Wang > > On Tue, Sep 25, 2018 at 2:14 PM David Blaikie wrote: > >> Hey Eric - thanks for the fix - but could you explain the issue here in a >> bit more detail, as I'm a bit confused (& really interested in >> understanding any layering problems in LLVM - and fixing them/making sure >> they're fixed/holding the line/etc) >> >> What do you mean by "pull all of the AST matchers library into clang" - >> how does including a header ever add a link dependency? >> >> - Dave >> >> >> On Sat, Sep 22, 2018 at 5:49 PM Eric Fiselier via cfe-commits < >> cfe-commits@lists.llvm.org> wrote: >> >>> Author: ericwf >>> Date: Sat Sep 22 17:48:05 2018 >>> New Revision: 342827 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=342827=rev >>> Log: >>> Fix modules build with shared library. >>> >>> r341994 caused clangAnalysis to pull all of the AST matchers >>> library into clang. Due to inline key functions in the headers, >>> importing the AST matchers library gives a link dependency on the >>> AST matchers (and thus the AST), which clang should not >>> have. >>> >>> This patch works around the issues by excluding the offending >>> libclangAnalysis header in the modulemap. >>> >>> Modified: >>> cfe/trunk/include/clang/module.modulemap >>> >>> Modified: cfe/trunk/include/clang/module.modulemap >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/module.modulemap?rev=342827=342826=342827=diff >>> >>> == >>> --- cfe/trunk/include/clang/module.modulemap (original) >>> +++ cfe/trunk/include/clang/module.modulemap Sat Sep 22 17:48:05 2018 >>> @@ -5,6 +5,12 @@ module Clang_Analysis { >>>textual header "Analysis/Analyses/ThreadSafetyOps.def" >>> >>>module * { export * } >>> + >>> + // FIXME: Exclude these headers to avoid pulling all of the AST >>> matchers >>> + // library into clang. Due to inline key functions in the headers, >>> + // importing the AST matchers library gives a link dependency on the >>> AST >>> + // matchers (and thus the AST), which clang-format should not have. >>> + exclude header "Analysis/Analyses/ExprMutationAnalyzer.h" >>> } >>> >>> module Clang_AST { >>> >>> >>> ___ >>> cfe-commits mailing list >>> cfe-commits@lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>> >> ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342586 - [NFC] Declare instead of define non-void functions in unit tests.
Author: shuaiwang Date: Wed Sep 19 13:27:25 2018 New Revision: 342586 URL: http://llvm.org/viewvc/llvm-project?rev=342586=rev Log: [NFC] Declare instead of define non-void functions in unit tests. Modified: cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Modified: cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp?rev=342586=342585=342586=diff == --- cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp (original) +++ cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Wed Sep 19 13:27:25 2018 @@ -203,7 +203,7 @@ TEST(ExprMutationAnalyzerTest, ByValueAr EXPECT_FALSE(isMutated(Results, AST.get())); AST = buildASTFromCode( - "struct A {}; A operator+(A, int) {} void f() { A x; x + 1; }"); + "struct A {}; A operator+(A, int); void f() { A x; x + 1; }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); @@ -239,7 +239,7 @@ TEST(ExprMutationAnalyzerTest, ByConstVa EXPECT_FALSE(isMutated(Results, AST.get())); AST = buildASTFromCode( - "struct A {}; A operator+(const A, int) {} void f() { A x; x + 1; }"); + "struct A {}; A operator+(const A, int); void f() { A x; x + 1; }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); @@ -289,7 +289,7 @@ TEST(ExprMutationAnalyzerTest, ByNonCons EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)")); AST = buildASTFromCode( - "struct A {}; A operator+(A&, int) {} void f() { A x; x + 1; }"); + "struct A {}; A operator+(A&, int); void f() { A x; x + 1; }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x + 1")); @@ -333,7 +333,7 @@ TEST(ExprMutationAnalyzerTest, ByConstRe EXPECT_FALSE(isMutated(Results, AST.get())); AST = buildASTFromCode( - "struct A {}; A operator+(const A&, int) {} void f() { A x; x + 1; }"); + "struct A {}; A operator+(const A&, int); void f() { A x; x + 1; }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); @@ -356,7 +356,7 @@ TEST(ExprMutationAnalyzerTest, ByNonCons EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(static_cast(x))")); - AST = buildASTFromCode("struct A {}; A operator+(A&&, int) {}" + AST = buildASTFromCode("struct A {}; A operator+(A&&, int);" "void f() { A x; static_cast(x) + 1; }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), @@ -382,7 +382,7 @@ TEST(ExprMutationAnalyzerTest, ByConstRR match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); - AST = buildASTFromCode("struct A {}; A operator+(const A&&, int) {}" + AST = buildASTFromCode("struct A {}; A operator+(const A&&, int);" "void f() { A x; static_cast(x) + 1; }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342562 - [analyzer] Fix nullptr access when processing instantiated function in ExprMutationAnalyzer.
Author: shuaiwang Date: Wed Sep 19 11:00:55 2018 New Revision: 342562 URL: http://llvm.org/viewvc/llvm-project?rev=342562=rev Log: [analyzer] Fix nullptr access when processing instantiated function in ExprMutationAnalyzer. Modified: cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Modified: cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp?rev=342562=342561=342562=diff == --- cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp (original) +++ cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp Wed Sep 19 11:00:55 2018 @@ -379,7 +379,7 @@ const Stmt *ExprMutationAnalyzer::findFu for (const auto : Matches) { const auto *Exp = Nodes.getNodeAs(NodeID::value); const auto *Func = Nodes.getNodeAs("func"); -if (!Func->getBody()) +if (!Func->getBody() || !Func->getPrimaryTemplate()) return Exp; const auto *Parm = Nodes.getNodeAs("parm"); Modified: cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp?rev=342562=342561=342562=diff == --- cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp (original) +++ cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Wed Sep 19 11:00:55 2018 @@ -215,6 +215,12 @@ TEST(ExprMutationAnalyzerTest, ByValueAr "void f() { A x, y; y = x; }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); + + AST = buildASTFromCode( + "template struct A { A(); A(const A&); static void mf(A) {} };" + "void f() { A<0> x; A<0>::mf(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); } TEST(ExprMutationAnalyzerTest, ByConstValueArgument) { @@ -241,6 +247,12 @@ TEST(ExprMutationAnalyzerTest, ByConstVa "void f() { struct A { A(const int); }; int x; A y(x); }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); + + AST = buildASTFromCode("template struct A { A(); A(const A&);" + "static void mf(const A&) {} };" + "void f() { A<0> x; A<0>::mf(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); } TEST(ExprMutationAnalyzerTest, ByNonConstRefArgument) { @@ -288,6 +300,12 @@ TEST(ExprMutationAnalyzerTest, ByNonCons AST = buildASTFromCode("void f() { struct A { A(); A(A&); }; A x; A y(x); }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x")); + + AST = buildASTFromCode( + "template struct A { A(); A(const A&); static void mf(A&) {} };" + "void f() { A<0> x; A<0>::mf(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("A<0>::mf(x)")); } TEST(ExprMutationAnalyzerTest, ByConstRefArgument) { @@ -686,6 +704,12 @@ TEST(ExprMutationAnalyzerTest, FollowFun Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x")); + AST = buildASTFromCode("template struct S {" + "template S(T&& t) : m(++t) { } U m; };" + "void f() { int x; S s(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x")); + AST = buildASTFromCode(StdRemoveReference + StdForward + "template void u(Args&...);" "template void h(Args&&... args)" @@ -737,6 +761,12 @@ TEST(ExprMutationAnalyzerTest, FollowFun Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); + AST = buildASTFromCode("template struct S {" + "template S(T&& t) : m(t) { } U m; };" + "void f() { int x; S s(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); + AST = buildASTFromCode(StdRemoveReference + StdForward + "template void u(Args...);" "template void h(Args&&... args)" ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342525 - [NFC] Fix uncompilable test cases of ExprMutationAnalyzer.
Author: shuaiwang Date: Tue Sep 18 20:50:03 2018 New Revision: 342525 URL: http://llvm.org/viewvc/llvm-project?rev=342525=rev Log: [NFC] Fix uncompilable test cases of ExprMutationAnalyzer. And ensure future test cases doesn't have compile errors. Modified: cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Modified: cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp?rev=342525=342524=342525=diff == --- cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp (original) +++ cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Tue Sep 18 20:50:03 2018 @@ -29,6 +29,18 @@ namespace { using ExprMatcher = internal::Matcher; using StmtMatcher = internal::Matcher; +std::unique_ptr +buildASTFromCodeWithArgs(const Twine , + const std::vector ) { + auto AST = tooling::buildASTFromCodeWithArgs(Code, Args); + EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); + return AST; +} + +std::unique_ptr buildASTFromCode(const Twine ) { + return buildASTFromCodeWithArgs(Code, {}); +} + ExprMatcher declRefTo(StringRef Name) { return declRefExpr(to(namedDecl(hasName(Name; } @@ -83,12 +95,12 @@ const std::string StdForward = "template T&& " "forward(typename remove_reference::type& t) noexcept { return t; }" "template T&& " -"forward(typename remove_reference::type&&) noexcept { return t; } }"; +"forward(typename remove_reference::type&& t) noexcept { return t; } }"; } // namespace TEST(ExprMutationAnalyzerTest, Trivial) { - const auto AST = tooling::buildASTFromCode("void f() { int x; x; }"); + const auto AST = buildASTFromCode("void f() { int x; x; }"); const auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); @@ -98,8 +110,7 @@ class AssignmentTest : public ::testing: TEST_P(AssignmentTest, AssignmentModifies) { const std::string ModExpr = "x " + GetParam() + " 10"; - const auto AST = - tooling::buildASTFromCode("void f() { int x; " + ModExpr + "; }"); + const auto AST = buildASTFromCode("void f() { int x; " + ModExpr + "; }"); const auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr)); @@ -113,8 +124,7 @@ class IncDecTest : public ::testing::Tes TEST_P(IncDecTest, IncDecModifies) { const std::string ModExpr = GetParam(); - const auto AST = - tooling::buildASTFromCode("void f() { int x; " + ModExpr + "; }"); + const auto AST = buildASTFromCode("void f() { int x; " + ModExpr + "; }"); const auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr)); @@ -124,7 +134,7 @@ INSTANTIATE_TEST_CASE_P(AllIncDecOperato Values("++x", "--x", "x++", "x--"), ); TEST(ExprMutationAnalyzerTest, NonConstMemberFunc) { - const auto AST = tooling::buildASTFromCode( + const auto AST = buildASTFromCode( "void f() { struct Foo { void mf(); }; Foo x; x.mf(); }"); const auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); @@ -132,7 +142,7 @@ TEST(ExprMutationAnalyzerTest, NonConstM } TEST(ExprMutationAnalyzerTest, AssumedNonConstMemberFunc) { - auto AST = tooling::buildASTFromCodeWithArgs( + auto AST = buildASTFromCodeWithArgs( "struct X { template void mf(); };" "template void f() { X x; x.mf(); }", {"-fno-delayed-template-parsing"}); @@ -140,13 +150,12 @@ TEST(ExprMutationAnalyzerTest, AssumedNo match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); - AST = tooling::buildASTFromCodeWithArgs( - "template void f() { T x; x.mf(); }", - {"-fno-delayed-template-parsing"}); + AST = buildASTFromCodeWithArgs("template void f() { T x; x.mf(); }", + {"-fno-delayed-template-parsing"}); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); - AST = tooling::buildASTFromCodeWithArgs( + AST = buildASTFromCodeWithArgs( "template struct X;" "template void f() { X x; x.mf(); }", {"-fno-delayed-template-parsing"}); @@ -155,7 +164,7 @@ TEST(ExprMutationAnalyzerTest, AssumedNo } TEST(ExprMutationAnalyzerTest, ConstMemberFunc) { - const auto AST = tooling::buildASTFromCode( + const auto AST = buildASTFromCode( "void f() { struct Foo { void mf() const; }; Foo x; x.mf(); }"); const auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); @@ -163,7 +172,7 @@
[clang-tools-extra] r342417 - [clang-tidy] Fix tests for performance-for-range-copy
Author: shuaiwang Date: Mon Sep 17 14:28:08 2018 New Revision: 342417 URL: http://llvm.org/viewvc/llvm-project?rev=342417=rev Log: [clang-tidy] Fix tests for performance-for-range-copy Test failed as D52120 made ExprMutationAnalyzer smarter, fixed by: - Add move-ctor for `Mutable` to make it actually movable. - Properly implement `remove_reference`. The failed test case is: void negativeVarIsMoved() { for (auto M : View>()) { auto Moved = std::move(M); } } Before D52120, `std::move(M)` itself is considered as a mutation to `M`, while after D52120 it's only considered as a cast to rvalue, the move-assignment is what causes the actual mutation. The test case didn't mock things properly so the intended move-assignement was actually a copy-assignment. Modified: clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp Modified: clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp?rev=342417=342416=342417=diff == --- clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp (original) +++ clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp Mon Sep 17 14:28:08 2018 @@ -4,6 +4,10 @@ namespace std { template struct remove_reference { typedef _Tp type; }; +template +struct remove_reference<_Tp&> { typedef _Tp type; }; +template +struct remove_reference<_Tp&&> { typedef _Tp type; }; template constexpr typename std::remove_reference<_Tp>::type &(_Tp &&__t) { @@ -103,6 +107,7 @@ void f() { struct Mutable { Mutable() {} Mutable(const Mutable &) = default; + Mutable(Mutable&&) = default; Mutable(const Mutable &, const Mutable &) {} void setBool(bool B) {} bool constMethod() const { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342409 - [analyzer] Treat std::{move, forward} as casts in ExprMutationAnalyzer.
Author: shuaiwang Date: Mon Sep 17 13:10:56 2018 New Revision: 342409 URL: http://llvm.org/viewvc/llvm-project?rev=342409=rev Log: [analyzer] Treat std::{move,forward} as casts in ExprMutationAnalyzer. Summary: This is a follow up of D52008 and should make the analyzer being able to handle perfect forwardings in real world cases where forwardings are done through multiple layers of function calls with `std::forward`. Fixes PR38891. Reviewers: lebedev.ri, JonasToth, george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin, mikhail.ramalho, Szelethus, cfe-commits Differential Revision: https://reviews.llvm.org/D52120 Modified: cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Modified: cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp?rev=342409=342408=342409=diff == --- cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp (original) +++ cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp Mon Sep 17 13:10:56 2018 @@ -304,7 +304,16 @@ const Stmt *ExprMutationAnalyzer::findCa nonConstReferenceType() .bind(NodeID::value)), Stm, Context); - return findExprMutation(Casts); + if (const Stmt *S = findExprMutation(Casts)) +return S; + // Treat std::{move,forward} as cast. + const auto Calls = + match(findAll(callExpr(callee(namedDecl( + hasAnyName("::std::move", "::std::forward"))), + hasArgument(0, equalsNode(Exp))) +.bind("expr")), +Stm, Context); + return findExprMutation(Calls); } const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(const Expr *Exp) { @@ -360,7 +369,9 @@ const Stmt *ExprMutationAnalyzer::findFu const auto IsInstantiated = hasDeclaration(isInstantiated()); const auto FuncDecl = hasDeclaration(functionDecl().bind("func")); const auto Matches = match( - findAll(expr(anyOf(callExpr(NonConstRefParam, IsInstantiated, FuncDecl), + findAll(expr(anyOf(callExpr(NonConstRefParam, IsInstantiated, FuncDecl, + unless(callee(namedDecl(hasAnyName( + "::std::move", "::std::forward"), cxxConstructExpr(NonConstRefParam, IsInstantiated, FuncDecl))) .bind(NodeID::value)), Modified: cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp?rev=342409=342408=342409=diff == --- cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp (original) +++ cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Mon Sep 17 13:10:56 2018 @@ -66,6 +66,25 @@ std::string removeSpace(std::string s) { return s; } +const std::string StdRemoveReference = +"namespace std {" +"template struct remove_reference { typedef T type; };" +"template struct remove_reference { typedef T type; };" +"template struct remove_reference { typedef T type; }; }"; + +const std::string StdMove = +"namespace std {" +"template typename remove_reference::type&& " +"move(T&& t) noexcept {" +"return static_cast::type&&>(t); } }"; + +const std::string StdForward = +"namespace std {" +"template T&& " +"forward(typename remove_reference::type& t) noexcept { return t; }" +"template T&& " +"forward(typename remove_reference::type&&) noexcept { return t; } }"; + } // namespace TEST(ExprMutationAnalyzerTest, Trivial) { @@ -373,36 +392,87 @@ TEST(ExprMutationAnalyzerTest, ByConstRR } TEST(ExprMutationAnalyzerTest, Move) { - // Technically almost the same as ByNonConstRRefArgument, just double checking - const auto AST = tooling::buildASTFromCode( - "namespace std {" - "template struct remove_reference { typedef T type; };" - "template struct remove_reference { typedef T type; };" - "template struct remove_reference { typedef T type; };" - "template typename std::remove_reference::type&& " - "move(T&& t) noexcept; }" - "void f() { struct A {}; A x; std::move(x); }"); - const auto Results = + auto AST = + tooling::buildASTFromCode(StdRemoveReference + StdMove + +"void f() { struct A {}; A x; std::move(x); }"); + auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); - EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("std::move(x)")); + EXPECT_FALSE(isMutated(Results, AST.get())); + + AST = tooling::buildASTFromCode( + StdRemoveReference + StdMove + + "void f() { struct A {}; A x, y; std::move(x) =
[clang-tools-extra] r342408 - Fix build failure caused by D52157
Author: shuaiwang Date: Mon Sep 17 13:10:33 2018 New Revision: 342408 URL: http://llvm.org/viewvc/llvm-project?rev=342408=rev Log: Fix build failure caused by D52157 Modified: clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp Modified: clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp?rev=342408=342407=342408=diff == --- clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp (original) +++ clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp Mon Sep 17 13:10:33 2018 @@ -115,7 +115,7 @@ TEST_F(QueryEngineTest, Basic) { Str.clear(); - EXPECT_FALSE(MatchQuery(isArrow()).run(OS, S)); + EXPECT_FALSE(MatchQuery(isMain()).run(OS, S)); EXPECT_EQ("Not a valid top-level matcher.\n", OS.str()); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342407 - [ASTMatchers] Let isArrow also support UnresolvedMemberExpr, CXXDependentScopeMemberExpr
Author: shuaiwang Date: Mon Sep 17 11:48:43 2018 New Revision: 342407 URL: http://llvm.org/viewvc/llvm-project?rev=342407=rev Log: [ASTMatchers] Let isArrow also support UnresolvedMemberExpr, CXXDependentScopeMemberExpr Reviewers: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D52157 Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=342407=342406=342407=diff == --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Mon Sep 17 11:48:43 2018 @@ -2235,6 +2235,32 @@ cxxConstructorDecl(hasAnyConstructorInit +Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html;>CXXDependentScopeMemberExprisArrow +Matches member expressions that are called with '-' as opposed +to '.'. + +Member calls on the implicit this pointer match as called with '-'. + +Given + class Y { +void x() { this-x(); x(); Y y; y.x(); a; this-b; Y::b; } +template class T void f() { this-fT(); fT(); } +int a; +static int b; + }; + template class T + class Z { +void x() { this-m; } + }; +memberExpr(isArrow()) + matches this-x, x, y.x, a, this-b +cxxDependentScopeMemberExpr(isArrow()) + matches this-m +unresolvedMemberExpr(isArrow()) + matches this-fT, fT + + + Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html;>CXXMethodDeclisConst Matches if the given method declaration is const. @@ -3228,11 +3254,20 @@ Member calls on the implicit this pointe Given class Y { void x() { this-x(); x(); Y y; y.x(); a; this-b; Y::b; } +template class T void f() { this-fT(); fT(); } int a; static int b; }; + template class T + class Z { +void x() { this-m; } + }; memberExpr(isArrow()) matches this-x, x, y.x, a, this-b +cxxDependentScopeMemberExpr(isArrow()) + matches this-m +unresolvedMemberExpr(isArrow()) + matches this-fT, fT @@ -3886,6 +3921,32 @@ Example matches a || b (matcher = binary +Matcherhttp://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html;>UnresolvedMemberExprisArrow +Matches member expressions that are called with '-' as opposed +to '.'. + +Member calls on the implicit this pointer match as called with '-'. + +Given + class Y { +void x() { this-x(); x(); Y y; y.x(); a; this-b; Y::b; } +template class T void f() { this-fT(); fT(); } +int a; +static int b; + }; + template class T + class Z { +void x() { this-m; } + }; +memberExpr(isArrow()) + matches this-x, x, y.x, a, this-b +cxxDependentScopeMemberExpr(isArrow()) + matches this-m +unresolvedMemberExpr(isArrow()) + matches this-fT, fT + + + Matcherhttp://clang.llvm.org/doxygen/classclang_1_1VarDecl.html;>VarDeclhasAutomaticStorageDuration Matches a variable declaration that has automatic storage duration. Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=342407=342406=342407=diff == --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Mon Sep 17 11:48:43 2018 @@ -4697,13 +4697,24 @@ AST_MATCHER(CXXMethodDecl, isUserProvide /// \code /// class Y { /// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } +/// template void f() { this->f(); f(); } /// int a; /// static int b; /// }; +/// template +/// class Z { +/// void x() { this->m; } +/// }; /// \endcode /// memberExpr(isArrow()) /// matches this->x, x, y.x, a, this->b -AST_MATCHER(MemberExpr, isArrow) { +/// cxxDependentScopeMemberExpr(isArrow()) +/// matches this->m +/// unresolvedMemberExpr(isArrow()) +/// matches this->f, f +AST_POLYMORPHIC_MATCHER( +isArrow, AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr, + CXXDependentScopeMemberExpr)) { return Node.isArrow(); } Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp?rev=342407=342406=342407=diff == --- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Mon Sep 17 11:48:43 2018 @@ -765,6 +765,11 @@ TEST(IsArrow,
[clang-tools-extra] r342403 - [clang-tidy] Remove duplicated logic in UnnecessaryValueParamCheck and use FunctionParmMutationAnalyzer instead.
Author: shuaiwang Date: Mon Sep 17 10:59:51 2018 New Revision: 342403 URL: http://llvm.org/viewvc/llvm-project?rev=342403=rev Log: [clang-tidy] Remove duplicated logic in UnnecessaryValueParamCheck and use FunctionParmMutationAnalyzer instead. Reviewers: alexfh, JonasToth, george.karpenkov Subscribers: xazax.hun, kristof.beyls, chrib, a.sidorin, Szelethus, cfe-commits Differential Revision: https://reviews.llvm.org/D52158 Modified: clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.h Modified: clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp?rev=342403=342402=342403=diff == --- clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp Mon Sep 17 10:59:51 2018 @@ -13,7 +13,6 @@ #include "../utils/FixItHintUtils.h" #include "../utils/Matchers.h" #include "../utils/TypeTraits.h" -#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" @@ -92,21 +91,11 @@ void UnnecessaryValueParamCheck::check(c const auto *Param = Result.Nodes.getNodeAs("param"); const auto *Function = Result.Nodes.getNodeAs("functionDecl"); - // Do not trigger on non-const value parameters when they are mutated either - // within the function body or within init expression(s) when the function is - // a ctor. - if (ExprMutationAnalyzer(*Function->getBody(), *Result.Context) - .isMutated(Param)) + FunctionParmMutationAnalyzer = + MutationAnalyzers.try_emplace(Function, *Function, *Result.Context) + .first->second; + if (Analyzer.isMutated(Param)) return; - // CXXCtorInitializer might also mutate Param but they're not part of function - // body, so check them separately here. - if (const auto *Ctor = dyn_cast(Function)) { -for (const auto *Init : Ctor->inits()) { - if (ExprMutationAnalyzer(*Init->getInit(), *Result.Context) - .isMutated(Param)) -return; -} - } const bool IsConstQualified = Param->getType().getCanonicalType().isConstQualified(); @@ -186,6 +175,10 @@ void UnnecessaryValueParamCheck::storeOp utils::IncludeSorter::toString(IncludeStyle)); } +void UnnecessaryValueParamCheck::onEndOfTranslationUnit() { + MutationAnalyzers.clear(); +} + void UnnecessaryValueParamCheck::handleMoveFix(const ParmVarDecl , const DeclRefExpr , const ASTContext ) { Modified: clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.h?rev=342403=342402=342403=diff == --- clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.h (original) +++ clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.h Mon Sep 17 10:59:51 2018 @@ -12,6 +12,7 @@ #include "../ClangTidy.h" #include "../utils/IncludeInserter.h" +#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" namespace clang { namespace tidy { @@ -29,11 +30,14 @@ public: void check(const ast_matchers::MatchFinder::MatchResult ) override; void registerPPCallbacks(CompilerInstance ) override; void storeOptions(ClangTidyOptions::OptionMap ) override; + void onEndOfTranslationUnit() override; private: void handleMoveFix(const ParmVarDecl , const DeclRefExpr , const ASTContext ); + llvm::DenseMap + MutationAnalyzers; std::unique_ptr Inserter; const utils::IncludeSorter::IncludeStyle IncludeStyle; }; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342353 - [NFC] Minor refactoring to setup the stage for supporting pointers in ExprMutationAnalyzer
Author: shuaiwang Date: Sun Sep 16 14:09:50 2018 New Revision: 342353 URL: http://llvm.org/viewvc/llvm-project?rev=342353=rev Log: [NFC] Minor refactoring to setup the stage for supporting pointers in ExprMutationAnalyzer Modified: cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp Modified: cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h?rev=342353=342352=342353=diff == --- cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h (original) +++ cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h Sun Sep 16 14:09:50 2018 @@ -31,13 +31,32 @@ public: const Stmt *findMutation(const Expr *Exp); const Stmt *findMutation(const Decl *Dec); + bool isPointeeMutated(const Expr *Exp) { +return findPointeeMutation(Exp) != nullptr; + } + bool isPointeeMutated(const Decl *Dec) { +return findPointeeMutation(Dec) != nullptr; + } + const Stmt *findPointeeMutation(const Expr *Exp); + const Stmt *findPointeeMutation(const Decl *Dec); + private: + using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *); using ResultMap = llvm::DenseMap; + const Stmt *findMutationMemoized(const Expr *Exp, + llvm::ArrayRef Finders, + ResultMap ); + const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder); + bool isUnevaluated(const Expr *Exp); const Stmt *findExprMutation(ArrayRef Matches); const Stmt *findDeclMutation(ArrayRef Matches); + const Stmt * + findExprPointeeMutation(ArrayRef Matches); + const Stmt * + findDeclPointeeMutation(ArrayRef Matches); const Stmt *findDirectMutation(const Expr *Exp); const Stmt *findMemberMutation(const Expr *Exp); @@ -53,6 +72,7 @@ private: std::unique_ptr> FuncParmAnalyzer; ResultMap Results; + ResultMap PointeeResults; }; // A convenient wrapper around ExprMutationAnalyzer for analyzing function Modified: cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp?rev=342353=342352=342353=diff == --- cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp (original) +++ cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp Sun Sep 16 14:09:50 2018 @@ -64,33 +64,83 @@ const auto isMoveOnly = [] { unless(isDeleted())); }; +template struct NodeID; +template <> struct NodeID { static const std::string value; }; +template <> struct NodeID { static const std::string value; }; +const std::string NodeID::value = "expr"; +const std::string NodeID::value = "decl"; + +template +const Stmt *tryEachMatch(ArrayRef Matches, + ExprMutationAnalyzer *Analyzer, F Finder) { + const StringRef ID = NodeID::value; + for (const auto : Matches) { +if (const Stmt *S = (Analyzer->*Finder)(Nodes.getNodeAs(ID))) + return S; + } + return nullptr; +} + } // namespace const Stmt *ExprMutationAnalyzer::findMutation(const Expr *Exp) { - const auto Memoized = Results.find(Exp); - if (Memoized != Results.end()) + return findMutationMemoized(Exp, + {::findDirectMutation, + ::findMemberMutation, + ::findArrayElementMutation, + ::findCastMutation, + ::findRangeLoopMutation, + ::findReferenceMutation, + ::findFunctionArgMutation}, + Results); +} + +const Stmt *ExprMutationAnalyzer::findMutation(const Decl *Dec) { + return tryEachDeclRef(Dec, ::findMutation); +} + +const Stmt *ExprMutationAnalyzer::findPointeeMutation(const Expr *Exp) { + return findMutationMemoized(Exp, {/*TODO*/}, PointeeResults); +} + +const Stmt *ExprMutationAnalyzer::findPointeeMutation(const Decl *Dec) { + return tryEachDeclRef(Dec, ::findPointeeMutation); +} + +const Stmt *ExprMutationAnalyzer::findMutationMemoized( +const Expr *Exp, llvm::ArrayRef Finders, +ResultMap ) { + const auto Memoized = MemoizedResults.find(Exp); + if (Memoized != MemoizedResults.end()) return Memoized->second; if (isUnevaluated(Exp)) -return Results[Exp] = nullptr; +return MemoizedResults[Exp] = nullptr; - for (const auto : {::findDirectMutation, - ::findMemberMutation, - ::findArrayElementMutation, - ::findCastMutation, - ::findRangeLoopMutation, - ::findReferenceMutation, -
r342340 - [NFC] cosmetic tweaks to ExprMutationAnalyzer to be more consistent
Author: shuaiwang Date: Sat Sep 15 14:38:18 2018 New Revision: 342340 URL: http://llvm.org/viewvc/llvm-project?rev=342340=rev Log: [NFC] cosmetic tweaks to ExprMutationAnalyzer to be more consistent especially considering future changes. Modified: cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp Modified: cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h?rev=342340=342339=342340=diff == --- cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h (original) +++ cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h Sat Sep 15 14:38:18 2018 @@ -26,12 +26,14 @@ public: ExprMutationAnalyzer(const Stmt , ASTContext ) : Stm(Stm), Context(Context) {} - bool isMutated(const Decl *Dec) { return findDeclMutation(Dec) != nullptr; } bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; } + bool isMutated(const Decl *Dec) { return findMutation(Dec) != nullptr; } const Stmt *findMutation(const Expr *Exp); - const Stmt *findDeclMutation(const Decl *Dec); + const Stmt *findMutation(const Decl *Dec); private: + using ResultMap = llvm::DenseMap; + bool isUnevaluated(const Expr *Exp); const Stmt *findExprMutation(ArrayRef Matches); @@ -50,7 +52,7 @@ private: llvm::DenseMap> FuncParmAnalyzer; - llvm::DenseMap Results; + ResultMap Results; }; // A convenient wrapper around ExprMutationAnalyzer for analyzing function Modified: cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp?rev=342340=342339=342340=diff == --- cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp (original) +++ cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp Sat Sep 15 14:38:18 2018 @@ -131,13 +131,13 @@ ExprMutationAnalyzer::findExprMutation(A const Stmt * ExprMutationAnalyzer::findDeclMutation(ArrayRef Matches) { for (const auto : Matches) { -if (const Stmt *S = findDeclMutation(DeclNodes.getNodeAs("decl"))) +if (const Stmt *S = findMutation(DeclNodes.getNodeAs("decl"))) return S; } return nullptr; } -const Stmt *ExprMutationAnalyzer::findDeclMutation(const Decl *Dec) { +const Stmt *ExprMutationAnalyzer::findMutation(const Decl *Dec) { const auto Refs = match( findAll(declRefExpr(to(equalsNode(Dec))).bind("expr")), Stm, Context); for (const auto : Refs) { @@ -280,15 +280,14 @@ const Stmt *ExprMutationAnalyzer::findRe // Follow non-const reference returned by `operator*()` of move-only classes. // These are typically smart pointers with unique ownership so we treat // mutation of pointee as mutation of the smart pointer itself. - const auto Ref = match( - findAll(cxxOperatorCallExpr( - hasOverloadedOperatorName("*"), - callee(cxxMethodDecl(ofClass(isMoveOnly()), - returns(hasUnqualifiedDesugaredType( - nonConstReferenceType(), - argumentCountIs(1), hasArgument(0, equalsNode(Exp))) - .bind("expr")), - Stm, Context); + const auto Ref = + match(findAll(cxxOperatorCallExpr( +hasOverloadedOperatorName("*"), +callee(cxxMethodDecl(ofClass(isMoveOnly()), + returns(nonConstReferenceType(, +argumentCountIs(1), hasArgument(0, equalsNode(Exp))) +.bind("expr")), +Stm, Context); if (const Stmt *S = findExprMutation(Ref)) return S; @@ -370,7 +369,7 @@ FunctionParmMutationAnalyzer::FunctionPa for (const ParmVarDecl *Parm : Ctor->parameters()) { if (Results.find(Parm) != Results.end()) continue; -if (const Stmt *S = InitAnalyzer.findDeclMutation(Parm)) +if (const Stmt *S = InitAnalyzer.findMutation(Parm)) Results[Parm] = S; } } @@ -383,7 +382,7 @@ FunctionParmMutationAnalyzer::findMutati if (Memoized != Results.end()) return Memoized->second; - if (const Stmt *S = BodyAnalyzer.findDeclMutation(Parm)) + if (const Stmt *S = BodyAnalyzer.findMutation(Parm)) return Results[Parm] = S; return Results[Parm] = nullptr; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342271 - [analyzer] Handle forwarding reference better in ExprMutationAnalyzer.
Author: shuaiwang Date: Fri Sep 14 13:07:18 2018 New Revision: 342271 URL: http://llvm.org/viewvc/llvm-project?rev=342271=rev Log: [analyzer] Handle forwarding reference better in ExprMutationAnalyzer. Summary: We used to treat an `Expr` mutated whenever it's passed as non-const reference argument to a function. This results in false positives in cases like this: ``` int x; std::vector v; v.emplace_back(x); // `x` is passed as non-const reference to `emplace_back` ``` In theory the false positives can be suppressed with `v.emplace_back(std::as_const(x))` but that's considered overly verbose, inconsistent with existing code and spammy as diags. This diff handles such cases by following into the function definition and see whether the argument is mutated inside. Reviewers: lebedev.ri, JonasToth, george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin, mikhail.ramalho, Szelethus, cfe-commits Differential Revision: https://reviews.llvm.org/D52008 Modified: cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Modified: cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h?rev=342271=342270=342271=diff == --- cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h (original) +++ cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h Fri Sep 14 13:07:18 2018 @@ -17,6 +17,8 @@ namespace clang { +class FunctionParmMutationAnalyzer; + /// Analyzes whether any mutative operations are applied to an expression within /// a given statement. class ExprMutationAnalyzer { @@ -27,13 +29,13 @@ public: bool isMutated(const Decl *Dec) { return findDeclMutation(Dec) != nullptr; } bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; } const Stmt *findMutation(const Expr *Exp); + const Stmt *findDeclMutation(const Decl *Dec); private: bool isUnevaluated(const Expr *Exp); const Stmt *findExprMutation(ArrayRef Matches); const Stmt *findDeclMutation(ArrayRef Matches); - const Stmt *findDeclMutation(const Decl *Dec); const Stmt *findDirectMutation(const Expr *Exp); const Stmt *findMemberMutation(const Expr *Exp); @@ -41,12 +43,32 @@ private: const Stmt *findCastMutation(const Expr *Exp); const Stmt *findRangeLoopMutation(const Expr *Exp); const Stmt *findReferenceMutation(const Expr *Exp); + const Stmt *findFunctionArgMutation(const Expr *Exp); const Stmt ASTContext + llvm::DenseMap> + FuncParmAnalyzer; llvm::DenseMap Results; }; +// A convenient wrapper around ExprMutationAnalyzer for analyzing function +// params. +class FunctionParmMutationAnalyzer { +public: + FunctionParmMutationAnalyzer(const FunctionDecl , ASTContext ); + + bool isMutated(const ParmVarDecl *Parm) { +return findMutation(Parm) != nullptr; + } + const Stmt *findMutation(const ParmVarDecl *Parm); + +private: + ExprMutationAnalyzer BodyAnalyzer; + llvm::DenseMap Results; +}; + } // namespace clang #endif // LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H Modified: cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp?rev=342271=342270=342271=diff == --- cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp (original) +++ cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp Fri Sep 14 13:07:18 2018 @@ -79,7 +79,8 @@ const Stmt *ExprMutationAnalyzer::findMu ::findArrayElementMutation, ::findCastMutation, ::findRangeLoopMutation, - ::findReferenceMutation}) { + ::findReferenceMutation, + ::findFunctionArgMutation}) { if (const Stmt *S = (this->*Finder)(Exp)) return Results[Exp] = S; } @@ -192,10 +193,15 @@ const Stmt *ExprMutationAnalyzer::findDi // Used as non-const-ref argument when calling a function. // An argument is assumed to be non-const-ref when the function is unresolved. + // Instantiated template functions are not handled here but in + // findFunctionArgMutation which has additional smarts for handling forwarding + // references. const auto NonConstRefParam = forEachArgumentWithParam( equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType(; + const auto NotInstantiated = unless(hasDeclaration(isInstantiated())); const auto AsNonConstRefArg = anyOf( - callExpr(NonConstRefParam), cxxConstructExpr(NonConstRefParam), + callExpr(NonConstRefParam, NotInstantiated), + cxxConstructExpr(NonConstRefParam, NotInstantiated),
r342246 - Remove PseudoConstantAnalysis
Author: shuaiwang Date: Fri Sep 14 10:27:27 2018 New Revision: 342246 URL: http://llvm.org/viewvc/llvm-project?rev=342246=rev Log: Remove PseudoConstantAnalysis Summary: It's not used anywhere for years. The last usage is removed in https://reviews.llvm.org/rL198476 in 2014. Subscribers: mgorny, cfe-commits Differential Revision: https://reviews.llvm.org/D51946 Removed: cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp Modified: cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp cfe/trunk/lib/Analysis/CMakeLists.txt Removed: cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h?rev=342245=auto == --- cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h (original) +++ cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h (removed) @@ -1,45 +0,0 @@ -//== PseudoConstantAnalysis.h - Find Pseudo-constants in the AST -*- C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--===// -// -// This file tracks the usage of variables in a Decl body to see if they are -// never written to, implying that they constant. This is useful in static -// analysis to see if a developer might have intended a variable to be const. -// -//===--===// - -#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H -#define LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H - -#include "clang/AST/Stmt.h" - -namespace clang { - -class PseudoConstantAnalysis { -public: - PseudoConstantAnalysis(const Stmt *DeclBody); - ~PseudoConstantAnalysis(); - - bool isPseudoConstant(const VarDecl *VD); - bool wasReferenced(const VarDecl *VD); - -private: - void RunAnalysis(); - inline static const Decl *getDecl(const Expr *E); - - // for storing the result of analyzed ValueDecls - void *NonConstantsImpl; - void *UsedVarsImpl; - - const Stmt *DeclBody; - bool Analyzed; -}; - -} - -#endif Modified: cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h?rev=342246=342245=342246=diff == --- cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h (original) +++ cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h Fri Sep 14 10:27:27 2018 @@ -40,7 +40,6 @@ class ImplicitParamDecl; class LocationContext; class LocationContextManager; class ParentMap; -class PseudoConstantAnalysis; class StackFrameContext; class Stmt; class VarDecl; @@ -84,7 +83,6 @@ class AnalysisDeclContext { bool builtCFG = false; bool builtCompleteCFG = false; std::unique_ptr PM; - std::unique_ptr PCA; std::unique_ptr CFA; llvm::BumpPtrAllocator A; @@ -175,7 +173,6 @@ public: bool isCFGBuilt() const { return builtCFG; } ParentMap (); - PseudoConstantAnalysis *getPseudoConstantAnalysis(); using referenced_decls_iterator = const VarDecl * const *; Modified: cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp?rev=342246=342245=342246=diff == --- cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp (original) +++ cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp Fri Sep 14 10:27:27 2018 @@ -27,7 +27,6 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtVisitor.h" #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" -#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" #include "clang/Analysis/BodyFarm.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/CFGStmtMap.h" @@ -292,12 +291,6 @@ ParentMap ::getParen return *PM; } -PseudoConstantAnalysis *AnalysisDeclContext::getPseudoConstantAnalysis() { - if (!PCA) -PCA.reset(new PseudoConstantAnalysis(getBody())); - return PCA.get(); -} - AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) { if (const auto *FD = dyn_cast(D)) { // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl Modified: cfe/trunk/lib/Analysis/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=342246=342245=342246=diff == --- cfe/trunk/lib/Analysis/CMakeLists.txt (original) +++ cfe/trunk/lib/Analysis/CMakeLists.txt Fri Sep 14 10:27:27 2018 @@
[clang-tools-extra] r342012 - [NFC] Fix build breakage due to missing dep caused by D51950
Author: shuaiwang Date: Tue Sep 11 17:32:13 2018 New Revision: 342012 URL: http://llvm.org/viewvc/llvm-project?rev=342012=rev Log: [NFC] Fix build breakage due to missing dep caused by D51950 Modified: clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt Modified: clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt?rev=342012=342011=342012=diff == --- clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt (original) +++ clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt Tue Sep 11 17:32:13 2018 @@ -18,6 +18,7 @@ add_clang_library(clangTidyPerformanceMo LINK_LIBS clangAST clangASTMatchers + clangAnalysis clangBasic clangLex clangTidy ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] r342006 - [clangtidy] Remove old copy of ExprMutationAnalyzer
Author: shuaiwang Date: Tue Sep 11 15:59:46 2018 New Revision: 342006 URL: http://llvm.org/viewvc/llvm-project?rev=342006=rev Log: [clangtidy] Remove old copy of ExprMutationAnalyzer Summary: This is 2/2 of moving ExprMutationAnalyzer from clangtidy to clang/Analysis. ExprMutationAnalyzer is moved to clang/Analysis in D51948. This diff migrates existing usages within clangtidy to point to the new location and remove the old copy of ExprMutationAnalyzer. Reviewers: george.karpenkov, JonasToth Reviewed By: george.karpenkov Subscribers: mgorny, a.sidorin, Szelethus, cfe-commits Differential Revision: https://reviews.llvm.org/D51950 Removed: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.h clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Modified: clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt clang-tools-extra/trunk/unittests/clang-tidy/CMakeLists.txt Modified: clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp?rev=342006=342005=342006=diff == --- clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp Tue Sep 11 15:59:46 2018 @@ -9,9 +9,9 @@ #include "ForRangeCopyCheck.h" #include "../utils/DeclRefExprUtils.h" -#include "../utils/ExprMutationAnalyzer.h" #include "../utils/FixItHintUtils.h" #include "../utils/TypeTraits.h" +#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" using namespace clang::ast_matchers; @@ -88,8 +88,7 @@ bool ForRangeCopyCheck::handleCopyIsOnly // Because the fix (changing to `const auto &`) will introduce an unused // compiler warning which can't be suppressed. // Since this case is very rare, it is safe to ignore it. - if (!utils::ExprMutationAnalyzer(*ForRange.getBody(), Context) - .isMutated() && + if (!ExprMutationAnalyzer(*ForRange.getBody(), Context).isMutated() && !utils::decl_ref_expr::allDeclRefExprs(LoopVar, *ForRange.getBody(), Context) .empty()) { Modified: clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp?rev=342006=342005=342006=diff == --- clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp Tue Sep 11 15:59:46 2018 @@ -10,10 +10,10 @@ #include "UnnecessaryValueParamCheck.h" #include "../utils/DeclRefExprUtils.h" -#include "../utils/ExprMutationAnalyzer.h" #include "../utils/FixItHintUtils.h" #include "../utils/Matchers.h" #include "../utils/TypeTraits.h" +#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" @@ -95,14 +95,14 @@ void UnnecessaryValueParamCheck::check(c // Do not trigger on non-const value parameters when they are mutated either // within the function body or within init expression(s) when the function is // a ctor. - if (utils::ExprMutationAnalyzer(*Function->getBody(), *Result.Context) + if (ExprMutationAnalyzer(*Function->getBody(), *Result.Context) .isMutated(Param)) return; // CXXCtorInitializer might also mutate Param but they're not part of function // body, so check them separately here. if (const auto *Ctor = dyn_cast(Function)) { for (const auto *Init : Ctor->inits()) { - if (utils::ExprMutationAnalyzer(*Init->getInit(), *Result.Context) + if (ExprMutationAnalyzer(*Init->getInit(), *Result.Context) .isMutated(Param)) return; } Modified: clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt?rev=342006=342005=342006=diff == --- clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt (original) +++ clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt Tue Sep 11 15:59:46 2018 @@ -3,7 +3,6 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyUtils ASTUtils.cpp DeclRefExprUtils.cpp - ExprMutationAnalyzer.cpp ExprSequence.cpp FixItHintUtils.cpp HeaderFileExtensionsUtils.cpp Removed:
r342005 - [NFC] Fix build breakage caused by D51948
Author: shuaiwang Date: Tue Sep 11 15:41:14 2018 New Revision: 342005 URL: http://llvm.org/viewvc/llvm-project?rev=342005=rev Log: [NFC] Fix build breakage caused by D51948 Modified: cfe/trunk/lib/Analysis/CMakeLists.txt Modified: cfe/trunk/lib/Analysis/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=342005=342004=342005=diff == --- cfe/trunk/lib/Analysis/CMakeLists.txt (original) +++ cfe/trunk/lib/Analysis/CMakeLists.txt Tue Sep 11 15:41:14 2018 @@ -34,6 +34,7 @@ add_clang_library(clangAnalysis LINK_LIBS clangAST + clangASTMatchers clangBasic clangLex ) ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r341994 - [analyzer] Add ExprMutationAnalyzer
Author: shuaiwang Date: Tue Sep 11 14:13:20 2018 New Revision: 341994 URL: http://llvm.org/viewvc/llvm-project?rev=341994=rev Log: [analyzer] Add ExprMutationAnalyzer Summary: This is 1/2 of moving ExprMutationAnalyzer from clangtidy to clang/Analysis. This diff along simply copies the ExprMutationAnalyzer over with trivial modifications (e.g. include path, namespace) 2/2 will migrate existing usage of ExprMutationAnalyzer and remove the original copy inside clangtidy. Reviewers: george.karpenkov Subscribers: mgorny, xazax.hun, szepet, a.sidorin, mikhail.ramalho, Szelethus, cfe-commits, JonasToth Differential Revision: https://reviews.llvm.org/D51948 Added: cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp cfe/trunk/unittests/Analysis/ExprMutationAnalyzerTest.cpp Modified: cfe/trunk/lib/Analysis/CMakeLists.txt cfe/trunk/unittests/Analysis/CMakeLists.txt Added: cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h?rev=341994=auto == --- cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h (added) +++ cfe/trunk/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h Tue Sep 11 14:13:20 2018 @@ -0,0 +1,52 @@ +//===-- ExprMutationAnalyzer.h ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H + +#include + +#include "clang/AST/AST.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "llvm/ADT/DenseMap.h" + +namespace clang { + +/// Analyzes whether any mutative operations are applied to an expression within +/// a given statement. +class ExprMutationAnalyzer { +public: + ExprMutationAnalyzer(const Stmt , ASTContext ) + : Stm(Stm), Context(Context) {} + + bool isMutated(const Decl *Dec) { return findDeclMutation(Dec) != nullptr; } + bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; } + const Stmt *findMutation(const Expr *Exp); + +private: + bool isUnevaluated(const Expr *Exp); + + const Stmt *findExprMutation(ArrayRef Matches); + const Stmt *findDeclMutation(ArrayRef Matches); + const Stmt *findDeclMutation(const Decl *Dec); + + const Stmt *findDirectMutation(const Expr *Exp); + const Stmt *findMemberMutation(const Expr *Exp); + const Stmt *findArrayElementMutation(const Expr *Exp); + const Stmt *findCastMutation(const Expr *Exp); + const Stmt *findRangeLoopMutation(const Expr *Exp); + const Stmt *findReferenceMutation(const Expr *Exp); + + const Stmt + ASTContext + llvm::DenseMap Results; +}; + +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H Modified: cfe/trunk/lib/Analysis/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=341994=341993=341994=diff == --- cfe/trunk/lib/Analysis/CMakeLists.txt (original) +++ cfe/trunk/lib/Analysis/CMakeLists.txt Tue Sep 11 14:13:20 2018 @@ -15,6 +15,7 @@ add_clang_library(clangAnalysis Consumed.cpp CodeInjector.cpp Dominators.cpp + ExprMutationAnalyzer.cpp FormatString.cpp LiveVariables.cpp OSLog.cpp Added: cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp?rev=341994=auto == --- cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp (added) +++ cfe/trunk/lib/Analysis/ExprMutationAnalyzer.cpp Tue Sep 11 14:13:20 2018 @@ -0,0 +1,308 @@ +//===-- ExprMutationAnalyzer.cpp --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// +#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "llvm/ADT/STLExtras.h" + +namespace clang { +using namespace ast_matchers; + +namespace { + +AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) { + return llvm::is_contained(Node.capture_inits(), E); +} + +AST_MATCHER_P(CXXForRangeStmt, hasRangeStmt, + ast_matchers::internal::Matcher, InnerMatcher) { + const DeclStmt *const Range = Node.getRangeStmt(); + return InnerMatcher.matches(*Range, Finder, Builder); +}
[clang-tools-extra] r341986 - [clang-tidy] Handle sugared reference types in ExprMutationAnalyzer
Author: shuaiwang Date: Tue Sep 11 13:05:37 2018 New Revision: 341986 URL: http://llvm.org/viewvc/llvm-project?rev=341986=rev Log: [clang-tidy] Handle sugared reference types in ExprMutationAnalyzer Summary: This handles cases like this: ``` typedef int& IntRef; void mutate(IntRef); void f() { int x; mutate(x); } ``` where the param type is a sugared type (`TypedefType`) instead of a reference type directly. Note that another category of similar but different cases are already handled properly before: ``` typedef int Int; void mutate(Int&); void f() { int x; mutate(x); } ``` Reviewers: aaron.ballman, alexfh, george.karpenkov Subscribers: xazax.hun, a.sidorin, Szelethus, cfe-commits Differential Revision: https://reviews.llvm.org/D50953 Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp?rev=341986=341985=341986=diff == --- clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp Tue Sep 11 13:05:37 2018 @@ -48,11 +48,13 @@ AST_MATCHER_P(GenericSelectionExpr, hasC } const auto nonConstReferenceType = [] { - return referenceType(pointee(unless(isConstQualified(; + return hasUnqualifiedDesugaredType( + referenceType(pointee(unless(isConstQualified(); }; const auto nonConstPointerType = [] { - return pointerType(pointee(unless(isConstQualified(; + return hasUnqualifiedDesugaredType( + pointerType(pointee(unless(isConstQualified(); }; const auto isMoveOnly = [] { @@ -185,12 +187,11 @@ const Stmt *ExprMutationAnalyzer::findDi // Treat calling `operator->()` of move-only classes as taking address. // These are typically smart pointers with unique ownership so we treat // mutation of pointee as mutation of the smart pointer itself. - const auto AsOperatorArrowThis = cxxOperatorCallExpr( - hasOverloadedOperatorName("->"), - callee(cxxMethodDecl( - ofClass(isMoveOnly()), - returns(hasUnqualifiedDesugaredType(nonConstPointerType(), - argumentCountIs(1), hasArgument(0, equalsNode(Exp))); + const auto AsOperatorArrowThis = + cxxOperatorCallExpr(hasOverloadedOperatorName("->"), + callee(cxxMethodDecl(ofClass(isMoveOnly()), + returns(nonConstPointerType(, + argumentCountIs(1), hasArgument(0, equalsNode(Exp))); // Used as non-const-ref argument when calling a function. // An argument is assumed to be non-const-ref when the function is unresolved. Modified: clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp?rev=341986=341985=341986=diff == --- clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp (original) +++ clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Tue Sep 11 13:05:37 2018 @@ -168,6 +168,15 @@ TEST(ExprMutationAnalyzerTest, ByValueAr match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); + AST = tooling::buildASTFromCode("void g(int*); void f() { int* x; g(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); + + AST = tooling::buildASTFromCode("typedef int* IntPtr;" + "void g(IntPtr); void f() { int* x; g(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); + AST = tooling::buildASTFromCode( "void f() { struct A {}; A operator+(A, int); A x; x + 1; }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); @@ -184,6 +193,40 @@ TEST(ExprMutationAnalyzerTest, ByValueAr EXPECT_FALSE(isMutated(Results, AST.get())); } +TEST(ExprMutationAnalyzerTest, ByConstValueArgument) { + auto AST = + tooling::buildASTFromCode("void g(const int); void f() { int x; g(x); }"); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); + + AST = tooling::buildASTFromCode( + "void g(int* const); void f() { int* x; g(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); + + AST = + tooling::buildASTFromCode("typedef
[clang-tools-extra] r341967 - [clang-tidy] Handle unique owning smart pointers in ExprMutationAnalyzer
Author: shuaiwang Date: Tue Sep 11 10:33:12 2018 New Revision: 341967 URL: http://llvm.org/viewvc/llvm-project?rev=341967=rev Log: [clang-tidy] Handle unique owning smart pointers in ExprMutationAnalyzer Summary: For smart pointers like std::unique_ptr which uniquely owns the underlying object, treat the mutation of the pointee as mutation of the smart pointer itself. This gives better behavior for cases like this: ``` void f(std::vector> v) { // undesirable analyze result of `v` as not mutated. for (auto& p : v) { p->mutate(); // only const member function `operator->` is invoked on `p` } } ``` Reviewers: hokein, george.karpenkov Subscribers: xazax.hun, a.sidorin, Szelethus, cfe-commits Differential Revision: https://reviews.llvm.org/D50883 Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp?rev=341967=341966=341967=diff == --- clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp Tue Sep 11 10:33:12 2018 @@ -51,6 +51,20 @@ const auto nonConstReferenceType = [] { return referenceType(pointee(unless(isConstQualified(; }; +const auto nonConstPointerType = [] { + return pointerType(pointee(unless(isConstQualified(; +}; + +const auto isMoveOnly = [] { + return cxxRecordDecl( + hasMethod(cxxConstructorDecl(isMoveConstructor(), unless(isDeleted(, + hasMethod(cxxMethodDecl(isMoveAssignmentOperator(), unless(isDeleted(, + unless(anyOf(hasMethod(cxxConstructorDecl(isCopyConstructor(), +unless(isDeleted(, + hasMethod(cxxMethodDecl(isCopyAssignmentOperator(), + unless(isDeleted())); +}; + } // namespace const Stmt *ExprMutationAnalyzer::findMutation(const Expr *Exp) { @@ -168,6 +182,15 @@ const Stmt *ExprMutationAnalyzer::findDi const auto AsPointerFromArrayDecay = castExpr(hasCastKind(CK_ArrayToPointerDecay), unless(hasParent(arraySubscriptExpr())), has(equalsNode(Exp))); + // Treat calling `operator->()` of move-only classes as taking address. + // These are typically smart pointers with unique ownership so we treat + // mutation of pointee as mutation of the smart pointer itself. + const auto AsOperatorArrowThis = cxxOperatorCallExpr( + hasOverloadedOperatorName("->"), + callee(cxxMethodDecl( + ofClass(isMoveOnly()), + returns(hasUnqualifiedDesugaredType(nonConstPointerType(), + argumentCountIs(1), hasArgument(0, equalsNode(Exp))); // Used as non-const-ref argument when calling a function. // An argument is assumed to be non-const-ref when the function is unresolved. @@ -197,8 +220,8 @@ const Stmt *ExprMutationAnalyzer::findDi const auto Matches = match(findAll(stmt(anyOf(AsAssignmentLhs, AsIncDecOperand, AsNonConstThis, AsAmpersandOperand, AsPointerFromArrayDecay, - AsNonConstRefArg, AsLambdaRefCaptureInit, - AsNonConstRefReturn)) + AsOperatorArrowThis, AsNonConstRefArg, + AsLambdaRefCaptureInit, AsNonConstRefReturn)) .bind("stmt")), Stm, Context); return selectFirst("stmt", Matches); @@ -250,6 +273,21 @@ const Stmt *ExprMutationAnalyzer::findRa } const Stmt *ExprMutationAnalyzer::findReferenceMutation(const Expr *Exp) { + // Follow non-const reference returned by `operator*()` of move-only classes. + // These are typically smart pointers with unique ownership so we treat + // mutation of pointee as mutation of the smart pointer itself. + const auto Ref = match( + findAll(cxxOperatorCallExpr( + hasOverloadedOperatorName("*"), + callee(cxxMethodDecl(ofClass(isMoveOnly()), + returns(hasUnqualifiedDesugaredType( + nonConstReferenceType(), + argumentCountIs(1), hasArgument(0, equalsNode(Exp))) + .bind("expr")), + Stm, Context); + if (const Stmt *S = findExprMutation(Ref)) +return S; + // If 'Exp' is bound to a non-const reference, check all declRefExpr to that. const auto Refs = match( stmt(forEachDescendant( Modified: clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp URL:
[clang-tools-extra] r341891 - Revert "Revert "[clang-tidy] Handle unresolved expressions in ExprMutationAnalyzer""
Author: shuaiwang Date: Mon Sep 10 19:23:35 2018 New Revision: 341891 URL: http://llvm.org/viewvc/llvm-project?rev=341891=rev Log: Revert "Revert "[clang-tidy] Handle unresolved expressions in ExprMutationAnalyzer"" This is the same as D50619 plus fixes for buildbot failures on windows. The test failures on windows are caused by -fdelayed-template-parsing and is fixed by forcing -fno-delayed-template-parsing on test cases that requires AST for uninstantiated templates. Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp?rev=341891=341890=341891=diff == --- clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp Mon Sep 10 19:23:35 2018 @@ -145,11 +145,16 @@ const Stmt *ExprMutationAnalyzer::findDi hasUnaryOperand(equalsNode(Exp))); // Invoking non-const member function. + // A member function is assumed to be non-const when it is unresolved. const auto NonConstMethod = cxxMethodDecl(unless(isConst())); const auto AsNonConstThis = expr(anyOf(cxxMemberCallExpr(callee(NonConstMethod), on(equalsNode(Exp))), cxxOperatorCallExpr(callee(NonConstMethod), - hasArgument(0, equalsNode(Exp); + hasArgument(0, equalsNode(Exp))), + callExpr(callee(expr(anyOf( + unresolvedMemberExpr(hasObjectExpression(equalsNode(Exp))), + cxxDependentScopeMemberExpr( + hasObjectExpression(equalsNode(Exp); // Taking address of 'Exp'. // We're assuming 'Exp' is mutated as soon as its address is taken, though in @@ -165,10 +170,16 @@ const Stmt *ExprMutationAnalyzer::findDi unless(hasParent(arraySubscriptExpr())), has(equalsNode(Exp))); // Used as non-const-ref argument when calling a function. + // An argument is assumed to be non-const-ref when the function is unresolved. const auto NonConstRefParam = forEachArgumentWithParam( equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType(; - const auto AsNonConstRefArg = - anyOf(callExpr(NonConstRefParam), cxxConstructExpr(NonConstRefParam)); + const auto AsNonConstRefArg = anyOf( + callExpr(NonConstRefParam), cxxConstructExpr(NonConstRefParam), + callExpr(callee(expr(anyOf(unresolvedLookupExpr(), unresolvedMemberExpr(), + cxxDependentScopeMemberExpr(), + hasType(templateTypeParmType(), + hasAnyArgument(equalsNode(Exp))), + cxxUnresolvedConstructExpr(hasAnyArgument(equalsNode(Exp; // Captured by a lambda by reference. // If we're initializing a capture with 'Exp' directly then we're initializing @@ -195,9 +206,12 @@ const Stmt *ExprMutationAnalyzer::findDi const Stmt *ExprMutationAnalyzer::findMemberMutation(const Expr *Exp) { // Check whether any member of 'Exp' is mutated. - const auto MemberExprs = match( - findAll(memberExpr(hasObjectExpression(equalsNode(Exp))).bind("expr")), - Stm, Context); + const auto MemberExprs = + match(findAll(expr(anyOf(memberExpr(hasObjectExpression(equalsNode(Exp))), + cxxDependentScopeMemberExpr( + hasObjectExpression(equalsNode(Exp) +.bind("expr")), +Stm, Context); return findExprMutation(MemberExprs); } Modified: clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp?rev=341891=341890=341891=diff == --- clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp (original) +++ clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Mon Sep 10 19:23:35 2018 @@ -114,6 +114,29 @@ TEST(ExprMutationAnalyzerTest, NonConstM EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); } +TEST(ExprMutationAnalyzerTest, AssumedNonConstMemberFunc) { + auto AST = tooling::buildASTFromCodeWithArgs( + "struct X { template void mf(); };" + "template void f() { X x; x.mf(); }", + {"-fno-delayed-template-parsing"}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); + + AST = tooling::buildASTFromCodeWithArgs( +
[clang-tools-extra] r341886 - Revert "[clang-tidy] Handle unresolved expressions in ExprMutationAnalyzer"
Author: shuaiwang Date: Mon Sep 10 16:58:04 2018 New Revision: 341886 URL: http://llvm.org/viewvc/llvm-project?rev=341886=rev Log: Revert "[clang-tidy] Handle unresolved expressions in ExprMutationAnalyzer" Summary: Tests somehow break on windows (and only on windows) http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/13003 http://lab.llvm.org:8011/builders/clang-x86-windows-msvc2015/builds/13747 I have yet figure out why so reverting to unbreak first. Reviewers: george.karpenkov Subscribers: xazax.hun, a.sidorin, Szelethus, cfe-commits Differential Revision: https://reviews.llvm.org/D51898 Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp?rev=341886=341885=341886=diff == --- clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp Mon Sep 10 16:58:04 2018 @@ -145,16 +145,11 @@ const Stmt *ExprMutationAnalyzer::findDi hasUnaryOperand(equalsNode(Exp))); // Invoking non-const member function. - // A member function is assumed to be non-const when it is unresolved. const auto NonConstMethod = cxxMethodDecl(unless(isConst())); const auto AsNonConstThis = expr(anyOf(cxxMemberCallExpr(callee(NonConstMethod), on(equalsNode(Exp))), cxxOperatorCallExpr(callee(NonConstMethod), - hasArgument(0, equalsNode(Exp))), - callExpr(callee(expr(anyOf( - unresolvedMemberExpr(hasObjectExpression(equalsNode(Exp))), - cxxDependentScopeMemberExpr( - hasObjectExpression(equalsNode(Exp); + hasArgument(0, equalsNode(Exp); // Taking address of 'Exp'. // We're assuming 'Exp' is mutated as soon as its address is taken, though in @@ -170,16 +165,10 @@ const Stmt *ExprMutationAnalyzer::findDi unless(hasParent(arraySubscriptExpr())), has(equalsNode(Exp))); // Used as non-const-ref argument when calling a function. - // An argument is assumed to be non-const-ref when the function is unresolved. const auto NonConstRefParam = forEachArgumentWithParam( equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType(; - const auto AsNonConstRefArg = anyOf( - callExpr(NonConstRefParam), cxxConstructExpr(NonConstRefParam), - callExpr(callee(expr(anyOf(unresolvedLookupExpr(), unresolvedMemberExpr(), - cxxDependentScopeMemberExpr(), - hasType(templateTypeParmType(), - hasAnyArgument(equalsNode(Exp))), - cxxUnresolvedConstructExpr(hasAnyArgument(equalsNode(Exp; + const auto AsNonConstRefArg = + anyOf(callExpr(NonConstRefParam), cxxConstructExpr(NonConstRefParam)); // Captured by a lambda by reference. // If we're initializing a capture with 'Exp' directly then we're initializing @@ -206,12 +195,9 @@ const Stmt *ExprMutationAnalyzer::findDi const Stmt *ExprMutationAnalyzer::findMemberMutation(const Expr *Exp) { // Check whether any member of 'Exp' is mutated. - const auto MemberExprs = - match(findAll(expr(anyOf(memberExpr(hasObjectExpression(equalsNode(Exp))), - cxxDependentScopeMemberExpr( - hasObjectExpression(equalsNode(Exp) -.bind("expr")), -Stm, Context); + const auto MemberExprs = match( + findAll(memberExpr(hasObjectExpression(equalsNode(Exp))).bind("expr")), + Stm, Context); return findExprMutation(MemberExprs); } Modified: clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp?rev=341886=341885=341886=diff == --- clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp (original) +++ clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Mon Sep 10 16:58:04 2018 @@ -114,26 +114,6 @@ TEST(ExprMutationAnalyzerTest, NonConstM EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); } -TEST(ExprMutationAnalyzerTest, AssumedNonConstMemberFunc) { - auto AST = tooling::buildASTFromCode( - "struct X { template void mf(); };" - "template void f() { X x; x.mf(); }"); - auto Results = - match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); - EXPECT_THAT(mutatedBy(Results,
[clang-tools-extra] r341848 - [clang-tidy] Handle unresolved expressions in ExprMutationAnalyzer
Author: shuaiwang Date: Mon Sep 10 11:05:13 2018 New Revision: 341848 URL: http://llvm.org/viewvc/llvm-project?rev=341848=rev Log: [clang-tidy] Handle unresolved expressions in ExprMutationAnalyzer Summary: - If a function is unresolved, assume it mutates its arguments - Follow unresolved member expressions for nested mutations Reviewers: aaron.ballman, JonasToth, george.karpenkov Subscribers: xazax.hun, a.sidorin, cfe-commits Differential Revision: https://reviews.llvm.org/D50619 Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Modified: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp?rev=341848=341847=341848=diff == --- clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp Mon Sep 10 11:05:13 2018 @@ -145,11 +145,16 @@ const Stmt *ExprMutationAnalyzer::findDi hasUnaryOperand(equalsNode(Exp))); // Invoking non-const member function. + // A member function is assumed to be non-const when it is unresolved. const auto NonConstMethod = cxxMethodDecl(unless(isConst())); const auto AsNonConstThis = expr(anyOf(cxxMemberCallExpr(callee(NonConstMethod), on(equalsNode(Exp))), cxxOperatorCallExpr(callee(NonConstMethod), - hasArgument(0, equalsNode(Exp); + hasArgument(0, equalsNode(Exp))), + callExpr(callee(expr(anyOf( + unresolvedMemberExpr(hasObjectExpression(equalsNode(Exp))), + cxxDependentScopeMemberExpr( + hasObjectExpression(equalsNode(Exp); // Taking address of 'Exp'. // We're assuming 'Exp' is mutated as soon as its address is taken, though in @@ -165,10 +170,16 @@ const Stmt *ExprMutationAnalyzer::findDi unless(hasParent(arraySubscriptExpr())), has(equalsNode(Exp))); // Used as non-const-ref argument when calling a function. + // An argument is assumed to be non-const-ref when the function is unresolved. const auto NonConstRefParam = forEachArgumentWithParam( equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType(; - const auto AsNonConstRefArg = - anyOf(callExpr(NonConstRefParam), cxxConstructExpr(NonConstRefParam)); + const auto AsNonConstRefArg = anyOf( + callExpr(NonConstRefParam), cxxConstructExpr(NonConstRefParam), + callExpr(callee(expr(anyOf(unresolvedLookupExpr(), unresolvedMemberExpr(), + cxxDependentScopeMemberExpr(), + hasType(templateTypeParmType(), + hasAnyArgument(equalsNode(Exp))), + cxxUnresolvedConstructExpr(hasAnyArgument(equalsNode(Exp; // Captured by a lambda by reference. // If we're initializing a capture with 'Exp' directly then we're initializing @@ -195,9 +206,12 @@ const Stmt *ExprMutationAnalyzer::findDi const Stmt *ExprMutationAnalyzer::findMemberMutation(const Expr *Exp) { // Check whether any member of 'Exp' is mutated. - const auto MemberExprs = match( - findAll(memberExpr(hasObjectExpression(equalsNode(Exp))).bind("expr")), - *Stm, *Context); + const auto MemberExprs = + match(findAll(expr(anyOf(memberExpr(hasObjectExpression(equalsNode(Exp))), + cxxDependentScopeMemberExpr( + hasObjectExpression(equalsNode(Exp) +.bind("expr")), +*Stm, *Context); return findExprMutation(MemberExprs); } Modified: clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp?rev=341848=341847=341848=diff == --- clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp (original) +++ clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Mon Sep 10 11:05:13 2018 @@ -114,6 +114,26 @@ TEST(ExprMutationAnalyzerTest, NonConstM EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); } +TEST(ExprMutationAnalyzerTest, AssumedNonConstMemberFunc) { + auto AST = tooling::buildASTFromCode( + "struct X { template void mf(); };" + "template void f() { X x; x.mf(); }"); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); + + AST = + tooling::buildASTFromCode("template void f() { T x; x.mf(); }"); +
r340547 - [ASTMatchers] Let hasObjectExpression also support UnresolvedMemberExpr, CXXDependentScopeMemberExpr
Author: shuaiwang Date: Thu Aug 23 10:16:06 2018 New Revision: 340547 URL: http://llvm.org/viewvc/llvm-project?rev=340547=rev Log: [ASTMatchers] Let hasObjectExpression also support UnresolvedMemberExpr, CXXDependentScopeMemberExpr Reviewers: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D50617 Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=340547=340546=340547=diff == --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Thu Aug 23 10:16:06 2018 @@ -4668,6 +4668,20 @@ with withInitializer matching (1) +Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html;>CXXDependentScopeMemberExprhasObjectExpressionMatcherhttp://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr InnerMatcher +Matches a member expression where the object expression is +matched by a given matcher. + +Given + struct X { int m; }; + void f(X x) { x.m; m; } +memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))) + matches "x.m" and "m" +with hasObjectExpression(...) + matching "x" and the implicit object expression of "m" which has type X*. + + + Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html;>CXXForRangeStmthasBodyMatcherhttp://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>Stmt InnerMatcher Matches a 'for', 'while', 'do while' statement or a function definition that has a given body. @@ -6692,6 +6706,20 @@ Example matches true (matcher = hasUnary +Matcherhttp://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html;>UnresolvedMemberExprhasObjectExpressionMatcherhttp://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr InnerMatcher +Matches a member expression where the object expression is +matched by a given matcher. + +Given + struct X { int m; }; + void f(X x) { x.m; m; } +memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))) + matches "x.m" and "m" +with hasObjectExpression(...) + matching "x" and the implicit object expression of "m" which has type X*. + + + Matcherhttp://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html;>UnresolvedUsingTypehasDeclarationconst Matcherhttp://clang.llvm.org/doxygen/classclang_1_1Decl.html;>Decl InnerMatcher Matches a node if the declaration associated with that node matches the given matcher. Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=340547=340546=340547=diff == --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Thu Aug 23 10:16:06 2018 @@ -4825,8 +4825,17 @@ AST_MATCHER_P(MemberExpr, member, /// matches "x.m" and "m" /// with hasObjectExpression(...) /// matching "x" and the implicit object expression of "m" which has type X*. -AST_MATCHER_P(MemberExpr, hasObjectExpression, - internal::Matcher, InnerMatcher) { +AST_POLYMORPHIC_MATCHER_P( +hasObjectExpression, +AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr, +CXXDependentScopeMemberExpr), +internal::Matcher, InnerMatcher) { + if (const auto *E = dyn_cast()) +if (E->isImplicitAccess()) + return false; + if (const auto *E = dyn_cast()) +if (E->isImplicitAccess()) + return false; return InnerMatcher.matches(*Node.getBase(), Finder, Builder); } Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp?rev=340547=340546=340547=diff == --- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Thu Aug 23 10:16:06 2018 @@ -1517,6 +1517,26 @@ TEST(HasObjectExpression, MatchesBaseOfV "struct X { int m; }; void f(X* x) { x->m; }", memberExpr(hasObjectExpression( hasType(pointsTo(recordDecl(hasName("X"; + EXPECT_TRUE(matches("template struct X { void f() { T t; t.m; } };", + cxxDependentScopeMemberExpr(hasObjectExpression( + declRefExpr(to(namedDecl(hasName("t"; + EXPECT_TRUE( + matches("template struct X { void f() { T t; t->m; } };", + cxxDependentScopeMemberExpr(hasObjectExpression( +
r339530 - [ASTMatchers] Let hasAnyArgument also support CXXUnresolvedConstructExpr
Author: shuaiwang Date: Sun Aug 12 16:30:05 2018 New Revision: 339530 URL: http://llvm.org/viewvc/llvm-project?rev=339530=rev Log: [ASTMatchers] Let hasAnyArgument also support CXXUnresolvedConstructExpr Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D50605 Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/AST/ExprCXX.h cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=339530=339529=339530=diff == --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Sun Aug 12 16:30:05 2018 @@ -4854,6 +4854,25 @@ match Base. +Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html;>CXXUnresolvedConstructExprhasAnyArgumentMatcherhttp://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr InnerMatcher +Matches any argument of a call expression or a constructor call +expression, or an ObjC-message-send expression. + +Given + void x(int, int, int) { int y; x(1, y, 42); } +callExpr(hasAnyArgument(declRefExpr())) + matches x(1, y, 42) +with hasAnyArgument(...) + matching y + +For ObjectiveC, given + @interface I - (void) f:(int) y; @end + void foo(I *i) { [i f:12]; } +objcMessageExpr(hasAnyArgument(integerLiteral(equals(12 + matches [i f:12] + + + Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CallExpr.html;>CallExprcalleeMatcherhttp://clang.llvm.org/doxygen/classclang_1_1Decl.html;>Decl InnerMatcher Matches if the call expression's callee's declaration matches the given matcher. @@ -5938,8 +5957,8 @@ nestedNameSpecifier(specifiesType( -Matcherhttp://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html;>ObjCMessageExprhasAnyArgumentMatcherhttp://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr InnerMatcher -Matches any argument of a call expression or a constructor call +Matcherhttp://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html;>ObjCMessageExprhasAnyArgumentMatcherhttp://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr InnerMatcher +Matches any argument of a call expression or a constructor call expression, or an ObjC-message-send expression. Given Modified: cfe/trunk/include/clang/AST/ExprCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=339530=339529=339530=diff == --- cfe/trunk/include/clang/AST/ExprCXX.h (original) +++ cfe/trunk/include/clang/AST/ExprCXX.h Sun Aug 12 16:30:05 2018 @@ -3426,16 +3426,22 @@ public: unsigned arg_size() const { return NumArgs; } using arg_iterator = Expr **; + using arg_range = llvm::iterator_range; arg_iterator arg_begin() { return getTrailingObjects(); } arg_iterator arg_end() { return arg_begin() + NumArgs; } + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } using const_arg_iterator = const Expr* const *; + using const_arg_range = llvm::iterator_range; const_arg_iterator arg_begin() const { return getTrailingObjects(); } const_arg_iterator arg_end() const { return arg_begin() + NumArgs; } + const_arg_range arguments() const { +return const_arg_range(arg_begin(), arg_end()); + } Expr *getArg(unsigned I) { assert(I < NumArgs && "Argument index out-of-range"); Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=339530=339529=339530=diff == --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Sun Aug 12 16:30:05 2018 @@ -3565,9 +3565,9 @@ AST_MATCHER(CXXCtorInitializer, isMember /// objcMessageExpr(hasAnyArgument(integerLiteral(equals(12 /// matches [i f:12] AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, - AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr, - CXXConstructExpr, - ObjCMessageExpr), + AST_POLYMORPHIC_SUPPORTED_TYPES( + CallExpr, CXXConstructExpr, + CXXUnresolvedConstructExpr, ObjCMessageExpr), internal::Matcher, InnerMatcher) { for (const Expr *Arg : Node.arguments()) { BoundNodesTreeBuilder Result(*Builder); Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp?rev=339530=339529=339530=diff
r339522 - [ASTMatchers] Add matchers unresolvedMemberExpr, cxxDependentScopeMemberExpr
Author: shuaiwang Date: Sun Aug 12 10:34:36 2018 New Revision: 339522 URL: http://llvm.org/viewvc/llvm-project?rev=339522=rev Log: [ASTMatchers] Add matchers unresolvedMemberExpr, cxxDependentScopeMemberExpr Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D50606 Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp cfe/trunk/unittests/AST/ASTImporterTest.cpp cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=339522=339521=339522=diff == --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Sun Aug 12 10:34:36 2018 @@ -866,6 +866,17 @@ cxxDeleteExpr() +Matcherhttp://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtcxxDependentScopeMemberExprMatcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html;>CXXDependentScopeMemberExpr... +Matches member expressions where the actual member referenced could not be +resolved because the base expression or the member name was dependent. + +Given + template class T void f() { T t; t.g(); } +cxxDependentScopeMemberExpr() + matches t.g + + + Matcherhttp://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtcxxDynamicCastExprMatcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXDynamicCastExpr.html;>CXXDynamicCastExpr... Matches a dynamic_cast expression. @@ -1455,6 +1466,20 @@ unresolvedLookupExpr() matches fooT() +Matcherhttp://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtunresolvedMemberExprMatcherhttp://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html;>UnresolvedMemberExpr... +Matches unresolved member expressions. + +Given + struct X { +template class T void f(); +void g(); + }; + template class T void h() { X x; x.fT(); x.g(); } +unresolvedMemberExpr() + matches x.fT + + + Matcherhttp://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtuserDefinedLiteralMatcherhttp://clang.llvm.org/doxygen/classclang_1_1UserDefinedLiteral.html;>UserDefinedLiteral... Matches user defined literal operator call. @@ -1598,7 +1623,7 @@ Given: short i = 1; int j = 42; decltype(i + j) result = i + j; -decltypeType() +decltypeType() matches "decltype(i + j)" Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=339522=339521=339522=diff == --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Sun Aug 12 10:34:36 2018 @@ -1141,6 +1141,34 @@ extern const internal::VariadicDynCastAl /// matches this->x, x, y.x, a, this->b extern const internal::VariadicDynCastAllOfMatcher memberExpr; +/// Matches unresolved member expressions. +/// +/// Given +/// \code +/// struct X { +/// template void f(); +/// void g(); +/// }; +/// template void h() { X x; x.f(); x.g(); } +/// \endcode +/// unresolvedMemberExpr() +/// matches x.f +extern const internal::VariadicDynCastAllOfMatcher +unresolvedMemberExpr; + +/// Matches member expressions where the actual member referenced could not be +/// resolved because the base expression or the member name was dependent. +/// +/// Given +/// \code +/// template void f() { T t; t.g(); } +/// \endcode +/// cxxDependentScopeMemberExpr() +/// matches t.g +extern const internal::VariadicDynCastAllOfMatcher +cxxDependentScopeMemberExpr; + /// Matches call expressions. /// /// Example matches x.y() and y() Modified: cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp?rev=339522=339521=339522=diff == --- cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp (original) +++ cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp Sun Aug 12 10:34:36 2018 @@ -610,6 +610,10 @@ const internal::VariadicDynCastAllOfMatc const internal::VariadicAllOfMatcher stmt; const internal::VariadicDynCastAllOfMatcher declStmt; const internal::VariadicDynCastAllOfMatcher memberExpr; +const internal::VariadicDynCastAllOfMatcher +unresolvedMemberExpr; +const internal::VariadicDynCastAllOfMatcher +cxxDependentScopeMemberExpr; const internal::VariadicDynCastAllOfMatcher callExpr; const internal::VariadicDynCastAllOfMatcher lambdaExpr; const internal::VariadicDynCastAllOfMatcher Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp URL:
[clang-tools-extra] r338903 - Use ExprMutationAnalyzer in performance-unnecessary-value-param
Author: shuaiwang Date: Fri Aug 3 10:23:37 2018 New Revision: 338903 URL: http://llvm.org/viewvc/llvm-project?rev=338903=rev Log: Use ExprMutationAnalyzer in performance-unnecessary-value-param Summary: This yields better recall as ExprMutationAnalyzer is more accurate. One common pattern this check is now able to catch is: ``` void foo(std::vector v) { for (const auto& elm : v) { // ... } } ``` Reviewers: george.karpenkov Subscribers: a.sidorin, cfe-commits Differential Revision: https://reviews.llvm.org/D50102 Modified: clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp Modified: clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp?rev=338903=338902=338903=diff == --- clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp Fri Aug 3 10:23:37 2018 @@ -10,6 +10,7 @@ #include "UnnecessaryValueParamCheck.h" #include "../utils/DeclRefExprUtils.h" +#include "../utils/ExprMutationAnalyzer.h" #include "../utils/FixItHintUtils.h" #include "../utils/Matchers.h" #include "../utils/TypeTraits.h" @@ -31,14 +32,6 @@ std::string paramNameOrIndex(StringRef N .str(); } -template -bool isSubset(const S , const S ) { - for (const auto : SubsetCandidate) -if (SupersetCandidate.count(E) == 0) - return false; - return true; -} - bool isReferencedOutsideOfCallExpr(const FunctionDecl , ASTContext ) { auto Matches = match(declRefExpr(to(functionDecl(equalsNode())), @@ -98,43 +91,55 @@ void UnnecessaryValueParamCheck::registe void UnnecessaryValueParamCheck::check(const MatchFinder::MatchResult ) { const auto *Param = Result.Nodes.getNodeAs("param"); const auto *Function = Result.Nodes.getNodeAs("functionDecl"); - const size_t Index = std::find(Function->parameters().begin(), - Function->parameters().end(), Param) - - Function->parameters().begin(); - bool IsConstQualified = - Param->getType().getCanonicalType().isConstQualified(); - auto AllDeclRefExprs = utils::decl_ref_expr::allDeclRefExprs( - *Param, *Function, *Result.Context); - auto ConstDeclRefExprs = utils::decl_ref_expr::constReferenceDeclRefExprs( - *Param, *Function, *Result.Context); - - // Do not trigger on non-const value parameters when they are not only used as - // const. - if (!isSubset(AllDeclRefExprs, ConstDeclRefExprs)) + // Do not trigger on non-const value parameters when they are mutated either + // within the function body or within init expression(s) when the function is + // a ctor. + if (utils::ExprMutationAnalyzer(Function->getBody(), Result.Context) + .isMutated(Param)) return; + // CXXCtorInitializer might also mutate Param but they're not part of function + // body, so check them separately here. + if (const auto *Ctor = dyn_cast(Function)) { +for (const auto *Init : Ctor->inits()) { + if (utils::ExprMutationAnalyzer(Init->getInit(), Result.Context) + .isMutated(Param)) +return; +} + } + + const bool IsConstQualified = + Param->getType().getCanonicalType().isConstQualified(); // If the parameter is non-const, check if it has a move constructor and is // only referenced once to copy-construct another object or whether it has a // move assignment operator and is only referenced once when copy-assigned. // In this case wrap DeclRefExpr with std::move() to avoid the unnecessary // copy. - if (!IsConstQualified && AllDeclRefExprs.size() == 1) { -auto CanonicalType = Param->getType().getCanonicalType(); -const auto = **AllDeclRefExprs.begin(); - -if (!hasLoopStmtAncestor(DeclRefExpr, *Function, *Result.Context) && -((utils::type_traits::hasNonTrivialMoveConstructor(CanonicalType) && - utils::decl_ref_expr::isCopyConstructorArgument( - DeclRefExpr, *Function, *Result.Context)) || - (utils::type_traits::hasNonTrivialMoveAssignment(CanonicalType) && - utils::decl_ref_expr::isCopyAssignmentArgument( - DeclRefExpr, *Function, *Result.Context { - handleMoveFix(*Param, DeclRefExpr, *Result.Context); - return; + if (!IsConstQualified) { +auto AllDeclRefExprs = utils::decl_ref_expr::allDeclRefExprs( +*Param, *Function, *Result.Context); +if (AllDeclRefExprs.size() == 1) { + auto CanonicalType = Param->getType().getCanonicalType(); + const auto = **AllDeclRefExprs.begin(); + + if (!hasLoopStmtAncestor(DeclRefExpr, *Function, *Result.Context)
[clang-tools-extra] r336737 - Use ExprMutationAnalyzer in performance-for-range-copy
Author: shuaiwang Date: Tue Jul 10 15:51:06 2018 New Revision: 336737 URL: http://llvm.org/viewvc/llvm-project?rev=336737=rev Log: Use ExprMutationAnalyzer in performance-for-range-copy Summary: This gives better coverage to the check as ExprMutationAnalyzer is more accurate comparing to isOnlyUsedAsConst. Majority of wins come from const usage of member field, e.g.: for (auto widget : container) { // copy of loop variable if (widget.type == BUTTON) { // const usage only recognized by ExprMutationAnalyzer // ... } } Reviewers: george.karpenkov Subscribers: a.sidorin, cfe-commits Differential Revision: https://reviews.llvm.org/D48854 Modified: clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp Modified: clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp?rev=336737=336736=336737=diff == --- clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp Tue Jul 10 15:51:06 2018 @@ -8,7 +8,7 @@ //===--===// #include "ForRangeCopyCheck.h" -#include "../utils/DeclRefExprUtils.h" +#include "../utils/ExprMutationAnalyzer.h" #include "../utils/FixItHintUtils.h" #include "../utils/TypeTraits.h" @@ -79,8 +79,8 @@ bool ForRangeCopyCheck::handleCopyIsOnly utils::type_traits::isExpensiveToCopy(LoopVar.getType(), Context); if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive) return false; - if (!utils::decl_ref_expr::isOnlyUsedAsConst(LoopVar, *ForRange.getBody(), - Context)) + if (utils::ExprMutationAnalyzer(ForRange.getBody(), ) + .isMutated()) return false; diag(LoopVar.getLocation(), "loop variable is copied but only used as const reference; consider " Modified: clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp?rev=336737=336736=336737=diff == --- clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp (original) +++ clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp Tue Jul 10 15:51:06 2018 @@ -117,6 +117,11 @@ struct Mutable { ~Mutable() {} }; +struct Point { + ~Point() {} + int x, y; +}; + Mutable& operator<<(Mutable , bool B) { Out.setBool(B); return Out; @@ -214,6 +219,15 @@ void positiveOnlyUsedAsConstArguments() } } +void positiveOnlyAccessedFieldAsConst() { + for (auto UsedAsConst : View>()) { +// CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy] +// CHECK-FIXES: for (const auto& UsedAsConst : View>()) { +use(UsedAsConst.x); +use(UsedAsConst.y); + } +} + void positiveOnlyUsedInCopyConstructor() { for (auto A : View>()) { // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy] ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D17586: Add a new check, readability-redundant-string-init, that checks unnecessary string initializations.
shuaiwang marked an inline comment as done. shuaiwang added a comment. http://reviews.llvm.org/D17586 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D17586: Add a new check, readability-redundant-string-init, that checks unnecessary string initializations.
shuaiwang updated this revision to Diff 49114. shuaiwang added a comment. CHECK-FIXES for macro tests http://reviews.llvm.org/D17586 Files: clang-tidy/ClangTidyDiagnosticConsumer.cpp clang-tidy/ClangTidyDiagnosticConsumer.h clang-tidy/readability/CMakeLists.txt clang-tidy/readability/ReadabilityTidyModule.cpp clang-tidy/readability/RedundantStringInitCheck.cpp clang-tidy/readability/RedundantStringInitCheck.h docs/clang-tidy/checks/list.rst docs/clang-tidy/checks/readability-redundant-string-init.rst test/clang-tidy/readability-redundant-string-init.cpp Index: test/clang-tidy/readability-redundant-string-init.cpp === --- /dev/null +++ test/clang-tidy/readability-redundant-string-init.cpp @@ -0,0 +1,86 @@ +// RUN: %check_clang_tidy %s readability-redundant-string-init %t + +namespace std { +template +class allocator {}; +template +class char_traits {}; +template , typename A = std::allocator> +struct basic_string { + basic_string(); + basic_string(const basic_string&); + basic_string(const C *, const A = A()); + ~basic_string(); +}; +typedef basic_string string; +typedef basic_string wstring; +} + +void f() { + std::string a = ""; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization [readability-redundant-string-init] + // CHECK-FIXES: std::string a; + std::string b(""); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string b; + std::string c = R"()"; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string c; + std::string d(R"()"); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string d; + + std::string u = "u"; + std::string w("w"); + std::string x = R"(x)"; + std::string y(R"(y)"); + std::string z; +} + +void g() { + std::wstring a = L""; + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring a; + std::wstring b(L""); + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring b; + std::wstring c = LR"()"; + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring c; + std::wstring d(LR"()"); + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring d; + + std::wstring u = L"u"; + std::wstring w(L"w"); + std::wstring x = LR"(x)"; + std::wstring y(LR"(y)"); + std::wstring z; +} + +template +void templ() { + std::string s = ""; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string s; +} + +#define M(x) x +#define N { std::string s = ""; } +// CHECK-FIXES: #define N { std::string s = ""; } + +void h() { + templ(); + templ(); + + M({ std::string s = ""; }) + // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization + // CHECK-FIXES: M({ std::string s; }) + + N + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant string initialization + // CHECK-FIXES: N + N + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant string initialization + // CHECK-FIXES: N +} Index: docs/clang-tidy/checks/readability-redundant-string-init.rst === --- /dev/null +++ docs/clang-tidy/checks/readability-redundant-string-init.rst @@ -0,0 +1,16 @@ +.. title:: clang-tidy - readability-redundant-string-init + +readability-redundant-string-init += + + +Finds unnecessary string initializations. + +Examples: + +.. code:: c++ + + // Initializing string with empty string literal is unnecessary. + std::string a = ""; + std::string b(""); + Index: docs/clang-tidy/checks/list.rst === --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -99,5 +99,6 @@ readability-redundant-control-flow readability-redundant-smartptr-get readability-redundant-string-cstr + readability-redundant-string-init readability-simplify-boolean-expr readability-uniqueptr-delete-release Index: clang-tidy/readability/RedundantStringInitCheck.h === --- /dev/null +++ clang-tidy/readability/RedundantStringInitCheck.h @@ -0,0 +1,32 @@ +//===- RedundantStringInitCheck.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_REDUNDANT_STRING_INIT_H +#define
Re: [PATCH] D17586: Add a new check, readability-redundant-string-init, that checks unnecessary string initializations.
shuaiwang updated this revision to Diff 49108. shuaiwang added a comment. more test cases http://reviews.llvm.org/D17586 Files: clang-tidy/ClangTidyDiagnosticConsumer.cpp clang-tidy/ClangTidyDiagnosticConsumer.h clang-tidy/readability/CMakeLists.txt clang-tidy/readability/ReadabilityTidyModule.cpp clang-tidy/readability/RedundantStringInitCheck.cpp clang-tidy/readability/RedundantStringInitCheck.h docs/clang-tidy/checks/list.rst docs/clang-tidy/checks/readability-redundant-string-init.rst test/clang-tidy/readability-redundant-string-init.cpp Index: test/clang-tidy/readability-redundant-string-init.cpp === --- /dev/null +++ test/clang-tidy/readability-redundant-string-init.cpp @@ -0,0 +1,83 @@ +// RUN: %check_clang_tidy %s readability-redundant-string-init %t + +namespace std { +template +class allocator {}; +template +class char_traits {}; +template , typename A = std::allocator> +struct basic_string { + basic_string(); + basic_string(const basic_string&); + basic_string(const C *, const A = A()); + ~basic_string(); +}; +typedef basic_string string; +typedef basic_string wstring; +} + +void f() { + std::string a = ""; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization [readability-redundant-string-init] + // CHECK-FIXES: std::string a; + std::string b(""); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string b; + std::string c = R"()"; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string c; + std::string d(R"()"); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string d; + + std::string u = "u"; + std::string w("w"); + std::string x = R"(x)"; + std::string y(R"(y)"); + std::string z; +} + +void g() { + std::wstring a = L""; + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring a; + std::wstring b(L""); + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring b; + std::wstring c = LR"()"; + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring c; + std::wstring d(LR"()"); + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization + // CHECK-FIXES: std::wstring d; + + std::wstring u = L"u"; + std::wstring w(L"w"); + std::wstring x = LR"(x)"; + std::wstring y(LR"(y)"); + std::wstring z; +} + +template +void templ() { + std::string s = ""; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization + // CHECK-FIXES: std::string s; +} + +#define M(x) x +#define N { std::string s = ""; } + +void h() { + templ(); + templ(); + + M({ std::string s = ""; }) + // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization + // CHECK-FIXES: M({ std::string s; }) + + N + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant string initialization + N + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant string initialization +} Index: docs/clang-tidy/checks/readability-redundant-string-init.rst === --- /dev/null +++ docs/clang-tidy/checks/readability-redundant-string-init.rst @@ -0,0 +1,16 @@ +.. title:: clang-tidy - readability-redundant-string-init + +readability-redundant-string-init += + + +Finds unnecessary string initializations. + +Examples: + +.. code:: c++ + + // Initializing string with empty string literal is unnecessary. + std::string a = ""; + std::string b(""); + Index: docs/clang-tidy/checks/list.rst === --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -99,5 +99,6 @@ readability-redundant-control-flow readability-redundant-smartptr-get readability-redundant-string-cstr + readability-redundant-string-init readability-simplify-boolean-expr readability-uniqueptr-delete-release Index: clang-tidy/readability/RedundantStringInitCheck.h === --- /dev/null +++ clang-tidy/readability/RedundantStringInitCheck.h @@ -0,0 +1,32 @@ +//===- RedundantStringInitCheck.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_REDUNDANT_STRING_INIT_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_STRING_INIT_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace