OikawaKirie created this revision. OikawaKirie added reviewers: gamesh411, martong, hgabii. OikawaKirie added a project: clang. Herald added subscribers: steakhal, ASDenysPetrov, dkrupp, donat.nagy, Szelethus, arphaman, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun. OikawaKirie requested review of this revision. Herald added a subscriber: cfe-commits.
This error was found when analyzing MySQL with CTU enabled. When there are space characters in the lookup name, the current delimiter searching strategy will make the file path wrongly parsed. And when two lookup names have the same prefix before their first space characters, a 'multiple definitions' error will be wrongly reported. e.g. The lookup names for the two lambda exprs in the test case are `c:@S@G@F@G#@Sa@F@operator int (*)(char)#1` and `c:@S@G@F@G#@Sa@F@operator bool (*)(char)#1` respectively. And their prefixes are both `c:@S@G@F@G#@Sa@F@operator` when using the first space character as the delimiter. This patch solves the problem by replacing `find` with `rfind` for the delimiter, as the chance of file paths having space characters seems to be far less than the lookup name. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D102669 Files: clang/lib/CrossTU/CrossTranslationUnit.cpp clang/test/Analysis/Inputs/ctu-lookup-name-with-space.cpp clang/test/Analysis/ctu-lookup-name-with-space.cpp Index: clang/test/Analysis/ctu-lookup-name-with-space.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/ctu-lookup-name-with-space.cpp @@ -0,0 +1,29 @@ +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: cp %s %t/trigger.cpp +// RUN: cp %S/Inputs/ctu-lookup-name-with-space.cpp %t/importee.cpp +// RUN: echo '"%t/importee.cpp" : ["g++", "-c", "%t/importee.cpp"]' > %t/invocations.yaml +// RUN: echo '[{"directory": "%t", "command": "g++ -c %t/importee.cpp", "file": "%t/importee.cpp"}, {"directory": "%t", "command": "g++ -c %t/trigger.cpp", "file": "%t/trigger.cpp"}]' > %t/compile_commands.json + +// RUN: %clang_extdef_map -p %t %t/importee.cpp > %t/externalDefMap.txt + +// RUN: cd %t && %clang_cc1 -fsyntax-only -analyze \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=. \ +// RUN: -analyzer-config ctu-invocation-list=invocations.yaml \ +// RUN: trigger.cpp 2>&1 | FileCheck importee.cpp + +// RUN: cd %t && %clang_cc1 -fsyntax-only -analyze \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=. \ +// RUN: -analyzer-config ctu-invocation-list=invocations.yaml \ +// RUN: -verify trigger.cpp + +int importee(int); + +void trigger() { + importee(0); // expected-warn...@importee.cpp:13 {{Division by zero}} +} Index: clang/test/Analysis/Inputs/ctu-lookup-name-with-space.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/Inputs/ctu-lookup-name-with-space.cpp @@ -0,0 +1,14 @@ +void f(int (*)(char)); +void f(bool (*)(char)); + +struct G { + G() { + // CHECK-NOT: error: multiple definitions are found for the same key in index + f([](char) -> int { return 42; }); + f([](char) -> bool { return true; }); + } +}; + +int importee(int X) { + return 1 / X; +} Index: clang/lib/CrossTU/CrossTranslationUnit.cpp =================================================================== --- clang/lib/CrossTU/CrossTranslationUnit.cpp +++ clang/lib/CrossTU/CrossTranslationUnit.cpp @@ -157,7 +157,7 @@ unsigned LineNo = 1; while (std::getline(ExternalMapFile, Line)) { StringRef LineRef{Line}; - const size_t Delimiter = LineRef.find(' '); + const size_t Delimiter = LineRef.rfind(' '); if (Delimiter > 0 && Delimiter != std::string::npos) { StringRef LookupName = LineRef.substr(0, Delimiter);
Index: clang/test/Analysis/ctu-lookup-name-with-space.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/ctu-lookup-name-with-space.cpp @@ -0,0 +1,29 @@ +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: cp %s %t/trigger.cpp +// RUN: cp %S/Inputs/ctu-lookup-name-with-space.cpp %t/importee.cpp +// RUN: echo '"%t/importee.cpp" : ["g++", "-c", "%t/importee.cpp"]' > %t/invocations.yaml +// RUN: echo '[{"directory": "%t", "command": "g++ -c %t/importee.cpp", "file": "%t/importee.cpp"}, {"directory": "%t", "command": "g++ -c %t/trigger.cpp", "file": "%t/trigger.cpp"}]' > %t/compile_commands.json + +// RUN: %clang_extdef_map -p %t %t/importee.cpp > %t/externalDefMap.txt + +// RUN: cd %t && %clang_cc1 -fsyntax-only -analyze \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=. \ +// RUN: -analyzer-config ctu-invocation-list=invocations.yaml \ +// RUN: trigger.cpp 2>&1 | FileCheck importee.cpp + +// RUN: cd %t && %clang_cc1 -fsyntax-only -analyze \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=. \ +// RUN: -analyzer-config ctu-invocation-list=invocations.yaml \ +// RUN: -verify trigger.cpp + +int importee(int); + +void trigger() { + importee(0); // expected-warn...@importee.cpp:13 {{Division by zero}} +} Index: clang/test/Analysis/Inputs/ctu-lookup-name-with-space.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/Inputs/ctu-lookup-name-with-space.cpp @@ -0,0 +1,14 @@ +void f(int (*)(char)); +void f(bool (*)(char)); + +struct G { + G() { + // CHECK-NOT: error: multiple definitions are found for the same key in index + f([](char) -> int { return 42; }); + f([](char) -> bool { return true; }); + } +}; + +int importee(int X) { + return 1 / X; +} Index: clang/lib/CrossTU/CrossTranslationUnit.cpp =================================================================== --- clang/lib/CrossTU/CrossTranslationUnit.cpp +++ clang/lib/CrossTU/CrossTranslationUnit.cpp @@ -157,7 +157,7 @@ unsigned LineNo = 1; while (std::getline(ExternalMapFile, Line)) { StringRef LineRef{Line}; - const size_t Delimiter = LineRef.find(' '); + const size_t Delimiter = LineRef.rfind(' '); if (Delimiter > 0 && Delimiter != std::string::npos) { StringRef LookupName = LineRef.substr(0, Delimiter);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits