[PATCH] D52076: [CodeComplete] Add completions for filenames in #include directives.
sammccall created this revision. sammccall added a reviewer: ilya-biryukov. Herald added a subscriber: cfe-commits. The dir component ("somedir" in #include ) is considered fixed. We append "foo" to each directory on the include path, and then list its files. Completions are of the forms: ^-text--^^-TT-^ (TypedText) and https://reviews.llvm.org/D51921 will fix. Repository: rC Clang https://reviews.llvm.org/D52076 Files: include/clang-c/Index.h include/clang/Lex/CodeCompletionHandler.h include/clang/Lex/Preprocessor.h include/clang/Parse/Parser.h include/clang/Sema/CodeCompleteConsumer.h include/clang/Sema/Sema.h lib/Frontend/ASTUnit.cpp lib/Lex/Lexer.cpp lib/Lex/Preprocessor.cpp lib/Parse/Parser.cpp lib/Sema/CodeCompleteConsumer.cpp lib/Sema/SemaCodeComplete.cpp test/CodeCompletion/included-files.cpp tools/libclang/CIndexCodeCompletion.cpp Index: tools/libclang/CIndexCodeCompletion.cpp === --- tools/libclang/CIndexCodeCompletion.cpp +++ tools/libclang/CIndexCodeCompletion.cpp @@ -499,6 +499,10 @@ contexts = CXCompletionContext_NaturalLanguage; break; } +case CodeCompletionContext::CCC_IncludedFile: { + contexts = CXCompletionContext_IncludedFile; + break; +} case CodeCompletionContext::CCC_SelectorName: { contexts = CXCompletionContext_ObjCSelectorName; break; Index: test/CodeCompletion/included-files.cpp === --- /dev/null +++ test/CodeCompletion/included-files.cpp @@ -0,0 +1,25 @@ +// RUN: rm -rf %t && mkdir %t && cp %s %t/main.cc && mkdir %t/a +// RUN: touch %t/foo.h && touch %t/foo.cc && touch %t/a/foosys %t/a/foosys.h + +// Quoted string shows header-ish files from CWD, and all from system. +#include "foo.h" +// RUN: %clang -fsyntax-only -isystem %t/a -Xclang -code-completion-at=%t/main.cc:5:13 %t/main.cc | FileCheck -check-prefix=CHECK-1 %s +// CHECK-1-NOT: "foo.cc" +// CHECK-1: "foo.h" +// CHECK-1: "foosys" + +// Quoted string with dir shows header-ish files in that subdir. +#include "a/foosys" +// RUN: %clang -fsyntax-only -isystem %t/a -Xclang -code-completion-at=%t/main.cc:12:13 %t/main.cc | FileCheck -check-prefix=CHECK-2 %s +// CHECK-2-NOT: "a/foosys" +// CHECK-2: "a/foosys.h" +// CHECK-2-NOT: "a/foosys" +// CHECK-2-NOT: "foo.h" +// CHECK-2-NOT: "foosys" + +// Angled string showes all files, but only in system dirs. +#include +// RUN: %clang -fsyntax-only -isystem %t/a -Xclang -code-completion-at=%t/main.cc:21:13 %t/main.cc | FileCheck -check-prefix=CHECK-3 %s +// CHECK-3-NOT: +// CHECK-3-NOT: +// CHECK-3: Index: lib/Sema/SemaCodeComplete.cpp === --- lib/Sema/SemaCodeComplete.cpp +++ lib/Sema/SemaCodeComplete.cpp @@ -32,6 +32,8 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Path.h" #include #include #include @@ -7994,6 +7996,115 @@ // for the expanded tokens. } +// This handles completion inside an #include filename, e.g. #include getAllocator().CopyString( + (Angled ? "<" : "\"") + RelDir + "/"); + SmallString<128> NativeRelDir = RelDir; + llvm::sys::path::native(NativeRelDir); + auto FS = getSourceManager().getFileManager().getVirtualFileSystem(); + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), +CodeCompleter->getCodeCompletionTUInfo(), +CodeCompletionContext::CCC_IncludedFile); + llvm::DenseSet SeenResults; // To deduplicate results. + + // Helper: adds one file or directory completion result. + auto AddCompletion = [&](StringRef Filename, bool IsDirectory) { +SmallString<64> TypedChunk = Filename; +// Directory completion is up to the slash, e.g. ' : '"'); +auto R = SeenResults.insert(TypedChunk); +if (R.second) { // New completion + const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk); + *R.first = InternedTyped; // Avoid dangling StringRef. + CodeCompletionBuilder Builder(CodeCompleter->getAllocator(), +CodeCompleter->getCodeCompletionTUInfo()); + Builder.AddTextChunk(InternedPrefix); + Builder.AddTypedTextChunk(InternedTyped); + // The result is a "Pattern", which is pretty opaque. + // We may want to include the real filename to allow smart ranking. + Results.AddResult(CodeCompletionResult(Builder.TakeString())); +} + }; + + // Helper: scans IncludeDir for nice files, and adds results for each. + auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) { +llvm::SmallString<128> Dir = IncludeDir; +if (!NativeRelDir.empty()) + llvm::sys::path::append(Dir, NativeRelDir); + +std::error_code EC; +unsigned Count = 0
[PATCH] D52047: [clangd] Add a "benchmark" for tracking memory
kbobyrev updated this revision to Diff 165437. kbobyrev added a comment. - Start measuring time in ms - Add Tokens' `Data` size for more precise memory usage estimation (accounts for ~1MB of Static Index in LLVM) https://reviews.llvm.org/D52047 Files: clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp clang-tools-extra/clangd/index/dex/Dex.cpp Index: clang-tools-extra/clangd/index/dex/Dex.cpp === --- clang-tools-extra/clangd/index/dex/Dex.cpp +++ clang-tools-extra/clangd/index/dex/Dex.cpp @@ -232,8 +232,10 @@ Bytes += SymbolQuality.size() * sizeof(float); Bytes += LookupTable.getMemorySize(); Bytes += InvertedIndex.getMemorySize(); - for (const auto &P : InvertedIndex) + for (const auto &P : InvertedIndex) { +Bytes += P.first.Data.size(); Bytes += P.second.size() * sizeof(DocID); + } return Bytes + BackingDataSize; } Index: clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp === --- clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp +++ clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp @@ -66,23 +66,44 @@ return Requests; } +// This is not a *real* benchmark: it shows size of built MemIndex (in bytes). +// Same for the next "benchmark". +// FIXME(kbobyrev): Should this be separated into the BackingMemorySize +// (underlying SymbolSlab size) and Symbol Index (MemIndex/Dex) overhead? +static void MemSize(benchmark::State &State) { + const auto Mem = buildMem(); + for (auto _ : State) +// Divide size of Mem by 1000 so that it will be correctly displayed in the +// benchmark report (possible options for time units are ms, ns and us). +State.SetIterationTime(/*double Seconds=*/Mem->estimateMemoryUsage() / + 1000); +} +BENCHMARK(MemSize)->UseManualTime()->Unit(benchmark::kMillisecond); + +static void DexSize(benchmark::State &State) { + const auto Dex = buildDex(); + for (auto _ : State) +State.SetIterationTime(Dex->estimateMemoryUsage() / 1000); +} +BENCHMARK(DexSize)->UseManualTime()->Unit(benchmark::kMillisecond); + static void MemQueries(benchmark::State &State) { const auto Mem = buildMem(); const auto Requests = extractQueriesFromLogs(); for (auto _ : State) for (const auto &Request : Requests) Mem->fuzzyFind(Request, [](const Symbol &S) {}); } -BENCHMARK(MemQueries); +BENCHMARK(MemQueries)->Unit(benchmark::kMillisecond); static void DexQueries(benchmark::State &State) { const auto Dex = buildDex(); const auto Requests = extractQueriesFromLogs(); for (auto _ : State) for (const auto &Request : Requests) Dex->fuzzyFind(Request, [](const Symbol &S) {}); } -BENCHMARK(DexQueries); +BENCHMARK(DexQueries)->Unit(benchmark::kMillisecond); } // namespace } // namespace clangd Index: clang-tools-extra/clangd/index/dex/Dex.cpp === --- clang-tools-extra/clangd/index/dex/Dex.cpp +++ clang-tools-extra/clangd/index/dex/Dex.cpp @@ -232,8 +232,10 @@ Bytes += SymbolQuality.size() * sizeof(float); Bytes += LookupTable.getMemorySize(); Bytes += InvertedIndex.getMemorySize(); - for (const auto &P : InvertedIndex) + for (const auto &P : InvertedIndex) { +Bytes += P.first.Data.size(); Bytes += P.second.size() * sizeof(DocID); + } return Bytes + BackingDataSize; } Index: clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp === --- clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp +++ clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp @@ -66,23 +66,44 @@ return Requests; } +// This is not a *real* benchmark: it shows size of built MemIndex (in bytes). +// Same for the next "benchmark". +// FIXME(kbobyrev): Should this be separated into the BackingMemorySize +// (underlying SymbolSlab size) and Symbol Index (MemIndex/Dex) overhead? +static void MemSize(benchmark::State &State) { + const auto Mem = buildMem(); + for (auto _ : State) +// Divide size of Mem by 1000 so that it will be correctly displayed in the +// benchmark report (possible options for time units are ms, ns and us). +State.SetIterationTime(/*double Seconds=*/Mem->estimateMemoryUsage() / + 1000); +} +BENCHMARK(MemSize)->UseManualTime()->Unit(benchmark::kMillisecond); + +static void DexSize(benchmark::State &State) { + const auto Dex = buildDex(); + for (auto _ : State) +State.SetIterationTime(Dex->estimateMemoryUsage() / 1000); +} +BENCHMARK(DexSize)->UseManualTime()->Unit(benchmark::kMillisecond); + static void MemQueries(benchmark::State &State) { const auto Mem = buildMem(); const auto Requests = extractQueriesFromLogs(); for (auto _ : State) for (const auto &Request : Requests) Mem->fuzzyFind(Request, [](const Symbol &S) {}); } -BENCHMARK(MemQuer
[PATCH] D52047: [clangd] Add a "benchmark" for tracking memory
kbobyrev updated this revision to Diff 165440. kbobyrev added a comment. Move `vlog` message to the outer `build(...)` function: otherwise `BackingMemorySize` is not set to the correct value and log reports index overhead (instead of the complete index + slab) size. https://reviews.llvm.org/D52047 Files: clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp clang-tools-extra/clangd/index/dex/Dex.cpp clang-tools-extra/clangd/index/dex/Dex.h Index: clang-tools-extra/clangd/index/dex/Dex.h === --- clang-tools-extra/clangd/index/dex/Dex.h +++ clang-tools-extra/clangd/index/dex/Dex.h @@ -21,6 +21,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_DEX_DEX_H #include "Iterator.h" +#include "Logger.h" #include "Token.h" #include "Trigram.h" #include "index/Index.h" @@ -53,6 +54,7 @@ this->Symbols.push_back(&Sym); buildIndex(); } + // Symbols are owned by BackingData, Index takes ownership. template Dex(Range &&Symbols, Payload &&BackingData, size_t BackingDataSize, @@ -68,8 +70,11 @@ build(SymbolSlab Slab, llvm::ArrayRef URISchemes) { // Store Slab size before it is moved. const auto BackingDataSize = Slab.bytes(); -return llvm::make_unique(Slab, std::move(Slab), BackingDataSize, - URISchemes); +auto Index = llvm::make_unique(Slab, std::move(Slab), BackingDataSize, +URISchemes); +vlog("Built Dex with estimated memory usage {0} bytes.", + Index->estimateMemoryUsage()); +return Index; } bool Index: clang-tools-extra/clangd/index/dex/Dex.cpp === --- clang-tools-extra/clangd/index/dex/Dex.cpp +++ clang-tools-extra/clangd/index/dex/Dex.cpp @@ -10,7 +10,6 @@ #include "Dex.h" #include "FileDistance.h" #include "FuzzyMatch.h" -#include "Logger.h" #include "Quality.h" #include "llvm/ADT/StringSet.h" #include @@ -118,9 +117,6 @@ for (const auto &Token : generateSearchTokens(*Sym)) InvertedIndex[Token].push_back(SymbolRank); } - - vlog("Built Dex with estimated memory usage {0} bytes.", - estimateMemoryUsage()); } /// Constructs iterators over tokens extracted from the query and exhausts it @@ -232,8 +228,10 @@ Bytes += SymbolQuality.size() * sizeof(float); Bytes += LookupTable.getMemorySize(); Bytes += InvertedIndex.getMemorySize(); - for (const auto &P : InvertedIndex) + for (const auto &P : InvertedIndex) { +Bytes += P.first.Data.size(); Bytes += P.second.size() * sizeof(DocID); + } return Bytes + BackingDataSize; } Index: clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp === --- clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp +++ clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp @@ -66,23 +66,44 @@ return Requests; } +// This is not a *real* benchmark: it shows size of built MemIndex (in bytes). +// Same for the next "benchmark". +// FIXME(kbobyrev): Should this be separated into the BackingMemorySize +// (underlying SymbolSlab size) and Symbol Index (MemIndex/Dex) overhead? +static void MemSize(benchmark::State &State) { + const auto Mem = buildMem(); + for (auto _ : State) +// Divide size of Mem by 1000 so that it will be correctly displayed in the +// benchmark report (possible options for time units are ms, ns and us). +State.SetIterationTime(/*double Seconds=*/Mem->estimateMemoryUsage() / + 1000); +} +BENCHMARK(MemSize)->UseManualTime()->Unit(benchmark::kMillisecond); + +static void DexSize(benchmark::State &State) { + const auto Dex = buildDex(); + for (auto _ : State) +State.SetIterationTime(Dex->estimateMemoryUsage() / 1000); +} +BENCHMARK(DexSize)->UseManualTime()->Unit(benchmark::kMillisecond); + static void MemQueries(benchmark::State &State) { const auto Mem = buildMem(); const auto Requests = extractQueriesFromLogs(); for (auto _ : State) for (const auto &Request : Requests) Mem->fuzzyFind(Request, [](const Symbol &S) {}); } -BENCHMARK(MemQueries); +BENCHMARK(MemQueries)->Unit(benchmark::kMillisecond); static void DexQueries(benchmark::State &State) { const auto Dex = buildDex(); const auto Requests = extractQueriesFromLogs(); for (auto _ : State) for (const auto &Request : Requests) Dex->fuzzyFind(Request, [](const Symbol &S) {}); } -BENCHMARK(DexQueries); +BENCHMARK(DexQueries)->Unit(benchmark::kMillisecond); } // namespace } // namespace clangd ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52078: [clangd] Store preamble macros in dynamic index.
ioeric created this revision. ioeric added reviewers: ilya-biryukov, sammccall. Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay. Pros: o Loading macros from preamble for every completion is slow (see profile). o Calculating macro USR is also slow (see profile). o Sema can provide a lot of macro completion results (e.g. when filter is empty, 60k for some large TUs!). Cons: o Slight memory increase in dynamic index (~1%). o Some extra work during preamble build (should be fine as preamble build and indexAST is way slower). [profile place holder] Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52078 Files: clangd/ClangdServer.cpp clangd/index/FileIndex.cpp clangd/index/FileIndex.h unittests/clangd/CodeCompleteTests.cpp unittests/clangd/FileIndexTests.cpp unittests/clangd/IndexTests.cpp unittests/clangd/TestTU.cpp Index: unittests/clangd/TestTU.cpp === --- unittests/clangd/TestTU.cpp +++ unittests/clangd/TestTU.cpp @@ -51,7 +51,7 @@ std::unique_ptr TestTU::index() const { auto AST = build(); auto Content = indexAST(AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); return MemIndex::build(std::move(Content.first), std::move(Content.second)); } Index: unittests/clangd/IndexTests.cpp === --- unittests/clangd/IndexTests.cpp +++ unittests/clangd/IndexTests.cpp @@ -244,7 +244,7 @@ Test.Filename = "test.cc"; auto AST = Test.build(); Dyn.update(Test.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); // Build static index for test.cc. Test.HeaderCode = HeaderCode; @@ -254,7 +254,7 @@ // Add stale refs for test.cc. StaticIndex.update(Test.Filename, &StaticAST.getASTContext(), StaticAST.getPreprocessorPtr(), - StaticAST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, StaticAST.getLocalTopLevelDecls()); // Add refs for test2.cc Annotations Test2Code(R"(class $Foo[[Foo]] {};)"); @@ -265,7 +265,7 @@ StaticAST = Test2.build(); StaticIndex.update(Test2.Filename, &StaticAST.getASTContext(), StaticAST.getPreprocessorPtr(), - StaticAST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, StaticAST.getLocalTopLevelDecls()); RefsRequest Request; Request.IDs = {Foo.ID}; Index: unittests/clangd/FileIndexTests.cpp === --- unittests/clangd/FileIndexTests.cpp +++ unittests/clangd/FileIndexTests.cpp @@ -15,6 +15,7 @@ #include "index/FileIndex.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/PCHContainerOperations.h" +#include "clang/Index/IndexSymbol.h" #include "clang/Lex/Preprocessor.h" #include "clang/Tooling/CompilationDatabase.h" #include "gtest/gtest.h" @@ -135,7 +136,8 @@ File.HeaderFilename = (Basename + ".h").str(); File.HeaderCode = Code; auto AST = File.build(); - M.update(File.Filename, &AST.getASTContext(), AST.getPreprocessorPtr()); + M.update(File.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), + /*IndexMacros=*/true); } TEST(FileIndexTest, CustomizedURIScheme) { @@ -333,23 +335,38 @@ Test.Filename = "test.cc"; auto AST = Test.build(); Index.update(Test.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); // Add test2.cc TestTU Test2; Test2.HeaderCode = HeaderCode; Test2.Code = MainCode.code(); Test2.Filename = "test2.cc"; AST = Test2.build(); Index.update(Test2.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); EXPECT_THAT(getRefs(Index, Foo.ID), RefsAre({AllOf(RefRange(MainCode.range("foo")), FileURI("unittest:///test.cc")), AllOf(RefRange(MainCode.range("foo")), FileURI("unittest:///test2.cc"))})); } +TEST(FileIndexTest, CollectMacros) { + FileIndex M; + update(M, "f", "#define MAC 1; class X {};"); + + FuzzyFindRequest Req; + Req.Query = ""; + bool SeenSymbol = false; + M.fuzzyFind(Req, [&](const Symbol &Sym) { +EXPECT_EQ(Sym.Name, "MAC"); +EXPECT_EQ(Sym.SymInfo.Kind, index::SymbolKind::Macro); +SeenSymbol = true; + }); + EXPECT_TRUE(SeenSymbol); +} + } // namespace } // namespace clangd } // namespace clang Index: unittests/clangd/CodeCompleteTests.cpp ===
[PATCH] D52079: [Sema] Do not load macros from preamble when LoadExternal is false.
ioeric created this revision. ioeric added a reviewer: ilya-biryukov. Herald added a subscriber: cfe-commits. Repository: rC Clang https://reviews.llvm.org/D52079 Files: include/clang/Sema/CodeCompleteOptions.h lib/Sema/SemaCodeComplete.cpp Index: lib/Sema/SemaCodeComplete.cpp === --- lib/Sema/SemaCodeComplete.cpp +++ lib/Sema/SemaCodeComplete.cpp @@ -3302,14 +3302,14 @@ } static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, -bool IncludeUndefined, +bool LoadExternal, bool IncludeUndefined, bool TargetTypeIsPointer = false) { typedef CodeCompletionResult Result; Results.EnterNewScope(); - for (Preprocessor::macro_iterator M = PP.macro_begin(), - MEnd = PP.macro_end(); + for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal), +MEnd = PP.macro_end(LoadExternal); M != MEnd; ++M) { auto MD = PP.getMacroDefinition(M->first); if (IncludeUndefined || MD) { @@ -3325,7 +3325,6 @@ } Results.ExitScope(); - } static void AddPrettyFunctionResults(const LangOptions &LangOpts, @@ -3609,7 +3608,7 @@ } if (CodeCompleter->includeMacros()) -AddMacroResults(PP, Results, false); +AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); @@ -3747,7 +3746,8 @@ AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) -AddMacroResults(PP, Results, false, PreferredTypeIsPointer); +AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false, +PreferredTypeIsPointer); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -4370,7 +4370,7 @@ Results.ExitScope(); if (CodeCompleter->includeMacros()) { -AddMacroResults(PP, Results, false); +AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); } HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); @@ -4686,7 +4686,7 @@ AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) -AddMacroResults(PP, Results, false); +AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); @@ -5720,7 +5720,7 @@ CodeCompleter->loadExternal()); if (CodeCompleter->includeMacros()) -AddMacroResults(PP, Results, false); +AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); @@ -5949,10 +5949,9 @@ Results.ExitScope(); if (CodeCompleter->includeMacros()) -AddMacroResults(PP, Results, false); +AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); - } void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, @@ -7965,7 +7964,9 @@ CodeCompletionContext::CCC_PreprocessorExpression); if (!CodeCompleter || CodeCompleter->includeMacros()) -AddMacroResults(PP, Results, true); +AddMacroResults(PP, Results, +CodeCompleter ? CodeCompleter->loadExternal() : false, +true); // defined () Results.EnterNewScope(); @@ -8030,7 +8031,9 @@ } if (!CodeCompleter || CodeCompleter->includeMacros()) -AddMacroResults(PP, Builder, true); +AddMacroResults(PP, Builder, +CodeCompleter ? CodeCompleter->loadExternal() : false, +true); Results.clear(); Results.insert(Results.end(), Index: include/clang/Sema/CodeCompleteOptions.h === --- include/clang/Sema/CodeCompleteOptions.h +++ include/clang/Sema/CodeCompleteOptions.h @@ -36,7 +36,8 @@ unsigned IncludeBriefComments : 1; /// Hint whether to load data from the external AST to provide full results. - /// If false, namespace-level declarations from the preamble may be omitted. + /// If false, namespace-level declarations and macros from the preamble may be + /// omitted. unsigned LoadExternal : 1; /// Include results after corrections (small fix-its), e.g. change '.' to '->' ___ cfe-commits ma
[PATCH] D52078: [clangd] Store preamble macros in dynamic index.
ioeric updated this revision to Diff 165444. ioeric added a comment. - minor cleanup Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52078 Files: clangd/ClangdServer.cpp clangd/index/FileIndex.cpp clangd/index/FileIndex.h unittests/clangd/CodeCompleteTests.cpp unittests/clangd/FileIndexTests.cpp unittests/clangd/IndexTests.cpp unittests/clangd/TestTU.cpp Index: unittests/clangd/TestTU.cpp === --- unittests/clangd/TestTU.cpp +++ unittests/clangd/TestTU.cpp @@ -51,7 +51,7 @@ std::unique_ptr TestTU::index() const { auto AST = build(); auto Content = indexAST(AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); return MemIndex::build(std::move(Content.first), std::move(Content.second)); } Index: unittests/clangd/IndexTests.cpp === --- unittests/clangd/IndexTests.cpp +++ unittests/clangd/IndexTests.cpp @@ -244,7 +244,7 @@ Test.Filename = "test.cc"; auto AST = Test.build(); Dyn.update(Test.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); // Build static index for test.cc. Test.HeaderCode = HeaderCode; @@ -254,7 +254,7 @@ // Add stale refs for test.cc. StaticIndex.update(Test.Filename, &StaticAST.getASTContext(), StaticAST.getPreprocessorPtr(), - StaticAST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, StaticAST.getLocalTopLevelDecls()); // Add refs for test2.cc Annotations Test2Code(R"(class $Foo[[Foo]] {};)"); @@ -265,7 +265,7 @@ StaticAST = Test2.build(); StaticIndex.update(Test2.Filename, &StaticAST.getASTContext(), StaticAST.getPreprocessorPtr(), - StaticAST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, StaticAST.getLocalTopLevelDecls()); RefsRequest Request; Request.IDs = {Foo.ID}; Index: unittests/clangd/FileIndexTests.cpp === --- unittests/clangd/FileIndexTests.cpp +++ unittests/clangd/FileIndexTests.cpp @@ -15,6 +15,7 @@ #include "index/FileIndex.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/PCHContainerOperations.h" +#include "clang/Index/IndexSymbol.h" #include "clang/Lex/Preprocessor.h" #include "clang/Tooling/CompilationDatabase.h" #include "gtest/gtest.h" @@ -135,7 +136,8 @@ File.HeaderFilename = (Basename + ".h").str(); File.HeaderCode = Code; auto AST = File.build(); - M.update(File.Filename, &AST.getASTContext(), AST.getPreprocessorPtr()); + M.update(File.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), + /*IndexMacros=*/true); } TEST(FileIndexTest, CustomizedURIScheme) { @@ -333,23 +335,38 @@ Test.Filename = "test.cc"; auto AST = Test.build(); Index.update(Test.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); // Add test2.cc TestTU Test2; Test2.HeaderCode = HeaderCode; Test2.Code = MainCode.code(); Test2.Filename = "test2.cc"; AST = Test2.build(); Index.update(Test2.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); EXPECT_THAT(getRefs(Index, Foo.ID), RefsAre({AllOf(RefRange(MainCode.range("foo")), FileURI("unittest:///test.cc")), AllOf(RefRange(MainCode.range("foo")), FileURI("unittest:///test2.cc"))})); } +TEST(FileIndexTest, CollectMacros) { + FileIndex M; + update(M, "f", "#define CLANGD 1"); + + FuzzyFindRequest Req; + Req.Query = ""; + bool SeenSymbol = false; + M.fuzzyFind(Req, [&](const Symbol &Sym) { +EXPECT_EQ(Sym.Name, "CLANGD"); +EXPECT_EQ(Sym.SymInfo.Kind, index::SymbolKind::Macro); +SeenSymbol = true; + }); + EXPECT_TRUE(SeenSymbol); +} + } // namespace } // namespace clangd } // namespace clang Index: unittests/clangd/CodeCompleteTests.cpp === --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -223,12 +223,13 @@ void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) { auto Results = completions( R"cpp( - #define MACRO X - int global_var; int global_func(); + // Make sure this is not in preamble. + #define MACRO X + struct GlobalClass {}; struct ClassWithMembers { @@ -276,11 +277,12 @@ void Te
[PATCH] D51921: [VFS] vfs::directory_iterator yields path and file type instead of full Status
bkramer accepted this revision. bkramer added a comment. This revision is now accepted and ready to land. lg Repository: rC Clang https://reviews.llvm.org/D51921 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342211 - gcc is now returning the same output on this example, removing this example
Author: sylvestre Date: Fri Sep 14 01:52:18 2018 New Revision: 342211 URL: http://llvm.org/viewvc/llvm-project?rev=342211&view=rev Log: gcc is now returning the same output on this example, removing this example Modified: cfe/trunk/www/diagnostics.html Modified: cfe/trunk/www/diagnostics.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/diagnostics.html?rev=342211&r1=342210&r2=342211&view=diff == --- cfe/trunk/www/diagnostics.html (original) +++ cfe/trunk/www/diagnostics.html Fri Sep 14 01:52:18 2018 @@ -51,12 +51,6 @@ helps when multiple instances of the sam revisit this more in following examples.) - $ gcc-4.9 -fsyntax-only -Wformat format-strings.c - format-strings.c: In function 'void f()': - format-strings.c:91:16: warning: field precision specifier '.*' expects a matching 'int' argument [-Wformat=] - printf("%.*d"); - ^ - format-strings.c:91:16: warning: format '%d' expects a matching 'int' argument [-Wformat=] $ clang -fsyntax-only format-strings.c format-strings.c:91:13: warning: '.*' specified field precision is missing a matching 'int' argument printf("%.*d"); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342212 - update the doc to compare with gcc 4.9 instead of 4.2
Author: sylvestre Date: Fri Sep 14 01:55:09 2018 New Revision: 342212 URL: http://llvm.org/viewvc/llvm-project?rev=342212&view=rev Log: update the doc to compare with gcc 4.9 instead of 4.2 Modified: cfe/trunk/www/features.html Modified: cfe/trunk/www/features.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/features.html?rev=342212&r1=342211&r2=342212&view=diff == --- cfe/trunk/www/features.html (original) +++ cfe/trunk/www/features.html Fri Sep 14 01:55:09 2018 @@ -95,8 +95,11 @@ and making the wording as clear as possi GCC and Clang diagnostic: - $ gcc-4.2 -fsyntax-only t.c - t.c:7: error: invalid operands to binary + (have 'int' and 'struct A') + $ gcc-4.9 -fsyntax-only t.c + t.c: In function 'int f(int, int)': + t.c:7:39: error: invalid operands to binary + (have 'int' and 'struct A') + return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X); + ^ $ clang -fsyntax-only t.c t.c:7:39: error: invalid operands to binary expression ('int' and 'struct A') return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342213 - [analyzer][UninitializedObjectChecker] Fixed dereferencing
Author: szelethus Date: Fri Sep 14 01:58:21 2018 New Revision: 342213 URL: http://llvm.org/viewvc/llvm-project?rev=342213&view=rev Log: [analyzer][UninitializedObjectChecker] Fixed dereferencing iThis patch aims to fix derefencing, which has been debated for months now. Instead of working with SVals, the function now relies on TypedValueRegion. Differential Revision: https://reviews.llvm.org/D51057 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp cfe/trunk/test/Analysis/objcpp-uninitialized-object.mm Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=342213&r1=342212&r2=342213&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Fri Sep 14 01:58:21 2018 @@ -87,7 +87,7 @@ public: /// Returns with Field's name. This is a helper function to get the correct name /// even if Field is a captured lambda variable. -StringRef getVariableName(const FieldDecl *Field); +std::string getVariableName(const FieldDecl *Field); /// Represents a field chain. A field chain is a vector of fields where the /// first element of the chain is the object under checking (not stored), and @@ -255,7 +255,13 @@ private: /// ease. This also helps ensuring that every special field type is handled /// correctly. inline bool isPrimitiveType(const QualType &T) { - return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType(); + return T->isBuiltinType() || T->isEnumeralType() || + T->isMemberPointerType() || T->isBlockPointerType() || + T->isFunctionType(); +} + +inline bool isDereferencableType(const QualType &T) { + return T->isAnyPointerType() || T->isReferenceType(); } // Template method definitions. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342213&r1=342212&r2=342213&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Fri Sep 14 01:58:21 2018 @@ -252,9 +252,12 @@ bool FindUninitializedFields::isNonUnion !R->getValueType()->isUnionType() && "This method only checks non-union record objects!"); - const RecordDecl *RD = - R->getValueType()->getAs()->getDecl()->getDefinition(); - assert(RD && "Referred record has no definition"); + const RecordDecl *RD = R->getValueType()->getAsRecordDecl()->getDefinition(); + + if (!RD) { +IsAnyFieldInitialized = true; +return true; + } bool ContainsUninitField = false; @@ -292,8 +295,7 @@ bool FindUninitializedFields::isNonUnion continue; } -if (T->isAnyPointerType() || T->isReferenceType() || -T->isBlockPointerType()) { +if (isDereferencableType(T)) { if (isPointerOrReferenceUninit(FR, LocalChain)) ContainsUninitField = true; continue; @@ -487,7 +489,7 @@ static bool willObjectBeAnalyzedLater(co return false; } -StringRef clang::ento::getVariableName(const FieldDecl *Field) { +std::string clang::ento::getVariableName(const FieldDecl *Field) { // If Field is a captured lambda variable, Field->getName() will return with // an empty string. We can however acquire it's name from the lambda's // captures. @@ -496,7 +498,16 @@ StringRef clang::ento::getVariableName(c if (CXXParent && CXXParent->isLambda()) { assert(CXXParent->captures_begin()); auto It = CXXParent->captures_begin() + Field->getFieldIndex(); -return It->getCapturedVar()->getName(); + +if (It->capturesVariable()) + return llvm::Twine("/*captured variable*/" + + It->getCapturedVar()->getName()) + .str(); + +if (It->capturesThis()) + return "/*'this' capture*/"; + +llvm_unreachable("No other capture type is expected!"); } return Field->getName(); Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedP
[PATCH] D51057: [analyzer][UninitializedObjectChecker] Fixed dereferencing
This revision was automatically updated to reflect the committed changes. Closed by commit rL342213: [analyzer][UninitializedObjectChecker] Fixed dereferencing (authored by Szelethus, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D51057?vs=163992&id=165445#toc Repository: rL LLVM https://reviews.llvm.org/D51057 Files: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp cfe/trunk/test/Analysis/objcpp-uninitialized-object.mm Index: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp === --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -252,9 +252,12 @@ !R->getValueType()->isUnionType() && "This method only checks non-union record objects!"); - const RecordDecl *RD = - R->getValueType()->getAs()->getDecl()->getDefinition(); - assert(RD && "Referred record has no definition"); + const RecordDecl *RD = R->getValueType()->getAsRecordDecl()->getDefinition(); + + if (!RD) { +IsAnyFieldInitialized = true; +return true; + } bool ContainsUninitField = false; @@ -292,8 +295,7 @@ continue; } -if (T->isAnyPointerType() || T->isReferenceType() || -T->isBlockPointerType()) { +if (isDereferencableType(T)) { if (isPointerOrReferenceUninit(FR, LocalChain)) ContainsUninitField = true; continue; @@ -487,16 +489,25 @@ return false; } -StringRef clang::ento::getVariableName(const FieldDecl *Field) { +std::string clang::ento::getVariableName(const FieldDecl *Field) { // If Field is a captured lambda variable, Field->getName() will return with // an empty string. We can however acquire it's name from the lambda's // captures. const auto *CXXParent = dyn_cast(Field->getParent()); if (CXXParent && CXXParent->isLambda()) { assert(CXXParent->captures_begin()); auto It = CXXParent->captures_begin() + Field->getFieldIndex(); -return It->getCapturedVar()->getName(); + +if (It->capturesVariable()) + return llvm::Twine("/*captured variable*/" + + It->getCapturedVar()->getName()) + .str(); + +if (It->capturesThis()) + return "/*'this' capture*/"; + +llvm_unreachable("No other capture type is expected!"); } return Field->getName(); Index: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h === --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h @@ -87,7 +87,7 @@ /// Returns with Field's name. This is a helper function to get the correct name /// even if Field is a captured lambda variable. -StringRef getVariableName(const FieldDecl *Field); +std::string getVariableName(const FieldDecl *Field); /// Represents a field chain. A field chain is a vector of fields where the /// first element of the chain is the object under checking (not stored), and @@ -255,7 +255,13 @@ /// ease. This also helps ensuring that every special field type is handled /// correctly. inline bool isPrimitiveType(const QualType &T) { - return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType(); + return T->isBuiltinType() || T->isEnumeralType() || + T->isMemberPointerType() || T->isBlockPointerType() || + T->isFunctionType(); +} + +inline bool isDereferencableType(const QualType &T) { + return T->isAnyPointerType() || T->isReferenceType(); } // Template method definitions. Index: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp === --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp @@ -95,11 +95,13 @@ /// known, and thus FD can not be analyzed. static bool isVoidPointer(QualType T); -/// Dereferences \p V and returns the value and dynamic type of the pointee, as -/// well as whether \p FR needs to be casted back to that type. If for whatever -/// reason dereferencing fails, returns with None. -static llvm::Optional> -dereference(ProgramStateRef State, const FieldRegion *FR); +using DereferenceInfo = std::pair; + +/// Dereferences \p FR and returns with the pointee's region
r342214 - remove 11 years old videos from the homepage. if you have a suggestion, please drop me an email
Author: sylvestre Date: Fri Sep 14 02:00:48 2018 New Revision: 342214 URL: http://llvm.org/viewvc/llvm-project?rev=342214&view=rev Log: remove 11 years old videos from the homepage. if you have a suggestion, please drop me an email Modified: cfe/trunk/www/index.html Modified: cfe/trunk/www/index.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/index.html?rev=342214&r1=342213&r2=342214&view=diff == --- cfe/trunk/www/index.html (original) +++ cfe/trunk/www/index.html Fri Sep 14 02:00:48 2018 @@ -74,16 +74,6 @@ motivations for starting work on a new front-end that could meet these needs. - A good (but quite dated) introduction to Clang can be found in the - following video lectures: - - -Clang Introduction -(May 2007) -Features and Performance of -Clang (July 2007) - - For a more detailed comparison between Clang and other compilers, please see the Clang comparison page. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342215 - [analyzer][UninitializedObjectChecker] Updated comments
Author: szelethus Date: Fri Sep 14 02:07:40 2018 New Revision: 342215 URL: http://llvm.org/viewvc/llvm-project?rev=342215&view=rev Log: [analyzer][UninitializedObjectChecker] Updated comments Some of the comments are incorrect, imprecise, or simply nonexistent. Since I have a better grasp on how the analyzer works, it makes sense to update most of them in a single swoop. I tried not to flood the code with comments too much, this amount feels just right to me. Differential Revision: https://reviews.llvm.org/D51417 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=342215&r1=342214&r2=342215&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Fri Sep 14 02:07:40 2018 @@ -26,31 +26,36 @@ namespace clang { namespace ento { -/// Represent a single field. This is only an interface to abstract away special -/// cases like pointers/references. +/// A lightweight polymorphic wrapper around FieldRegion *. We'll use this +/// interface to store addinitional information about fields. As described +/// later, a list of these objects (i.e. "fieldchain") will be constructed and +/// used for printing note messages should an uninitialized value be found. class FieldNode { protected: const FieldRegion *FR; + /// FieldNodes are never meant to be created on the heap, see + /// FindUninitializedFields::addFieldToUninits(). /* non-virtual */ ~FieldNode() = default; public: FieldNode(const FieldRegion *FR) : FR(FR) {} + // We'll delete all of these special member functions to force the users of + // this interface to only store references to FieldNode objects in containers. FieldNode() = delete; FieldNode(const FieldNode &) = delete; FieldNode(FieldNode &&) = delete; FieldNode &operator=(const FieldNode &) = delete; FieldNode &operator=(const FieldNode &&) = delete; - /// Profile - Used to profile the contents of this object for inclusion in a - /// FoldingSet. void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(this); } - // Helper method for uniqueing. + /// Helper method for uniqueing. bool isSameRegion(const FieldRegion *OtherFR) const { -// Special FieldNode descendants may wrap nullpointers -- we wouldn't like -// to unique these objects. +// Special FieldNode descendants may wrap nullpointers (for example if they +// describe a special relationship between two elements of the fieldchain) +// -- we wouldn't like to unique these objects. if (FR == nullptr) return false; @@ -63,19 +68,22 @@ public: return FR->getDecl(); } - // When a fieldchain is printed (a list of FieldNode objects), it will have - // the following format: - // 'this->...' + // When a fieldchain is printed, it will have the following format (without + // newline, indices are in order of insertion, from 1 to n): + // + // '... + // this->...' - /// If this is the last element of the fieldchain, this method will be called. + /// If this is the last element of the fieldchain, this method will print the + /// note message associated with it. /// The note message should state something like "uninitialized field" or /// "uninitialized pointee" etc. virtual void printNoteMsg(llvm::raw_ostream &Out) const = 0; - /// Print any prefixes before the fieldchain. + /// Print any prefixes before the fieldchain. Could contain casts, etc. virtual void printPrefix(llvm::raw_ostream &Out) const = 0; - /// Print the node. Should contain the name of the field stored in getRegion. + /// Print the node. Should contain the name of the field stored in FR. virtual void printNode(llvm::raw_ostream &Out) const = 0; /// Print the separator. For example, fields may be separated with '.' or @@ -89,14 +97,14 @@ public: /// even if Field is a captured lambda variable. std::string getVariableName(const FieldDecl *Field); -/// Represents a field chain. A field chain is a vector of fields where the -/// first element of the chain is the object under checking (not stored), and -/// every other element is a field, and the element that precedes it is the -/// object that contains it. +/// Represents a field chain. A field chain is a list of fields where the first +/// element of the chain is the object under checking (not stored), and every +/// other element is a field, and t
r342216 - Use Chrome and Firefox as example of success for clang
Author: sylvestre Date: Fri Sep 14 02:08:21 2018 New Revision: 342216 URL: http://llvm.org/viewvc/llvm-project?rev=342216&view=rev Log: Use Chrome and Firefox as example of success for clang Modified: cfe/trunk/www/index.html Modified: cfe/trunk/www/index.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/index.html?rev=342216&r1=342215&r2=342216&view=diff == --- cfe/trunk/www/index.html (original) +++ cfe/trunk/www/index.html Fri Sep 14 02:08:21 2018 @@ -84,11 +84,11 @@ Clang is considered to be a production quality C, Objective-C, C++ and Objective-C++ compiler when targeting X86-32, X86-64, and ARM (other targets may have caveats, but are - usually easy to fix). If you are looking for source analysis or - source-to-source transformation tools, Clang is probably a great - solution for you. Clang supports C++11, C++14 and C++17, please see the C++ status page for more - information. + usually easy to fix). As example, Clang is used in production to build + performance-critical software like Chrome or Firefox. If you are looking + for source analysis or source-to-source transformation tools, Clang is probably + a great solution for you. Clang supports C++11, C++14 and C++17, please see + the C++ status page for more information. Get it and get involved! ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51417: [analyzer][UninitializedObjectChecker] Updated comments
This revision was automatically updated to reflect the committed changes. Closed by commit rL342215: [analyzer][UninitializedObjectChecker] Updated comments (authored by Szelethus, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D51417?vs=163061&id=165446#toc Repository: rL LLVM https://reviews.llvm.org/D51417 Files: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Index: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp === --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp @@ -1,4 +1,4 @@ -//===- UninitializedPointer.cpp --*- C++ -*-==// +//===- UninitializedPointee.cpp --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -90,9 +90,8 @@ // Utility function declarations. -/// Returns whether T can be (transitively) dereferenced to a void pointer type -/// (void*, void**, ...). The type of the region behind a void pointer isn't -/// known, and thus FD can not be analyzed. +/// Returns whether \p T can be (transitively) dereferenced to a void pointer +/// type (void*, void**, ...). static bool isVoidPointer(QualType T); using DereferenceInfo = std::pair; @@ -107,9 +106,7 @@ // Methods for FindUninitializedFields. //===--===// -// Note that pointers/references don't contain fields themselves, so in this -// function we won't add anything to LocalChain. -bool FindUninitializedFields::isPointerOrReferenceUninit( +bool FindUninitializedFields::isDereferencableUninit( const FieldRegion *FR, FieldChainInfo LocalChain) { assert(isDereferencableType(FR->getDecl()->getType()) && @@ -222,12 +219,11 @@ while (const MemRegion *Tmp = State->getSVal(R, DynT).getAsRegion()) { R = Tmp->getAs(); - if (!R) return None; // We found a cyclic pointer, like int *ptr = (int *)&ptr. -// TODO: Report these fields too. +// TODO: Should we report these fields too? if (!VisitedRegions.insert(R).second) return None; Index: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp === --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -94,7 +94,9 @@ }; /// Represents that the FieldNode that comes after this is declared in a base -/// of the previous FieldNode. +/// of the previous FieldNode. As such, this descendant doesn't wrap a +/// FieldRegion, and is purely a tool to describe a relation between two other +/// FieldRegion wrapping descendants. class BaseClass final : public FieldNode { const QualType BaseClassT; @@ -296,7 +298,7 @@ } if (isDereferencableType(T)) { - if (isPointerOrReferenceUninit(FR, LocalChain)) + if (isDereferencableUninit(FR, LocalChain)) ContainsUninitField = true; continue; } @@ -314,7 +316,8 @@ llvm_unreachable("All cases are handled!"); } - // Checking bases. + // Checking bases. The checker will regard inherited data members as direct + // fields. const auto *CXXRD = dyn_cast(RD); if (!CXXRD) return ContainsUninitField; @@ -361,6 +364,9 @@ const FieldRegion *FieldChainInfo::getUninitRegion() const { assert(!Chain.isEmpty() && "Empty fieldchain!"); + + // ImmutableList::getHead() isn't a const method, hence the not too nice + // implementation. return (*Chain.begin()).getRegion(); } @@ -375,31 +381,11 @@ /// Prints every element except the last to `Out`. Since ImmutableLists store /// elements in reverse order, and have no reverse iterators, we use a /// recursive function to print the fieldchain correctly. The last element in -/// the chain is to be printed by `print`. +/// the chain is to be printed by `FieldChainInfo::print`. static void printTail(llvm::raw_ostream &Out, const FieldChainInfo::FieldChainImpl *L); -// TODO: This function constructs an incorrect string if a void pointer is a -// part of the chain: -// -// struct B { int x; } -// -// struct A { -// void *vptr; -// A(void* vptr) : vptr(vptr) {} -// }; -// -// void f() { -// B b; -// A a(&b); -// } -// -// The note message will be "uninitialized field 'this->vptr->x'", even though -// void pointers can't be dereferenced. This shoul
r342217 - [analyzer][UninitializedObjectChecker] Correct dynamic type is acquired for record pointees
Author: szelethus Date: Fri Sep 14 02:13:36 2018 New Revision: 342217 URL: http://llvm.org/viewvc/llvm-project?rev=342217&view=rev Log: [analyzer][UninitializedObjectChecker] Correct dynamic type is acquired for record pointees Differential Revision: https://reviews.llvm.org/D50892 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=342217&r1=342216&r2=342217&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Fri Sep 14 02:13:36 2018 @@ -234,5 +234,13 @@ static llvm::Optional d break; } + while (R->getAs()) { +NeedsCastBack = true; + +if (!isa(R->getSuperRegion())) + break; +R = R->getSuperRegion()->getAs(); + } + return std::make_pair(R, NeedsCastBack); } Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp?rev=342217&r1=342216&r2=342217&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp Fri Sep 14 02:13:36 2018 @@ -781,21 +781,53 @@ void fVirtualDiamondInheritanceTest3() { // Dynamic type test. //===--===// -struct DynTBase {}; -struct DynTDerived : DynTBase { - // TODO: we'd expect the note: {{uninitialized field 'this->x'}} - int x; // no-note +struct DynTBase1 {}; +struct DynTDerived1 : DynTBase1 { + int y; // expected-note{{uninitialized field 'static_cast(this->bptr)->y'}} }; -struct DynamicTypeTest { - DynTBase *bptr; +struct DynamicTypeTest1 { + DynTBase1 *bptr; int i = 0; - // TODO: we'd expect the warning: {{1 uninitialized field}} - DynamicTypeTest(DynTBase *bptr) : bptr(bptr) {} // no-warning + DynamicTypeTest1(DynTBase1 *bptr) : bptr(bptr) {} // expected-warning{{1 uninitialized field}} }; -void f() { - DynTDerived d; - DynamicTypeTest t(&d); +void fDynamicTypeTest1() { + DynTDerived1 d; + DynamicTypeTest1 t(&d); }; + +struct DynTBase2 { + int x; // expected-note{{uninitialized field 'static_cast(this->bptr)->DynTBase2::x'}} +}; +struct DynTDerived2 : DynTBase2 { + int y; // expected-note{{uninitialized field 'static_cast(this->bptr)->y'}} +}; + +struct DynamicTypeTest2 { + DynTBase2 *bptr; + int i = 0; + + DynamicTypeTest2(DynTBase2 *bptr) : bptr(bptr) {} // expected-warning{{2 uninitialized fields}} +}; + +void fDynamicTypeTest2() { + DynTDerived2 d; + DynamicTypeTest2 t(&d); +} + +struct SymbolicSuperRegionBase { + SymbolicSuperRegionBase() {} +}; + +struct SymbolicSuperRegionDerived : SymbolicSuperRegionBase { + SymbolicSuperRegionBase *bptr; // no-crash + SymbolicSuperRegionDerived(SymbolicSuperRegionBase *bptr) : bptr(bptr) {} +}; + +SymbolicSuperRegionDerived *getSymbolicRegion(); + +void fSymbolicSuperRegionTest() { + SymbolicSuperRegionDerived test(getSymbolicRegion()); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D50892: [analyzer][UninitializedObjectChecker] Correct dynamic type is acquired for record pointees
This revision was automatically updated to reflect the committed changes. Closed by commit rL342217: [analyzer][UninitializedObjectChecker] Correct dynamic type is acquired for… (authored by Szelethus, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D50892?vs=163479&id=165447#toc Repository: rL LLVM https://reviews.llvm.org/D50892 Files: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp Index: cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp === --- cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp @@ -781,21 +781,53 @@ // Dynamic type test. //===--===// -struct DynTBase {}; -struct DynTDerived : DynTBase { - // TODO: we'd expect the note: {{uninitialized field 'this->x'}} - int x; // no-note +struct DynTBase1 {}; +struct DynTDerived1 : DynTBase1 { + int y; // expected-note{{uninitialized field 'static_cast(this->bptr)->y'}} }; -struct DynamicTypeTest { - DynTBase *bptr; +struct DynamicTypeTest1 { + DynTBase1 *bptr; int i = 0; - // TODO: we'd expect the warning: {{1 uninitialized field}} - DynamicTypeTest(DynTBase *bptr) : bptr(bptr) {} // no-warning + DynamicTypeTest1(DynTBase1 *bptr) : bptr(bptr) {} // expected-warning{{1 uninitialized field}} }; -void f() { - DynTDerived d; - DynamicTypeTest t(&d); +void fDynamicTypeTest1() { + DynTDerived1 d; + DynamicTypeTest1 t(&d); }; + +struct DynTBase2 { + int x; // expected-note{{uninitialized field 'static_cast(this->bptr)->DynTBase2::x'}} +}; +struct DynTDerived2 : DynTBase2 { + int y; // expected-note{{uninitialized field 'static_cast(this->bptr)->y'}} +}; + +struct DynamicTypeTest2 { + DynTBase2 *bptr; + int i = 0; + + DynamicTypeTest2(DynTBase2 *bptr) : bptr(bptr) {} // expected-warning{{2 uninitialized fields}} +}; + +void fDynamicTypeTest2() { + DynTDerived2 d; + DynamicTypeTest2 t(&d); +} + +struct SymbolicSuperRegionBase { + SymbolicSuperRegionBase() {} +}; + +struct SymbolicSuperRegionDerived : SymbolicSuperRegionBase { + SymbolicSuperRegionBase *bptr; // no-crash + SymbolicSuperRegionDerived(SymbolicSuperRegionBase *bptr) : bptr(bptr) {} +}; + +SymbolicSuperRegionDerived *getSymbolicRegion(); + +void fSymbolicSuperRegionTest() { + SymbolicSuperRegionDerived test(getSymbolicRegion()); +} Index: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp === --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp @@ -234,5 +234,13 @@ break; } + while (R->getAs()) { +NeedsCastBack = true; + +if (!isa(R->getSuperRegion())) + break; +R = R->getSuperRegion()->getAs(); + } + return std::make_pair(R, NeedsCastBack); } Index: cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp === --- cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp @@ -781,21 +781,53 @@ // Dynamic type test. //===--===// -struct DynTBase {}; -struct DynTDerived : DynTBase { - // TODO: we'd expect the note: {{uninitialized field 'this->x'}} - int x; // no-note +struct DynTBase1 {}; +struct DynTDerived1 : DynTBase1 { + int y; // expected-note{{uninitialized field 'static_cast(this->bptr)->y'}} }; -struct DynamicTypeTest { - DynTBase *bptr; +struct DynamicTypeTest1 { + DynTBase1 *bptr; int i = 0; - // TODO: we'd expect the warning: {{1 uninitialized field}} - DynamicTypeTest(DynTBase *bptr) : bptr(bptr) {} // no-warning + DynamicTypeTest1(DynTBase1 *bptr) : bptr(bptr) {} // expected-warning{{1 uninitialized field}} }; -void f() { - DynTDerived d; - DynamicTypeTest t(&d); +void fDynamicTypeTest1() { + DynTDerived1 d; + DynamicTypeTest1 t(&d); }; + +struct DynTBase2 { + int x; // expected-note{{uninitialized field 'static_cast(this->bptr)->DynTBase2::x'}} +}; +struct DynTDerived2 : DynTBase2 { + int y; // expected-note{{uninitialized field 'static_cast(this->bptr)->y'}} +}; + +struct DynamicTypeTest2 { + DynTBase2 *bptr; + int i = 0; + + DynamicTypeTest2(DynTBase2 *bptr) : bptr(bptr) {} // expected-warning{{2 uninitialized fields}} +}; + +void fDynamicTypeTest2() { + DynTDerived2 d; + DynamicTypeTest2 t(&d); +} + +struct SymbolicSuperRegionBase { + SymbolicSuperRegionBase() {} +}; + +struct SymbolicSuperRegionDerived : SymbolicSuperRegionBase { + SymbolicSup
[PATCH] D52071: [clangd] Don't override the preamble while completing inside it, it doesn't work.
ilya-biryukov accepted this revision. ilya-biryukov added a comment. This revision is now accepted and ready to land. Neat, I was unaware that single-file mode completions actually work nicely in that case. LGTM! Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52071 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342219 - [analyzer][UninitializedObjectChecker] Refactored checker options
Author: szelethus Date: Fri Sep 14 02:39:26 2018 New Revision: 342219 URL: http://llvm.org/viewvc/llvm-project?rev=342219&view=rev Log: [analyzer][UninitializedObjectChecker] Refactored checker options Since I plan to add a number of new flags, it made sense to encapsulate them in a new struct, in order not to pollute FindUninitializedFields's constructor with new boolean options with super long names. This revision practically reverts D50508, since FindUninitializedFields now accesses the pedantic flag anyways. Differential Revision: https://reviews.llvm.org/D51679 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=342219&r1=342218&r2=342219&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Fri Sep 14 02:39:26 2018 @@ -10,8 +10,39 @@ // This file defines helper classes for UninitializedObjectChecker and // documentation about the logic of it. // -// To read about command line options and a description what this checker does, -// refer to UninitializedObjectChecker.cpp. +// The checker reports uninitialized fields in objects created after a +// constructor call. +// +// This checker has several options: +// - "Pedantic" (boolean). If its not set or is set to false, the checker +// won't emit warnings for objects that don't have at least one initialized +// field. This may be set with +// +// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`. +// +// - "NotesAsWarnings" (boolean). If set to true, the checker will emit a +// warning for each uninitalized field, as opposed to emitting one warning +// per constructor call, and listing the uninitialized fields that belongs +// to it in notes. Defaults to false. +// +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`. +// +// - "CheckPointeeInitialization" (boolean). If set to false, the checker will +// not analyze the pointee of pointer/reference fields, and will only check +// whether the object itself is initialized. Defaults to false. +// +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`. +// +// TODO: With some clever heuristics, some pointers should be dereferenced +// by default. For example, if the pointee is constructed within the +// constructor call, it's reasonable to say that no external object +// references it, and we wouldn't generate multiple report on the same +// pointee. +// +// Most of the following methods as well as the checker itself is defined in +// UninitializedObjectChecker.cpp. // // Some methods are implemented in UninitializedPointee.cpp, to reduce the // complexity of the main checker file. @@ -26,6 +57,12 @@ namespace clang { namespace ento { +struct UninitObjCheckerOptions { + bool IsPedantic = false; + bool ShouldConvertNotesToWarnings = false; + bool CheckPointeeInitialization = false; +}; + /// A lightweight polymorphic wrapper around FieldRegion *. We'll use this /// interface to store addinitional information about fields. As described /// later, a list of these objects (i.e. "fieldchain") will be constructed and @@ -147,7 +184,7 @@ class FindUninitializedFields { ProgramStateRef State; const TypedValueRegion *const ObjectR; - const bool CheckPointeeInitialization; + const UninitObjCheckerOptions Opts; bool IsAnyFieldInitialized = false; FieldChainInfo::FieldChain::Factory ChainFactory; @@ -169,7 +206,7 @@ public: /// uninitialized fields in R. FindUninitializedFields(ProgramStateRef State, const TypedValueRegion *const R, - bool CheckPointeeInitialization); + const UninitObjCheckerOptions &Opts); const UninitFieldMap &getUninitFields() { return UninitFields; } Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342219&r1=342218&r2=342219&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/Uninitial
[PATCH] D51679: [analyzer][UninitializedObjectChecker] Refactored checker options
This revision was automatically updated to reflect the committed changes. Closed by commit rC342219: [analyzer][UninitializedObjectChecker] Refactored checker options (authored by Szelethus, committed by ). Changed prior to commit: https://reviews.llvm.org/D51679?vs=164009&id=165449#toc Repository: rC Clang https://reviews.llvm.org/D51679 Files: lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Index: lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp === --- lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -10,36 +10,8 @@ // This file defines a checker that reports uninitialized fields in objects // created after a constructor call. // -// This checker has several options: -// - "Pedantic" (boolean). If its not set or is set to false, the checker -// won't emit warnings for objects that don't have at least one initialized -// field. This may be set with -// -// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`. -// -// - "NotesAsWarnings" (boolean). If set to true, the checker will emit a -// warning for each uninitalized field, as opposed to emitting one warning -// per constructor call, and listing the uninitialized fields that belongs -// to it in notes. Defaults to false. -// -// `-analyzer-config \ -// alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`. -// -// - "CheckPointeeInitialization" (boolean). If set to false, the checker will -// not analyze the pointee of pointer/reference fields, and will only check -// whether the object itself is initialized. Defaults to false. -// -// `-analyzer-config \ -// alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`. -// -// TODO: With some clever heuristics, some pointers should be dereferenced -// by default. For example, if the pointee is constructed within the -// constructor call, it's reasonable to say that no external object -// references it, and we wouldn't generate multiple report on the same -// pointee. -// -// To read about how the checker works, refer to the comments in -// UninitializedObject.h. +// To read about command line options and how the checker works, refer to the +// top of the file and inline comments in UninitializedObject.h. // // Some of the logic is implemented in UninitializedPointee.cpp, to reduce the // complexity of this file. @@ -62,10 +34,8 @@ std::unique_ptr BT_uninitField; public: - // These fields will be initialized when registering the checker. - bool IsPedantic; - bool ShouldConvertNotesToWarnings; - bool CheckPointeeInitialization; + // The fields of this struct will be initialized when registering the checker. + UninitObjCheckerOptions Opts; UninitializedObjectChecker() : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {} @@ -165,20 +135,13 @@ if (!Object) return; - FindUninitializedFields F(Context.getState(), Object->getRegion(), -CheckPointeeInitialization); + FindUninitializedFields F(Context.getState(), Object->getRegion(), Opts); const UninitFieldMap &UninitFields = F.getUninitFields(); if (UninitFields.empty()) return; - // In non-pedantic mode, if Object's region doesn't contain a single - // initialized field, we'll assume that Object was intentionally left - // uninitialized. - if (!IsPedantic && !F.isAnyFieldInitialized()) -return; - // There are uninitialized fields in the record. ExplodedNode *Node = Context.generateNonFatalErrorNode(Context.getState()); @@ -193,7 +156,7 @@ // For Plist consumers that don't support notes just yet, we'll convert notes // to warnings. - if (ShouldConvertNotesToWarnings) { + if (Opts.ShouldConvertNotesToWarnings) { for (const auto &Pair : UninitFields) { auto Report = llvm::make_unique( @@ -228,11 +191,15 @@ FindUninitializedFields::FindUninitializedFields( ProgramStateRef State, const TypedValueRegion *const R, -bool CheckPointeeInitialization) -: State(State), ObjectR(R), - CheckPointeeInitialization(CheckPointeeInitialization) { +const UninitObjCheckerOptions &Opts) +: State(State), ObjectR(R), Opts(Opts) { isNonUnionUninit(ObjectR, FieldChainInfo(ChainFactory)); + + // In non-pedantic mode, if ObjectR doesn't contain a single initialized + // field, we'll assume that Object was intentionally left uninitialized. + if (!Opts.IsPedantic && !isAnyFieldInitialized()) +UninitFields.clear(); } bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain) { @@ -502,10 +469,13
[PATCH] D51680: [analyzer][UninitializedObjectChecker] New flag to ignore records based on it's fields
Szelethus marked an inline comment as done. Szelethus added inline comments. Comment at: test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp:1-4 +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \ +// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \ +// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind" \ +// RUN: -std=c++11 -verify %s NoQ wrote: > If you like, you can make a directory for your tests, instead of a filename > prefix. > > Btw, thanks for pointing out that we can use `\` in run-lines, i never > noticed it before you started using it. Cheers! I actually saw this trick in D45050. https://reviews.llvm.org/D51680 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342220 - [analyzer][UninitializedObjectChecker] New flag to ignore records based on it's fields
Author: szelethus Date: Fri Sep 14 03:10:09 2018 New Revision: 342220 URL: http://llvm.org/viewvc/llvm-project?rev=342220&view=rev Log: [analyzer][UninitializedObjectChecker] New flag to ignore records based on it's fields Based on a suggestion from @george.karpenkov. In some cases, structs are used as unions with a help of a tag/kind field. This patch adds a new string flag (a pattern), that is matched against the fields of a record, and should a match be found, the entire record is ignored. For more info refer to http://lists.llvm.org/pipermail/cfe-dev/2018-August/058906.html and to the responses to that, especially http://lists.llvm.org/pipermail/cfe-dev/2018-August/059215.html. Differential Revision: https://reviews.llvm.org/D51680 Added: cfe/trunk/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/www/analyzer/alpha_checks.html Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=342220&r1=342219&r2=342220&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Fri Sep 14 03:10:09 2018 @@ -35,6 +35,13 @@ // `-analyzer-config \ // alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`. // +// - "IgnoreRecordsWithField" (string). If supplied, the checker will not +// analyze structures that have a field with a name or type name that +// matches the given pattern. Defaults to "". +// +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind"`. +// // TODO: With some clever heuristics, some pointers should be dereferenced // by default. For example, if the pointee is constructed within the // constructor call, it's reasonable to say that no external object @@ -60,7 +67,8 @@ namespace ento { struct UninitObjCheckerOptions { bool IsPedantic = false; bool ShouldConvertNotesToWarnings = false; - bool CheckPointeeInitialization = false; + bool CheckPointeeInitialization = false; + std::string IgnoredRecordsWithFieldPattern; }; /// A lightweight polymorphic wrapper around FieldRegion *. We'll use this Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342220&r1=342219&r2=342220&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Fri Sep 14 03:10:09 2018 @@ -109,6 +109,10 @@ getObjectVal(const CXXConstructorDecl *C static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, CheckerContext &Context); +/// Checks whether RD contains a field with a name or type name that matches +/// \p Pattern. +static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern); + //===--===// // Methods for UninitializedObjectChecker. //===--===// @@ -228,6 +232,12 @@ bool FindUninitializedFields::isNonUnion return true; } + if (!Opts.IgnoredRecordsWithFieldPattern.empty() && + shouldIgnoreRecord(RD, Opts.IgnoredRecordsWithFieldPattern)) { +IsAnyFieldInitialized = true; +return false; + } + bool ContainsUninitField = false; // Are all of this non-union's fields initialized? @@ -442,6 +452,19 @@ static bool willObjectBeAnalyzedLater(co return false; } +static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern) { + llvm::Regex R(Pattern); + + for (const FieldDecl *FD : RD->fields()) { +if (R.match(FD->getType().getAsString())) + return true; +if (R.match(FD->getName())) + return true; + } + + return false; +} + std::string clang::ento::getVariableName(const FieldDecl *Field) { // If Field is a captured lambda variable, Field->getName() will return with // an empty string. We can however acquire it's name from the lambda's @@ -472,10 +495,13 @@ void ento::registerUninitializedObjectCh AnalyzerOptions &AnOpts = Mgr.getAnalyzerOptions(); UninitObjCheckerOptions &ChOpts = Chk->Opts; - ChOpts.IsPedantic = A
[PATCH] D51680: [analyzer][UninitializedObjectChecker] New flag to ignore records based on it's fields
This revision was automatically updated to reflect the committed changes. Closed by commit rL342220: [analyzer][UninitializedObjectChecker] New flag to ignore records based on it's… (authored by Szelethus, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D51680?vs=164696&id=165454#toc Repository: rL LLVM https://reviews.llvm.org/D51680 Files: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp cfe/trunk/www/analyzer/alpha_checks.html Index: cfe/trunk/www/analyzer/alpha_checks.html === --- cfe/trunk/www/analyzer/alpha_checks.html +++ cfe/trunk/www/analyzer/alpha_checks.html @@ -356,6 +356,13 @@ whether the object itself is initialized. Defaults to false. -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true. + +"IgnoreRecordsWithField" (string). If supplied, the checker will not + analyze structures that have a field with a name or type name that + matches the given pattern. Defaults to "". + + -analyzer-config alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind". + Index: cfe/trunk/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp === --- cfe/trunk/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp @@ -0,0 +1,136 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \ +// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \ +// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind" \ +// RUN: -std=c++11 -verify %s + +// expected-no-diagnostics + +// Both type and name contains "kind". +struct UnionLikeStruct1 { + enum Kind { +volume, +area + } kind; + + int Volume; + int Area; + + UnionLikeStruct1(Kind kind, int Val) : kind(kind) { +switch (kind) { +case volume: + Volume = Val; + break; +case area: + Area = Val; + break; +} + } +}; + +void fUnionLikeStruct1() { + UnionLikeStruct1 t(UnionLikeStruct1::volume, 10); +} + +// Only name contains "kind". +struct UnionLikeStruct2 { + enum Type { +volume, +area + } kind; + + int Volume; + int Area; + + UnionLikeStruct2(Type kind, int Val) : kind(kind) { +switch (kind) { +case volume: + Volume = Val; + break; +case area: + Area = Val; + break; +} + } +}; + +void fUnionLikeStruct2() { + UnionLikeStruct2 t(UnionLikeStruct2::volume, 10); +} + +// Only type contains "kind". +struct UnionLikeStruct3 { + enum Kind { +volume, +area + } type; + + int Volume; + int Area; + + UnionLikeStruct3(Kind type, int Val) : type(type) { +switch (type) { +case volume: + Volume = Val; + break; +case area: + Area = Val; + break; +} + } +}; + +void fUnionLikeStruct3() { + UnionLikeStruct3 t(UnionLikeStruct3::volume, 10); +} + +// Only type contains "tag". +struct UnionLikeStruct4 { + enum Tag { +volume, +area + } type; + + int Volume; + int Area; + + UnionLikeStruct4(Tag type, int Val) : type(type) { +switch (type) { +case volume: + Volume = Val; + break; +case area: + Area = Val; + break; +} + } +}; + +void fUnionLikeStruct4() { + UnionLikeStruct4 t(UnionLikeStruct4::volume, 10); +} + +// Both name and type name contains but does not equal to tag/kind. +struct UnionLikeStruct5 { + enum WhateverTagBlahBlah { +volume, +area + } FunnyKindName; + + int Volume; + int Area; + + UnionLikeStruct5(WhateverTagBlahBlah type, int Val) : FunnyKindName(type) { +switch (FunnyKindName) { +case volume: + Volume = Val; + break; +case area: + Area = Val; + break; +} + } +}; + +void fUnionLikeStruct5() { + UnionLikeStruct5 t(UnionLikeStruct5::volume, 10); +} Index: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp === --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -109,6 +109,10 @@ static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, CheckerContext &Context); +/// Checks whether RD contains a field with a name or type name that matches +/// \p Pattern. +static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern); + //===--
[PATCH] D51332: [clang-tidy] Replace deprecated std::ios_base aliases
andobence updated this revision to Diff 165453. andobence added a comment. Fixed everything mentioned in comments. https://reviews.llvm.org/D51332 Files: clang-tidy/modernize/CMakeLists.txt clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.h clang-tidy/modernize/ModernizeTidyModule.cpp docs/ReleaseNotes.rst docs/clang-tidy/checks/list.rst docs/clang-tidy/checks/modernize-deprecated-ios-base-aliases.rst test/clang-tidy/modernize-deprecated-ios-base-aliases.cpp Index: test/clang-tidy/modernize-deprecated-ios-base-aliases.cpp === --- /dev/null +++ test/clang-tidy/modernize-deprecated-ios-base-aliases.cpp @@ -0,0 +1,239 @@ +// RUN: %check_clang_tidy %s modernize-deprecated-ios-base-aliases %t + +namespace std { +class ios_base { +public: + typedef int io_state; + typedef int open_mode; + typedef int seek_dir; + + typedef int streampos; + typedef int streamoff; +}; + +template +class basic_ios : public ios_base { +}; +} // namespace std + +// Test function return values (declaration) +std::ios_base::io_state f_5(); +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'std::ios_base::io_state' is deprecated; use 'std::ios_base::iostate' instead [modernize-deprecated-ios-base-aliases] +// CHECK-FIXES: std::ios_base::iostate f_5(); + +// Test function parameters. +void f_6(std::ios_base::open_mode); +// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 'std::ios_base::open_mode' is deprecated +// CHECK-FIXES: void f_6(std::ios_base::openmode); +void f_7(const std::ios_base::seek_dir &); +// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: 'std::ios_base::seek_dir' is deprecated +// CHECK-FIXES: void f_7(const std::ios_base::seekdir &); + +// Test on record type fields. +struct A { + std::ios_base::io_state field; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: std::ios_base::iostate field; + + typedef std::ios_base::io_state int_ptr_type; + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: typedef std::ios_base::iostate int_ptr_type; +}; + +struct B : public std::ios_base { + io_state a; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: iostate a; +}; + +struct C : public std::basic_ios { + io_state a; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: iostate a; +}; + +void f_1() { + std::ios_base::io_state a; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: std::ios_base::iostate a; + + // Check that spaces aren't modified unnecessarily. + std :: ios_base :: io_state b; + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: std :: ios_base :: iostate b; + + // Test construction from a temporary. + std::ios_base::io_state c = std::ios_base::io_state{}; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'std::ios_base::io_state' is deprecated + // CHECK-MESSAGES: :[[@LINE-2]]:46: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: std::ios_base::iostate c = std::ios_base::iostate{}; + + typedef std::ios_base::io_state alias1; + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: typedef std::ios_base::iostate alias1; + alias1 d(a); + + using alias2 = std::ios_base::io_state; + // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: using alias2 = std::ios_base::iostate; + alias2 e; + + // Test pointers. + std::ios_base::io_state *f; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: std::ios_base::iostate *f; + + // Test 'static' declarations. + static std::ios_base::io_state g; + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: static std::ios_base::iostate g; + + // Test with cv-qualifiers. + const std::ios_base::io_state h(0); + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: const std::ios_base::iostate h(0); + volatile std::ios_base::io_state i; + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: volatile std::ios_base::iostate i; + const volatile std::ios_base::io_state j(0); + // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: const volatile std::ios_base::iostate j(0); + + // Test auto and initializer-list. + auto k = std::ios_base::io_state{}; + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'std::ios_base::io_state' is deprecated + // CHECK-FIXES: auto k = std::ios_base::iostate{}; + + std::ios_base::io_state l{std::ios_base::io_state()}; + /
r342221 - [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger
Author: szelethus Date: Fri Sep 14 03:18:26 2018 New Revision: 342221 URL: http://llvm.org/viewvc/llvm-project?rev=342221&view=rev Log: [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger Differential Revision: https://reviews.llvm.org/D49437 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342221&r1=342220&r2=342221&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Fri Sep 14 03:18:26 2018 @@ -274,15 +274,15 @@ bool FindUninitializedFields::isNonUnion continue; } -if (isDereferencableType(T)) { +SVal V = State->getSVal(FieldVal); + +if (isDereferencableType(T) || V.getAs()) { if (isDereferencableUninit(FR, LocalChain)) ContainsUninitField = true; continue; } if (isPrimitiveType(T)) { - SVal V = State->getSVal(FieldVal); - if (isPrimitiveUninit(V)) { if (addFieldToUninits(LocalChain.add(RegularField(FR ContainsUninitField = true; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=342221&r1=342220&r2=342221&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Fri Sep 14 03:18:26 2018 @@ -57,9 +57,9 @@ public: } }; -/// Represents a void* field that needs to be casted back to its dynamic type -/// for a correct note message. -class NeedsCastLocField final : public FieldNode { +/// Represents a nonloc::LocAsInteger or void* field, that point to objects, but +/// needs to be casted back to its dynamic type for a correct note message. +class NeedsCastLocField : public FieldNode { QualType CastBackType; public: @@ -71,7 +71,13 @@ public: } virtual void printPrefix(llvm::raw_ostream &Out) const override { -Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; +// If this object is a nonloc::LocAsInteger. +if (getDecl()->getType()->isIntegerType()) + Out << "reinterpret_cast"; +// If this pointer's dynamic type is different then it's static type. +else + Out << "static_cast"; +Out << '<' << CastBackType.getAsString() << ">("; } virtual void printNode(llvm::raw_ostream &Out) const override { @@ -106,11 +112,12 @@ static llvm::Optional d bool FindUninitializedFields::isDereferencableUninit( const FieldRegion *FR, FieldChainInfo LocalChain) { - assert(isDereferencableType(FR->getDecl()->getType()) && - "This method only checks dereferencable objects!"); - SVal V = State->getSVal(FR); + assert((isDereferencableType(FR->getDecl()->getType()) || + V.getAs()) && + "This method only checks dereferencable objects!"); + if (V.isUnknown() || V.getAs()) { IsAnyFieldInitialized = true; return false; @@ -196,13 +203,15 @@ static llvm::Optional d llvm::SmallSet VisitedRegions; - // If the static type of the field is a void pointer, we need to cast it back - // to the dynamic type before dereferencing. - bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()); - SVal V = State->getSVal(FR); assert(V.getAsRegion() && "V must have an underlying region!"); + // If the static type of the field is a void pointer, or it is a + // nonloc::LocAsInteger, we need to cast it back to the dynamic type before + // dereferencing. + bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()) || + V.getAs(); + // The region we'd like to acquire. const auto *R = V.getAsRegion()->getAs(); if (!R) Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=342221&r1=342220&r2=342221&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Fri Sep 14 03:18:26 2018 @@ -22,6 +22,24 @@ void fConcreteInt
[PATCH] D51747: [clangd] Show deprecation diagnostics
kadircet updated this revision to Diff 165462. kadircet marked 2 inline comments as done. kadircet added a comment. - Add matchers to test. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D51747 Files: clangd/ClangdServer.cpp unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -43,6 +43,11 @@ namespace { +MATCHER(DeprecationWarning, "") { + return arg.Category == "Deprecations" && + arg.Severity == DiagnosticsEngine::Warning; +} + bool diagsContainErrors(const std::vector &Diagnostics) { for (auto D : Diagnostics) { if (D.Severity == DiagnosticsEngine::Error || @@ -963,6 +968,42 @@ Field(&CodeCompletion::Name, "baz"))); } +TEST(ClangdCompilecommand, DiagnosticDeprecated) { + std::string Code(R"cpp( +void foo() __attribute__((deprecated)); +void bar() { + foo(); +} + )cpp"); + auto SourcePath = testPath("source/foo.cpp"); + + MockFSProvider FS; + struct DiagConsumer : public DiagnosticsConsumer { +void onDiagnosticsReady(PathRef File, +std::vector Diagnostics) override { + Diags.insert(Diags.end(), Diagnostics.begin(), Diagnostics.end()); +} + +void reset() { + Diags.clear(); +} + +std::vector Diags; + } DiagConsumer; + MockCompilationDatabase CDB; + CDB.ExtraClangFlags.push_back("-Wno-deprecated"); + ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); + + runAddDocument(Server, SourcePath, Code); + EXPECT_THAT(DiagConsumer.Diags, ElementsAre(DeprecationWarning())); + DiagConsumer.reset(); + + CDB.ExtraClangFlags.push_back("-Werror"); + runAddDocument(Server, SourcePath, Code); + EXPECT_THAT(DiagConsumer.Diags, ElementsAre(DeprecationWarning())); +} + + } // namespace } // namespace clangd } // namespace clang Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -531,9 +531,15 @@ if (!C) // FIXME: Suppress diagnostics? Let the user know? C = CDB.getFallbackCommand(File); + // These flags are working for both gcc and clang-cl driver modes. // Inject the resource dir. // FIXME: Don't overwrite it if it's already there. C->CommandLine.push_back("-resource-dir=" + ResourceDir); + // Deprecations are often hidden for full-project build. They're useful in + // context. + C->CommandLine.push_back("-Wdeprecated"); + // Adding -Wdeprecated would trigger errors in projects what set -Werror. + C->CommandLine.push_back("-Wno-error=deprecated"); return std::move(*C); } Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -43,6 +43,11 @@ namespace { +MATCHER(DeprecationWarning, "") { + return arg.Category == "Deprecations" && + arg.Severity == DiagnosticsEngine::Warning; +} + bool diagsContainErrors(const std::vector &Diagnostics) { for (auto D : Diagnostics) { if (D.Severity == DiagnosticsEngine::Error || @@ -963,6 +968,42 @@ Field(&CodeCompletion::Name, "baz"))); } +TEST(ClangdCompilecommand, DiagnosticDeprecated) { + std::string Code(R"cpp( +void foo() __attribute__((deprecated)); +void bar() { + foo(); +} + )cpp"); + auto SourcePath = testPath("source/foo.cpp"); + + MockFSProvider FS; + struct DiagConsumer : public DiagnosticsConsumer { +void onDiagnosticsReady(PathRef File, +std::vector Diagnostics) override { + Diags.insert(Diags.end(), Diagnostics.begin(), Diagnostics.end()); +} + +void reset() { + Diags.clear(); +} + +std::vector Diags; + } DiagConsumer; + MockCompilationDatabase CDB; + CDB.ExtraClangFlags.push_back("-Wno-deprecated"); + ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); + + runAddDocument(Server, SourcePath, Code); + EXPECT_THAT(DiagConsumer.Diags, ElementsAre(DeprecationWarning())); + DiagConsumer.reset(); + + CDB.ExtraClangFlags.push_back("-Werror"); + runAddDocument(Server, SourcePath, Code); + EXPECT_THAT(DiagConsumer.Diags, ElementsAre(DeprecationWarning())); +} + + } // namespace } // namespace clangd } // namespace clang Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -531,9 +531,15 @@ if (!C) // FIXME: Suppress diagnostics? Let the user know? C = CDB.getFallbackCommand(File); + // These flags are working for both gcc and clang-cl driver modes. // Inject the resource dir. // FIXME: Don't overwrite it if it's already there. C->CommandLine.push_back("-resou
[PATCH] D52083: [clangd] Store OR iterator children in heap
kbobyrev created this revision. kbobyrev added reviewers: ioeric, sammccall, ilya-biryukov. kbobyrev added a project: clang-tools-extra. Herald added subscribers: kadircet, arphaman, jkorous, MaskRay. Use min-heap invariant for OR iterator's children. This helps to avoid iterating through all children in `reachedEnd()`, `peek()` and allows early-stopping in `consume()` and `advance()`. This optimization results in ~8-9% of performance boost on benchmark with ~4300 real queries to LLVM static index. benchmark's `compare.py` output: benchmarkTime CPU Time Old Time New CPU Old CPU New - DexQueries-0.0706 -0.070647191492414385985920 47191009564385946455 https://reviews.llvm.org/D52083 Files: clang-tools-extra/clangd/index/dex/Iterator.cpp clang-tools-extra/unittests/clangd/DexTests.cpp Index: clang-tools-extra/unittests/clangd/DexTests.cpp === --- clang-tools-extra/unittests/clangd/DexTests.cpp +++ clang-tools-extra/unittests/clangd/DexTests.cpp @@ -255,20 +255,20 @@ } TEST(DexIterators, StringRepresentation) { - const PostingList L0({4, 7, 8, 20, 42, 100}); + const PostingList L0({0, 1, 8, 20, 42, 100}); const PostingList L1({1, 3, 5, 8, 9}); const PostingList L2({1, 5, 7, 9}); - const PostingList L3({0, 5}); + const PostingList L3({0, 1}); const PostingList L4({0, 1, 5}); const PostingList L5({}); - EXPECT_EQ(llvm::to_string(*(L0.iterator())), "[4]"); + EXPECT_EQ(llvm::to_string(*(L0.iterator())), "[0]"); - auto Nested = - createAnd(createAnd(L1.iterator(), L2.iterator()), -createOr(L3.iterator(), L4.iterator(), L5.iterator())); + auto Nested = createAnd( + createAnd(L1.iterator(), L2.iterator(), L4.iterator(), L0.iterator()), + createOr(L3.iterator(), L5.iterator())); - EXPECT_EQ(llvm::to_string(*Nested), "(& (| [5] [1] [END]) (& [1] [1]))"); + EXPECT_EQ(llvm::to_string(*Nested), "(& (| [1] [END]) (& [1] [1] [1] [1]))"); } TEST(DexIterators, Limit) { Index: clang-tools-extra/clangd/index/dex/Iterator.cpp === --- clang-tools-extra/clangd/index/dex/Iterator.cpp +++ clang-tools-extra/clangd/index/dex/Iterator.cpp @@ -125,69 +125,80 @@ bool ReachedEnd = false; }; +// Return LHS > RHS. +auto Compare = [](const std::unique_ptr &LHS, + const std::unique_ptr &RHS) { + if (LHS->reachedEnd()) +return true; + if (RHS->reachedEnd()) +return false; + return LHS->peek() > RHS->peek(); +}; + /// Implements Iterator over the union of other iterators. /// /// OrIterator iterates through all items which can be pointed to by at least /// one child. To preserve the sorted order, this iterator always advances the /// child with smallest Child->peek() value. OrIterator becomes exhausted as /// soon as all of its children are exhausted. +/// +/// Invariant: Children are always stored in a min-heap which puts iterators +/// with the smallest DocID to the front. class OrIterator : public Iterator { public: explicit OrIterator(std::vector> AllChildren) : Children(std::move(AllChildren)) { assert(!Children.empty() && "OR iterator should have at least one child."); +// Initialize invariant. +std::make_heap(begin(Children), end(Children), Compare); } - /// Returns true if all children are exhausted. - bool reachedEnd() const override { -return std::all_of(begin(Children), end(Children), - [](const std::unique_ptr &Child) { - return Child->reachedEnd(); - }); - } + /// Returns true if all children are exhausted. Due to the invariant, if the + /// first child has reached the end, all of them have reached the end. + bool reachedEnd() const override { return Children.front()->reachedEnd(); } /// Moves each child pointing to the smallest DocID to the next item. void advance() override { assert(!reachedEnd() && "OR iterator can't advance() at the end."); const auto SmallestID = peek(); -for (const auto &Child : Children) - if (!Child->reachedEnd() && Child->peek() == SmallestID) -Child->advance(); +// The first element always contains Child with the smallest DocID. +while (!Children.front()->reachedEnd() && + Children.front()->peek() == SmallestID) { + Children.front()->advance(); + // Restore invariant. + std::pop_heap(begin(Children), end(Children), Compare); + std::push_heap(begin(Children), end(Children), Compare); +} } /// Advances each child to the next existing element with DocumentID >= ID. void advanceTo(DocID ID) override { assert(!reachedEnd() && "OR iterator can't advanceTo() at the en
[PATCH] D52066: [Driver] Fix missing MultiArch include dir on powerpcspe
glaubitz added a comment. I don't have commit access, btw. So it would be nice if someone else could commit this for me. Thanks! Repository: rC Clang https://reviews.llvm.org/D52066 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51747: [clangd] Show deprecation diagnostics
kadircet added a comment. In https://reviews.llvm.org/D51747#1233530, @ilya-biryukov wrote: > In https://reviews.llvm.org/D51747#1233499, @kadircet wrote: > > > Np, not planning to land it before we figure out the issue with vim can't > > handling lots of diagnostics anyway. > > > Just wondering: what's the problem with Vim? Slowness? Bad UI for diagnostics > when there are many of those? No, it starts to lag after some amount of diagnostics. I can't even move between lines in the file without a huge latency, and it doesn't return to normal after some time. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D51747 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52084: [clangd] NFC: Update documentation of Iterator's dump format
kbobyrev created this revision. kbobyrev added reviewers: ioeric, sammccall, ilya-biryukov. kbobyrev added a project: clang-tools-extra. Herald added subscribers: kadircet, arphaman, jkorous, MaskRay. Raw posting list iterator's `dump()` was changed in https://reviews.llvm.org/rCTE342155, but the documentation was not updated. https://reviews.llvm.org/D52084 Files: clang-tools-extra/clangd/index/dex/Iterator.h Index: clang-tools-extra/clangd/index/dex/Iterator.h === --- clang-tools-extra/clangd/index/dex/Iterator.h +++ clang-tools-extra/clangd/index/dex/Iterator.h @@ -93,9 +93,7 @@ /// /// Where Type is the iterator type representation: "&" for And, "|" for Or, /// ChildN is N-th iterator child. Raw iterators over PostingList are - /// represented as "[ID1, ID2, ..., {IDN}, ... END]" where IDN is N-th - /// PostingList entry and the element which is pointed to by the PostingList - /// iterator is enclosed in {} braces. + /// represented as "[ID]" where ID is the element under iterator cursor. friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Iterator &Iterator) { return Iterator.dump(OS); Index: clang-tools-extra/clangd/index/dex/Iterator.h === --- clang-tools-extra/clangd/index/dex/Iterator.h +++ clang-tools-extra/clangd/index/dex/Iterator.h @@ -93,9 +93,7 @@ /// /// Where Type is the iterator type representation: "&" for And, "|" for Or, /// ChildN is N-th iterator child. Raw iterators over PostingList are - /// represented as "[ID1, ID2, ..., {IDN}, ... END]" where IDN is N-th - /// PostingList entry and the element which is pointed to by the PostingList - /// iterator is enclosed in {} braces. + /// represented as "[ID]" where ID is the element under iterator cursor. friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Iterator &Iterator) { return Iterator.dump(OS); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52076: [CodeComplete] Add completions for filenames in #include directives.
ilya-biryukov added a comment. Amazing, can't wait for it to land! Comment at: lib/Lex/Lexer.cpp:1931 + StringRef PartialPath(AfterQuote, CurPtr - 1 - AfterQuote); + auto Slash = PartialPath.rfind('/'); + StringRef Dir = It's also valid to use `\` for path separators on Windows, maybe also handle those? Clang also supports this when running e.g. `clang-cl /c foo.cpp`. Comment at: lib/Lex/Lexer.cpp:2065 +if (C == '\n' || C == '\r' ||// Newline. +(C == 0 && (CurPtr - 1 == BufferEnd))) { // End of file. // If the filename is unterminated, then it must just be a lone < Does that mean we're losing completion at the end of file? Not sure if it's a big deal. The only common pattern I can come up with is starting with an empty file and writing: ``` #include "^ ``` Should we handle that? WDYT? Comment at: lib/Lex/Lexer.cpp:2075 +// Completion only applies to the filename, after the last slash. +StringRef PartialPath(AfterLessPos, CurPtr - 1 - AfterLessPos); +auto Slash = PartialPath.rfind('/'); This code looks exactly the same between two functions. Maybe extract it into a helper function? Comment at: lib/Sema/SemaCodeComplete.cpp:8021 +// Directory completion is up to the slash, e.g. ' : '"'); +auto R = SeenResults.insert(TypedChunk); Could we avoid adding `/`, `>` and `"` if it's currently missing? Otherwise it'll be annoying for editors that auto-add closing quotes and completions when editing existing includes, i.e. ``` // It's cool if we complete bar.h" (with closing quote) here: #include "foo/^ // It's annoying if we complete an extra closing quote here: #include "foo/^" ``` Comment at: lib/Sema/SemaCodeComplete.cpp:8028 +CodeCompleter->getCodeCompletionTUInfo()); + Builder.AddTextChunk(InternedPrefix); + Builder.AddTypedTextChunk(InternedTyped); Maybe leave this out? When completing `std::^` the completion is `vector`, not `std::vector`. In the same spirit, for includes I would expect completions for `#include ` to be `bar.h`, not ``. Comment at: lib/Sema/SemaCodeComplete.cpp:8046 + !EC && It != vfs::directory_iterator(); It.increment(EC)) { + if (++Count == 1000) // If we happen to hit a huge directory, +break; // bail out early so we're not too slow. The size of `/usr/include` on my machine is ~830 files and dirs, which is a little close to a limit. Not sure if the number of files grow with time or with a number of installed packages, but maybe we want a slightly higher limit to make sure it's won stop showing some results from this important include dir anytime soon? Comment at: lib/Sema/SemaCodeComplete.cpp:8057 + if (!(Filename.endswith(".h") || Filename.endswith(".hh") || +Filename.endswith(".H") || Filename.endswith(".hpp") || +Filename.endswith(".inc"))) Maybe do case-insensitive matching? A corner case, but still... Comment at: lib/Sema/SemaCodeComplete.cpp:8076 + // header maps are not (currently) enumerable. + break; +case DirectoryLookup::LT_NormalDir: NIT: Maybe return from each branch and put llvm_unreachable at the end of the function? To get an error in case the new enum value is added in addition to the compiler warning. Feel free to ignore if you like the current version more, the compiler warning is not likely to go unnoticed anyway. Repository: rC Clang https://reviews.llvm.org/D52076 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51332: [clang-tidy] Replace deprecated std::ios_base aliases
andobence marked 2 inline comments as done. andobence added inline comments. Comment at: clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp:34 + // provide any benefit to other languages, despite being benign. + if (!getLangOpts().CPlusPlus) +return; JonasToth wrote: > Which standard supplies the replacement functionality? e.g. for C++98 the > warning is probably not relevant because there is no way to replace the > deprecated types, but for C++17 it is possible. C++98 already has them, these types has been deprecated since draft N0785 from 1995. https://reviews.llvm.org/D51332 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52083: [clangd] Store OR iterator children in heap
ilya-biryukov added inline comments. Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:128 +// Return LHS > RHS. +auto Compare = [](const std::unique_ptr &LHS, NIT: use triple-slash comments. NIT: LHS > RHS seems to be exactly what's defined by this function. Maybe mention `peek()` to explain how actual comparison works? Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:129 +// Return LHS > RHS. +auto Compare = [](const std::unique_ptr &LHS, + const std::unique_ptr &RHS) { Turn lambda into a function? Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:129 +// Return LHS > RHS. +auto Compare = [](const std::unique_ptr &LHS, + const std::unique_ptr &RHS) { ilya-biryukov wrote: > Turn lambda into a function? Call `Greater` to avoid confusion? `Compare` can mean comparisons in both directions. Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:197 +for (const auto &Child : Children) { + if (Child->peek() != ID) +break; This seems to assume Children is sorted, but that's not the case. Why is it valid to iterate only a subset of the vector? https://reviews.llvm.org/D52083 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51429: [AArch64] Return Address Signing B Key Support
LukeCheeseman updated this revision to Diff 165467. LukeCheeseman added a comment. - updated tests to check the default a_key attribute is included in functions that have the return address signing scope attribute - setting the return-address-sign-key attribute of global static constructors https://reviews.llvm.org/D51429 Files: include/clang/Driver/Options.td include/clang/Frontend/CodeGenOptions.def include/clang/Frontend/CodeGenOptions.h lib/CodeGen/CGDeclCXX.cpp lib/CodeGen/TargetInfo.cpp lib/Driver/ToolChains/Clang.cpp lib/Frontend/CompilerInvocation.cpp test/CodeGen/aarch64-sign-return-address.c test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp Index: test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp === --- test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp +++ test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp @@ -4,6 +4,10 @@ // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL // RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all %s | \ // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all+a_key %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-A-KEY +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all+b_key %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-B-KEY struct Foo { Foo() {} @@ -17,5 +21,7 @@ // CHECK: @[[CTOR_FN]]() #[[ATTR:[0-9]*]] // CHECK-NONE-NOT: attributes #[[ATTR]] = { {{.*}} "sign-return-address"={{.*}} }} -// CHECK-PARTIAL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="non-leaf" {{.*}}} -// CHECK-ALL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" {{.*}} } +// CHECK-PARTIAL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" {{.*}}} +// CHECK-ALL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" {{.*}} } +// CHECK-A-KEY: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" {{.*}} } +// CHECK-B-KEY: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key" {{.*}} } Index: test/CodeGen/aarch64-sign-return-address.c === --- test/CodeGen/aarch64-sign-return-address.c +++ test/CodeGen/aarch64-sign-return-address.c @@ -1,14 +1,22 @@ // RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=none %s | FileCheck %s --check-prefix=CHECK-NONE // RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=non-leaf %s | FileCheck %s --check-prefix=CHECK-PARTIAL // RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK-ALL +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all+a_key %s | FileCheck %s --check-prefix=CHECK-A-KEY +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all+b_key %s | FileCheck %s --check-prefix=CHECK-B-KEY // CHECK-NONE: @foo() #[[ATTR:[0-9]*]] // CHECK-NONE-NOT: attributes #[[ATTR]] = { {{.*}} "sign-return-address"={{.*}} }} // CHECK-PARTIAL: @foo() #[[ATTR:[0-9]*]] -// CHECK-PARTIAL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="non-leaf" {{.*}}} +// CHECK-PARTIAL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" {{.*}}} // CHECK-ALL: @foo() #[[ATTR:[0-9]*]] -// CHECK-ALL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" {{.*}} } +// CHECK-ALL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" {{.*}} } + +// CHECK-A-KEY: @foo() #[[ATTR:[0-9]*]] +// CHECK-A-KEY: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" {{.*}} } + +// CHECK-B-KEY: @foo() #[[ATTR:[0-9]*]] +// CHECK-B-KEY: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key" {{.*}} } void foo() {} Index: lib/Frontend/CompilerInvocation.cpp === --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1129,8 +1129,11 @@ Opts.Addrsig = Args.hasArg(OPT_faddrsig); - if (Arg *A = Args.getLastArg(OPT_msign_return_address)) { -StringRef SignScope = A->getValue(); + if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) { +const auto SignScopeKey = StringRef(A->getValue()).split('+'); +StringRef SignScope = SignScopeKey.first; +StringRef SignKey = SignScopeKey.second; + if (SignScope.equals_lower("none")) Opts.setSignReturnAddress(CodeGenOptions::SignReturnAddressSc
[PATCH] D52036: [Analyzer] Use diff_plist in tests, NFC
miyuki updated this revision to Diff 165469. miyuki retitled this revision from "[Analyzer] Make plist tests less fragile" to "[Analyzer] Use diff_plist in tests, NFC". miyuki edited the summary of this revision. miyuki added a comment. Use a different approach (suggested by Artem). https://reviews.llvm.org/D52036 Files: test/Analysis/NewDelete-path-notes.cpp test/Analysis/conditional-path-notes.c test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp test/Analysis/copypaste/plist-diagnostics.cpp test/Analysis/cxx-for-range.cpp test/Analysis/diagnostics/deref-track-symbolic-region.c test/Analysis/diagnostics/report-issues-within-main-file.cpp test/Analysis/diagnostics/undef-value-caller.c test/Analysis/diagnostics/undef-value-param.c test/Analysis/diagnostics/undef-value-param.m test/Analysis/edges-new.mm test/Analysis/generics.m test/Analysis/inline-plist.c test/Analysis/inline-unique-reports.c test/Analysis/inlining/eager-reclamation-path-notes.c test/Analysis/inlining/eager-reclamation-path-notes.cpp test/Analysis/inlining/path-notes.c test/Analysis/inlining/path-notes.cpp test/Analysis/inlining/path-notes.m test/Analysis/method-call-path-notes.cpp test/Analysis/model-file.cpp test/Analysis/null-deref-path-notes.m test/Analysis/nullability-notes.m test/Analysis/objc-arc.m test/Analysis/plist-macros.cpp test/Analysis/plist-output-alternate.m test/Analysis/plist-output.m test/Analysis/retain-release-path-notes.m test/Analysis/unix-fns.c Index: test/Analysis/unix-fns.c === --- test/Analysis/unix-fns.c +++ test/Analysis/unix-fns.c @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-config faux-bodies=true -fblocks -verify -o %t.plist -// RUN: cat %t.plist | diff -u -w -I "/" -I ".:" -I "version" - %S/Inputs/expected-plists/unix-fns.c.plist +// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/unix-fns.c.plist // RUN: mkdir -p %t.dir // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,osx.API,optin.portability -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s // RUN: rm -fR %t.dir Index: test/Analysis/retain-release-path-notes.m === --- test/Analysis/retain-release-path-notes.m +++ test/Analysis/retain-release-path-notes.m @@ -1,6 +1,6 @@ // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=text -verify %s // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=plist-multi-file %s -o %t -// RUN: cat %t | diff -u -w -I "/" -I ".:" -I "version" - %S/Inputs/expected-plists/retain-release-path-notes.m.plist +// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/retain-release-path-notes.m.plist /*** This file is for testing the path-sensitive notes for retain/release errors. Index: test/Analysis/plist-output.m === --- test/Analysis/plist-output.m +++ test/Analysis/plist-output.m @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-config eagerly-assume=false %s -analyzer-checker=osx.cocoa.RetainCount,deadcode.DeadStores,core -analyzer-output=plist -o %t.plist -// RUN: cat %t.plist | diff -u -w -I "/" -I ".:" -I "version" - %S/Inputs/expected-plists/plist-output.m.plist +// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/plist-output.m.plist void test_null_init(void) { int *p = 0; Index: test/Analysis/plist-output-alternate.m === --- test/Analysis/plist-output-alternate.m +++ test/Analysis/plist-output-alternate.m @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -fblocks -analyzer-output=plist -o %t %s -// RUN: cat %t | diff -u -w -I "/" -I ".:" -I "version" - %S/Inputs/expected-plists/plist-output-alternate.m.plist +// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/plist-output-alternate.m.plist void test_null_init(void) { int *p = 0; Index: test/Analysis/plist-macros.cpp === --- test/Analysis/plist-macros.cpp +++ test/Analysis/plist-macros.cpp @@ -1,6 +1,6 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -verify %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-output=plist-multi-file %s -o %t.plist -// RUN: cat %t.plist | diff -u -w -I "/" -I ".:" -I "version" - %S/Inputs/expected-plists/plist-macros.cpp.plist +// RUN: cat %t.plist | %diff_plist
[PATCH] D52078: [clangd] Store preamble macros in dynamic index.
ilya-biryukov added a comment. ~1% increase in memory usage seems totally fine. Actually surprised it's that small. Overall LG, just a single comment about extra copying. Thanks for the change, looks like a great improvement! Comment at: clangd/index/FileIndex.cpp:84 +Merged.insert(Macro); + for (const auto &Sym : Collector.takeSymbols()) +Merged.insert(Sym); Why make an extra copy of the symbols? Why not add macros to the same builder used in collector? Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52078 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52083: [clangd] Store OR iterator children in heap
ilya-biryukov added inline comments. Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:128 +// Return LHS > RHS. +auto Compare = [](const std::unique_ptr &LHS, ilya-biryukov wrote: > NIT: use triple-slash comments. > NIT: LHS > RHS seems to be exactly what's defined by this function. Maybe > mention `peek()` to explain how actual comparison works? To make the second part of the comment clearer: `LHS > RHS` **duplicates** what could be inferred from the function name+body (which is small enough to be readily readable) https://reviews.llvm.org/D52083 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: r342221 - [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger
This introduced revision introduced a new warning: ../tools/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp:62:7: warning: '(anonymous namespace)::NeedsCastLocField' has virtual functions but non-virtual destructor [-Wnon-virtual-dtor] Which is turned into an error on our integrates, so it breaks us. Could you please take a look? A simple workaround would be to make FieldNode destructor virtual. Does that make sense? On Fri, Sep 14, 2018 at 12:19 PM Kristof Umann via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: szelethus > Date: Fri Sep 14 03:18:26 2018 > New Revision: 342221 > > URL: http://llvm.org/viewvc/llvm-project?rev=342221&view=rev > Log: > [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger > > Differential Revision: https://reviews.llvm.org/D49437 > > Modified: > > cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp > > cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp > cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp > > Modified: > cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342221&r1=342220&r2=342221&view=diff > > == > --- > cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp > (original) > +++ > cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp > Fri Sep 14 03:18:26 2018 > @@ -274,15 +274,15 @@ bool FindUninitializedFields::isNonUnion >continue; > } > > -if (isDereferencableType(T)) { > +SVal V = State->getSVal(FieldVal); > + > +if (isDereferencableType(T) || V.getAs()) { >if (isDereferencableUninit(FR, LocalChain)) > ContainsUninitField = true; >continue; > } > > if (isPrimitiveType(T)) { > - SVal V = State->getSVal(FieldVal); > - >if (isPrimitiveUninit(V)) { > if (addFieldToUninits(LocalChain.add(RegularField(FR >ContainsUninitField = true; > > Modified: > cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=342221&r1=342220&r2=342221&view=diff > > == > --- > cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp > (original) > +++ > cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp > Fri Sep 14 03:18:26 2018 > @@ -57,9 +57,9 @@ public: >} > }; > > -/// Represents a void* field that needs to be casted back to its dynamic > type > -/// for a correct note message. > -class NeedsCastLocField final : public FieldNode { > +/// Represents a nonloc::LocAsInteger or void* field, that point to > objects, but > +/// needs to be casted back to its dynamic type for a correct note > message. > +class NeedsCastLocField : public FieldNode { >QualType CastBackType; > > public: > @@ -71,7 +71,13 @@ public: >} > >virtual void printPrefix(llvm::raw_ostream &Out) const override { > -Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; > +// If this object is a nonloc::LocAsInteger. > +if (getDecl()->getType()->isIntegerType()) > + Out << "reinterpret_cast"; > +// If this pointer's dynamic type is different then it's static type. > +else > + Out << "static_cast"; > +Out << '<' << CastBackType.getAsString() << ">("; >} > >virtual void printNode(llvm::raw_ostream &Out) const override { > @@ -106,11 +112,12 @@ static llvm::Optional d > bool FindUninitializedFields::isDereferencableUninit( > const FieldRegion *FR, FieldChainInfo LocalChain) { > > - assert(isDereferencableType(FR->getDecl()->getType()) && > - "This method only checks dereferencable objects!"); > - >SVal V = State->getSVal(FR); > > + assert((isDereferencableType(FR->getDecl()->getType()) || > + V.getAs()) && > + "This method only checks dereferencable objects!"); > + >if (V.isUnknown() || V.getAs()) { > IsAnyFieldInitialized = true; > return false; > @@ -196,13 +203,15 @@ static llvm::Optional d > >llvm::SmallSet VisitedRegions; > > - // If the static type of the field is a void pointer, we need to cast > it back > - // to the dynamic type before dereferencing. > - bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()); > - >SVal V = State->getSVal(FR); >assert(V.getAsRegion() && "V must have an underlying region!"); > > + // If the static type of the field is a void pointer, or it is a > + // nonloc::LocAsInteger, we need to cast it
Re: r342221 - [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger
Ah, the reason why it does not fire on other inheritors is because they're final. Any reason to remove final from NeedsCastLocField? On Fri, Sep 14, 2018 at 1:17 PM Ilya Biryukov wrote: > This introduced revision introduced a new warning: > ../tools/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp:62:7: > warning: '(anonymous namespace)::NeedsCastLocField' has virtual functions > but non-virtual destructor [-Wnon-virtual-dtor] > > Which is turned into an error on our integrates, so it breaks us. Could > you please take a look? > A simple workaround would be to make FieldNode destructor virtual. > Does that make sense? > > > On Fri, Sep 14, 2018 at 12:19 PM Kristof Umann via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> Author: szelethus >> Date: Fri Sep 14 03:18:26 2018 >> New Revision: 342221 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=342221&view=rev >> Log: >> [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger >> >> Differential Revision: https://reviews.llvm.org/D49437 >> >> Modified: >> >> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp >> >> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp >> cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp >> >> Modified: >> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342221&r1=342220&r2=342221&view=diff >> >> == >> --- >> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp >> (original) >> +++ >> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp >> Fri Sep 14 03:18:26 2018 >> @@ -274,15 +274,15 @@ bool FindUninitializedFields::isNonUnion >>continue; >> } >> >> -if (isDereferencableType(T)) { >> +SVal V = State->getSVal(FieldVal); >> + >> +if (isDereferencableType(T) || V.getAs()) { >>if (isDereferencableUninit(FR, LocalChain)) >> ContainsUninitField = true; >>continue; >> } >> >> if (isPrimitiveType(T)) { >> - SVal V = State->getSVal(FieldVal); >> - >>if (isPrimitiveUninit(V)) { >> if (addFieldToUninits(LocalChain.add(RegularField(FR >>ContainsUninitField = true; >> >> Modified: >> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=342221&r1=342220&r2=342221&view=diff >> >> == >> --- >> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp >> (original) >> +++ >> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp >> Fri Sep 14 03:18:26 2018 >> @@ -57,9 +57,9 @@ public: >>} >> }; >> >> -/// Represents a void* field that needs to be casted back to its dynamic >> type >> -/// for a correct note message. >> -class NeedsCastLocField final : public FieldNode { >> +/// Represents a nonloc::LocAsInteger or void* field, that point to >> objects, but >> +/// needs to be casted back to its dynamic type for a correct note >> message. >> +class NeedsCastLocField : public FieldNode { >>QualType CastBackType; >> >> public: >> @@ -71,7 +71,13 @@ public: >>} >> >>virtual void printPrefix(llvm::raw_ostream &Out) const override { >> -Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; >> +// If this object is a nonloc::LocAsInteger. >> +if (getDecl()->getType()->isIntegerType()) >> + Out << "reinterpret_cast"; >> +// If this pointer's dynamic type is different then it's static type. >> +else >> + Out << "static_cast"; >> +Out << '<' << CastBackType.getAsString() << ">("; >>} >> >>virtual void printNode(llvm::raw_ostream &Out) const override { >> @@ -106,11 +112,12 @@ static llvm::Optional d >> bool FindUninitializedFields::isDereferencableUninit( >> const FieldRegion *FR, FieldChainInfo LocalChain) { >> >> - assert(isDereferencableType(FR->getDecl()->getType()) && >> - "This method only checks dereferencable objects!"); >> - >>SVal V = State->getSVal(FR); >> >> + assert((isDereferencableType(FR->getDecl()->getType()) || >> + V.getAs()) && >> + "This method only checks dereferencable objects!"); >> + >>if (V.isUnknown() || V.getAs()) { >> IsAnyFieldInitialized = true; >> return false; >> @@ -196,13 +203,15 @@ static llvm::Optional d >> >>llvm::SmallSet VisitedRegions; >> >> - // If the static type of the field is a void pointer, we need to cast >> it back >> - // to the dy
r342223 - [analyzer] Attempt to make a windows buildbot happy.
Author: szelethus Date: Fri Sep 14 04:20:16 2018 New Revision: 342223 URL: http://llvm.org/viewvc/llvm-project?rev=342223&view=rev Log: [analyzer] Attempt to make a windows buildbot happy. Got an error that a cast is happening from a pointer type to long, which is smaller. Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=342223&r1=34&r2=342223&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Fri Sep 14 04:20:16 2018 @@ -25,7 +25,7 @@ void fConcreteIntLocTest() { // nonloc::LocAsInteger tests. //===--===// -using intptr_t = long; +using intptr_t = unsigned long long; struct LocAsIntegerTest { intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast(this->ptr)'}} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342225 - [analyzer] Restore final on NeedsCastLocField. NFC
Author: ibiryukov Date: Fri Sep 14 04:28:48 2018 New Revision: 342225 URL: http://llvm.org/viewvc/llvm-project?rev=342225&view=rev Log: [analyzer] Restore final on NeedsCastLocField. NFC To fix compiler warning about non-virtual dtor introduced in r342221. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=342225&r1=342224&r2=342225&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Fri Sep 14 04:28:48 2018 @@ -59,7 +59,7 @@ public: /// Represents a nonloc::LocAsInteger or void* field, that point to objects, but /// needs to be casted back to its dynamic type for a correct note message. -class NeedsCastLocField : public FieldNode { +class NeedsCastLocField final : public FieldNode { QualType CastBackType; public: ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52036: [Analyzer] Use diff_plist in tests, NFC
Szelethus added a comment. Cool! Looks a lot cleaner. https://reviews.llvm.org/D52036 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: r342221 - [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger
I've sent a quick workaround restoring final (r342225) to unbreak our internal buildbots. On Fri, Sep 14, 2018 at 1:20 PM Ilya Biryukov wrote: > Ah, the reason why it does not fire on other inheritors is because they're > final. Any reason to remove final from NeedsCastLocField? > > On Fri, Sep 14, 2018 at 1:17 PM Ilya Biryukov > wrote: > >> This introduced revision introduced a new warning: >> ../tools/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp:62:7: >> warning: '(anonymous namespace)::NeedsCastLocField' has virtual functions >> but non-virtual destructor [-Wnon-virtual-dtor] >> >> Which is turned into an error on our integrates, so it breaks us. Could >> you please take a look? >> A simple workaround would be to make FieldNode destructor virtual. >> Does that make sense? >> >> >> On Fri, Sep 14, 2018 at 12:19 PM Kristof Umann via cfe-commits < >> cfe-commits@lists.llvm.org> wrote: >> >>> Author: szelethus >>> Date: Fri Sep 14 03:18:26 2018 >>> New Revision: 342221 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=342221&view=rev >>> Log: >>> [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger >>> >>> Differential Revision: https://reviews.llvm.org/D49437 >>> >>> Modified: >>> >>> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp >>> >>> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp >>> cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp >>> >>> Modified: >>> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342221&r1=342220&r2=342221&view=diff >>> >>> == >>> --- >>> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp >>> (original) >>> +++ >>> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp >>> Fri Sep 14 03:18:26 2018 >>> @@ -274,15 +274,15 @@ bool FindUninitializedFields::isNonUnion >>>continue; >>> } >>> >>> -if (isDereferencableType(T)) { >>> +SVal V = State->getSVal(FieldVal); >>> + >>> +if (isDereferencableType(T) || V.getAs()) { >>>if (isDereferencableUninit(FR, LocalChain)) >>> ContainsUninitField = true; >>>continue; >>> } >>> >>> if (isPrimitiveType(T)) { >>> - SVal V = State->getSVal(FieldVal); >>> - >>>if (isPrimitiveUninit(V)) { >>> if (addFieldToUninits(LocalChain.add(RegularField(FR >>>ContainsUninitField = true; >>> >>> Modified: >>> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=342221&r1=342220&r2=342221&view=diff >>> >>> == >>> --- >>> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp >>> (original) >>> +++ >>> cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp >>> Fri Sep 14 03:18:26 2018 >>> @@ -57,9 +57,9 @@ public: >>>} >>> }; >>> >>> -/// Represents a void* field that needs to be casted back to its >>> dynamic type >>> -/// for a correct note message. >>> -class NeedsCastLocField final : public FieldNode { >>> +/// Represents a nonloc::LocAsInteger or void* field, that point to >>> objects, but >>> +/// needs to be casted back to its dynamic type for a correct note >>> message. >>> +class NeedsCastLocField : public FieldNode { >>>QualType CastBackType; >>> >>> public: >>> @@ -71,7 +71,13 @@ public: >>>} >>> >>>virtual void printPrefix(llvm::raw_ostream &Out) const override { >>> -Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; >>> +// If this object is a nonloc::LocAsInteger. >>> +if (getDecl()->getType()->isIntegerType()) >>> + Out << "reinterpret_cast"; >>> +// If this pointer's dynamic type is different then it's static >>> type. >>> +else >>> + Out << "static_cast"; >>> +Out << '<' << CastBackType.getAsString() << ">("; >>>} >>> >>>virtual void printNode(llvm::raw_ostream &Out) const override { >>> @@ -106,11 +112,12 @@ static llvm::Optional d >>> bool FindUninitializedFields::isDereferencableUninit( >>> const FieldRegion *FR, FieldChainInfo LocalChain) { >>> >>> - assert(isDereferencableType(FR->getDecl()->getType()) && >>> - "This method only checks dereferencable objects!"); >>> - >>>SVal V = State->getSVal(FR); >>> >>> + assert((isDereferencableType(FR->getDecl()->getType()) || >>> + V.getAs()) && >>> + "This method only checks dereferencable objects!"); >>> + >>>if (V.isUnk
[PATCH] D52078: [clangd] Store preamble macros in dynamic index.
ioeric added inline comments. Comment at: clangd/index/FileIndex.cpp:84 +Merged.insert(Macro); + for (const auto &Sym : Collector.takeSymbols()) +Merged.insert(Sym); ilya-biryukov wrote: > Why make an extra copy of the symbols? Why not add macros to the same builder > used in collector? `index::indexTopLevelDecls` will re-`initialize` the collector. This is safe with the current implementation, but I can imagine it goes wrong when we do more cleanup in the initialization. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52078 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] r342226 - [clangd] Update IndexerMain.cpp file comment after rename. NFC
Author: ibiryukov Date: Fri Sep 14 04:39:05 2018 New Revision: 342226 URL: http://llvm.org/viewvc/llvm-project?rev=342226&view=rev Log: [clangd] Update IndexerMain.cpp file comment after rename. NFC Modified: clang-tools-extra/trunk/clangd/indexer/IndexerMain.cpp Modified: clang-tools-extra/trunk/clangd/indexer/IndexerMain.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/indexer/IndexerMain.cpp?rev=342226&r1=342225&r2=342226&view=diff == --- clang-tools-extra/trunk/clangd/indexer/IndexerMain.cpp (original) +++ clang-tools-extra/trunk/clangd/indexer/IndexerMain.cpp Fri Sep 14 04:39:05 2018 @@ -1,4 +1,4 @@ -//===--- GlobalSymbolBuilderMain.cpp -*- C++-*-===// +//===--- IndexerMain.cpp -*- C++-*-===// // // The LLVM Compiler Infrastructure // ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52078: [clangd] Store preamble macros in dynamic index.
ilya-biryukov added inline comments. Comment at: clangd/index/FileIndex.cpp:84 +Merged.insert(Macro); + for (const auto &Sym : Collector.takeSymbols()) +Merged.insert(Sym); ioeric wrote: > ilya-biryukov wrote: > > Why make an extra copy of the symbols? Why not add macros to the same > > builder used in collector? > `index::indexTopLevelDecls` will re-`initialize` the collector. This is safe > with the current implementation, but I can imagine it goes wrong when we do > more cleanup in the initialization. Sorry, missed the comment about it. And if we do this after `indexTopLevelDecls`, than we'll be calling after the `finish` call. **Sigh**... Doing an extra copy of the symbols here is wasteful and makes the code more complicated than it should be. We have alternatives that could fix this: 1. Move `IndexMacro` logic into `index::indexTopLevelDecls` 2. Move macro collection to `SymbolCollector::finish()` 3. Extract a function that creates a symbol for macro definition, so we don't need to call `handleMacroOccurence` and add can add extra macro symbols after `SymbolCollector` finishes. (1) seems to be the cleanest option, WDYT? Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52078 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52083: [clangd] Store OR iterator children in heap
kbobyrev updated this revision to Diff 165471. kbobyrev marked 3 inline comments as done. kbobyrev edited the summary of this revision. kbobyrev added a comment. Fixed the bug with incorrect assumption of `Children` being sorted (instead of being a heap). This caused a huge overhead (~30%). When I iterate through all children in `consume()` (like before) it's also worse (~18%). Seems like this optimization is not worth (yet?). As soon as we get more proximity paths (and hence more OR iterator children) that might make sense. https://reviews.llvm.org/D52083 Files: clang-tools-extra/clangd/index/dex/Iterator.cpp clang-tools-extra/unittests/clangd/DexTests.cpp Index: clang-tools-extra/unittests/clangd/DexTests.cpp === --- clang-tools-extra/unittests/clangd/DexTests.cpp +++ clang-tools-extra/unittests/clangd/DexTests.cpp @@ -255,20 +255,20 @@ } TEST(DexIterators, StringRepresentation) { - const PostingList L0({4, 7, 8, 20, 42, 100}); + const PostingList L0({0, 1, 8, 20, 42, 100}); const PostingList L1({1, 3, 5, 8, 9}); const PostingList L2({1, 5, 7, 9}); - const PostingList L3({0, 5}); + const PostingList L3({0, 1}); const PostingList L4({0, 1, 5}); const PostingList L5({}); - EXPECT_EQ(llvm::to_string(*(L0.iterator())), "[4]"); + EXPECT_EQ(llvm::to_string(*(L0.iterator())), "[0]"); - auto Nested = - createAnd(createAnd(L1.iterator(), L2.iterator()), -createOr(L3.iterator(), L4.iterator(), L5.iterator())); + auto Nested = createAnd( + createAnd(L1.iterator(), L2.iterator(), L4.iterator(), L0.iterator()), + createOr(L3.iterator(), L5.iterator())); - EXPECT_EQ(llvm::to_string(*Nested), "(& (| [5] [1] [END]) (& [1] [1]))"); + EXPECT_EQ(llvm::to_string(*Nested), "(& (| [1] [END]) (& [1] [1] [1] [1]))"); } TEST(DexIterators, Limit) { Index: clang-tools-extra/clangd/index/dex/Iterator.cpp === --- clang-tools-extra/clangd/index/dex/Iterator.cpp +++ clang-tools-extra/clangd/index/dex/Iterator.cpp @@ -125,69 +125,88 @@ bool ReachedEnd = false; }; +/// Comparator treats END as the largest DocID and ensures that peek() call is +/// valid. +bool Greater(const std::unique_ptr &LHS, + const std::unique_ptr &RHS) { + if (LHS->reachedEnd()) +return true; + if (RHS->reachedEnd()) +return false; + return LHS->peek() > RHS->peek(); +}; + /// Implements Iterator over the union of other iterators. /// /// OrIterator iterates through all items which can be pointed to by at least /// one child. To preserve the sorted order, this iterator always advances the /// child with smallest Child->peek() value. OrIterator becomes exhausted as /// soon as all of its children are exhausted. +/// +/// Invariant: Children are always stored in a min-heap which puts iterators +/// with the smallest DocID to the front. class OrIterator : public Iterator { public: explicit OrIterator(std::vector> AllChildren) : Children(std::move(AllChildren)) { assert(!Children.empty() && "OR iterator should have at least one child."); +// Initialize invariant. +std::make_heap(begin(Children), end(Children), Greater); } - /// Returns true if all children are exhausted. - bool reachedEnd() const override { -return std::all_of(begin(Children), end(Children), - [](const std::unique_ptr &Child) { - return Child->reachedEnd(); - }); - } + /// Returns true if all children are exhausted. Due to the invariant, if the + /// first child has reached the end, all of them have reached the end. + bool reachedEnd() const override { return Children.front()->reachedEnd(); } /// Moves each child pointing to the smallest DocID to the next item. void advance() override { assert(!reachedEnd() && "OR iterator can't advance() at the end."); const auto SmallestID = peek(); -for (const auto &Child : Children) - if (!Child->reachedEnd() && Child->peek() == SmallestID) -Child->advance(); +// The first element always contains Child with the smallest DocID. +while (!Children.front()->reachedEnd() && + Children.front()->peek() == SmallestID) { + Children.front()->advance(); + // Restore invariant. + std::pop_heap(begin(Children), end(Children), Greater); + std::push_heap(begin(Children), end(Children), Greater); +} } /// Advances each child to the next existing element with DocumentID >= ID. void advanceTo(DocID ID) override { assert(!reachedEnd() && "OR iterator can't advanceTo() at the end."); for (const auto &Child : Children) if (!Child->reachedEnd()) Child->advanceTo(ID); +// Restore invariant. +std::make_heap(begin(Children), end(Children), Greater); } /// Returns the element under cursor of the child with smallest Ch
[clang-tools-extra] r342227 - [clangd] NFC: Fix IndexBenchmark CLI arguments handling
Author: omtcyfz Date: Fri Sep 14 05:21:09 2018 New Revision: 342227 URL: http://llvm.org/viewvc/llvm-project?rev=342227&view=rev Log: [clangd] NFC: Fix IndexBenchmark CLI arguments handling Modified: clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp Modified: clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp?rev=342227&r1=342226&r2=342227&view=diff == --- clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp (original) +++ clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp Fri Sep 14 05:21:09 2018 @@ -101,9 +101,11 @@ int main(int argc, char *argv[]) { } IndexFilename = argv[1]; RequestsFilename = argv[2]; - // Trim first two arguments of the benchmark invocation. - argv += 3; - argc -= 3; + // Trim first two arguments of the benchmark invocation and pretend no + // arguments were passed in the first place. + argv[2] = argv[0]; + argv += 2; + argc -= 2; ::benchmark::Initialize(&argc, argv); ::benchmark::RunSpecifiedBenchmarks(); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342228 - [Tooling] JSONCompilationDatabasePlugin infers compile commands for missing files
Author: sammccall Date: Fri Sep 14 05:24:09 2018 New Revision: 342228 URL: http://llvm.org/viewvc/llvm-project?rev=342228&view=rev Log: [Tooling] JSONCompilationDatabasePlugin infers compile commands for missing files Summary: See the existing InterpolatingCompilationDatabase for details on how this works. We've been using this in clangd for a while, the heuristics seem to work well. Reviewers: bkramer Subscribers: ilya-biryukov, ioeric, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D51729 Modified: cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp cfe/trunk/test/Tooling/auto-detect-from-source.cpp Modified: cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp?rev=342228&r1=342227&r2=342228&view=diff == --- cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp (original) +++ cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp Fri Sep 14 05:24:09 2018 @@ -157,13 +157,16 @@ std::vector unescapeCommand return parser.parse(); } +// This plugin locates a nearby compile_command.json file, and also infers +// compile commands for files not present in the database. class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin { std::unique_ptr loadFromDirectory(StringRef Directory, std::string &ErrorMessage) override { SmallString<1024> JSONDatabasePath(Directory); llvm::sys::path::append(JSONDatabasePath, "compile_commands.json"); -return JSONCompilationDatabase::loadFromFile( +auto Base = JSONCompilationDatabase::loadFromFile( JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect); +return Base ? inferMissingCompileCommands(std::move(Base)) : nullptr; } }; Modified: cfe/trunk/test/Tooling/auto-detect-from-source.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/auto-detect-from-source.cpp?rev=342228&r1=342227&r2=342228&view=diff == --- cfe/trunk/test/Tooling/auto-detect-from-source.cpp (original) +++ cfe/trunk/test/Tooling/auto-detect-from-source.cpp Fri Sep 14 05:24:09 2018 @@ -1,8 +1,12 @@ // RUN: rm -rf %t // RUN: mkdir %t -// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\//g' > %t/compile_commands.json +// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -DSECRET=XYZZY -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\//g' > %t/compile_commands.json // RUN: cp "%s" "%t/test.cpp" // RUN: not clang-check "%t/test.cpp" 2>&1 | FileCheck %s -// CHECK: C++ requires -invalid; +// CHECK: XYZZY +SECRET; + +// Copy to a different file, and rely on the command being inferred. +// RUN: cp "%s" "%t/other.cpp" +// RUN: not clang-check "%t/other.cpp" 2>&1 | FileCheck %s ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51729: [Tooling] JSONCompilationDatabasePlugin infers compile commands for missing files
This revision was automatically updated to reflect the committed changes. Closed by commit rC342228: [Tooling] JSONCompilationDatabasePlugin infers compile commands for missing… (authored by sammccall, committed by ). Changed prior to commit: https://reviews.llvm.org/D51729?vs=164192&id=165472#toc Repository: rC Clang https://reviews.llvm.org/D51729 Files: lib/Tooling/JSONCompilationDatabase.cpp test/Tooling/auto-detect-from-source.cpp Index: test/Tooling/auto-detect-from-source.cpp === --- test/Tooling/auto-detect-from-source.cpp +++ test/Tooling/auto-detect-from-source.cpp @@ -1,8 +1,12 @@ // RUN: rm -rf %t // RUN: mkdir %t -// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\//g' > %t/compile_commands.json +// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -DSECRET=XYZZY -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\//g' > %t/compile_commands.json // RUN: cp "%s" "%t/test.cpp" // RUN: not clang-check "%t/test.cpp" 2>&1 | FileCheck %s -// CHECK: C++ requires -invalid; +// CHECK: XYZZY +SECRET; + +// Copy to a different file, and rely on the command being inferred. +// RUN: cp "%s" "%t/other.cpp" +// RUN: not clang-check "%t/other.cpp" 2>&1 | FileCheck %s Index: lib/Tooling/JSONCompilationDatabase.cpp === --- lib/Tooling/JSONCompilationDatabase.cpp +++ lib/Tooling/JSONCompilationDatabase.cpp @@ -157,13 +157,16 @@ return parser.parse(); } +// This plugin locates a nearby compile_command.json file, and also infers +// compile commands for files not present in the database. class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin { std::unique_ptr loadFromDirectory(StringRef Directory, std::string &ErrorMessage) override { SmallString<1024> JSONDatabasePath(Directory); llvm::sys::path::append(JSONDatabasePath, "compile_commands.json"); -return JSONCompilationDatabase::loadFromFile( +auto Base = JSONCompilationDatabase::loadFromFile( JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect); +return Base ? inferMissingCompileCommands(std::move(Base)) : nullptr; } }; Index: test/Tooling/auto-detect-from-source.cpp === --- test/Tooling/auto-detect-from-source.cpp +++ test/Tooling/auto-detect-from-source.cpp @@ -1,8 +1,12 @@ // RUN: rm -rf %t // RUN: mkdir %t -// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\//g' > %t/compile_commands.json +// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -DSECRET=XYZZY -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\//g' > %t/compile_commands.json // RUN: cp "%s" "%t/test.cpp" // RUN: not clang-check "%t/test.cpp" 2>&1 | FileCheck %s -// CHECK: C++ requires -invalid; +// CHECK: XYZZY +SECRET; + +// Copy to a different file, and rely on the command being inferred. +// RUN: cp "%s" "%t/other.cpp" +// RUN: not clang-check "%t/other.cpp" 2>&1 | FileCheck %s Index: lib/Tooling/JSONCompilationDatabase.cpp === --- lib/Tooling/JSONCompilationDatabase.cpp +++ lib/Tooling/JSONCompilationDatabase.cpp @@ -157,13 +157,16 @@ return parser.parse(); } +// This plugin locates a nearby compile_command.json file, and also infers +// compile commands for files not present in the database. class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin { std::unique_ptr loadFromDirectory(StringRef Directory, std::string &ErrorMessage) override { SmallString<1024> JSONDatabasePath(Directory); llvm::sys::path::append(JSONDatabasePath, "compile_commands.json"); -return JSONCompilationDatabase::loadFromFile( +auto Base = JSONCompilationDatabase::loadFromFile( JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect); +return Base ? inferMissingCompileCommands(std::move(Base)) : nullptr; } }; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52066: [Driver] Fix missing MultiArch include dir on powerpcspe
kristina accepted this revision. kristina added a comment. This revision is now accepted and ready to land. LGTM. In the future please make sure you supply all patches with context (ie. `-U9`), without context they may be harder to review and more importantly `patch` may mess up. Repository: rC Clang https://reviews.llvm.org/D52066 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] r342229 - [clangd] Don't double-infer compile commands after r342228
Author: sammccall Date: Fri Sep 14 05:32:08 2018 New Revision: 342229 URL: http://llvm.org/viewvc/llvm-project?rev=342229&view=rev Log: [clangd] Don't double-infer compile commands after r342228 Modified: clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp Modified: clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp?rev=342229&r1=342228&r2=342229&view=diff == --- clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp (original) +++ clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp Fri Sep 14 05:32:08 2018 @@ -95,8 +95,6 @@ DirectoryBasedGlobalCompilationDatabase: return CachedIt->second.get(); std::string Error = ""; auto CDB = tooling::CompilationDatabase::loadFromDirectory(Dir, Error); - if (CDB) -CDB = tooling::inferMissingCompileCommands(std::move(CDB)); auto Result = CDB.get(); CompilationDatabases.insert(std::make_pair(Dir, std::move(CDB))); return Result; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] r342230 - [clangd] Don't override the preamble while completing inside it, it doesn't work.
Author: sammccall Date: Fri Sep 14 05:36:06 2018 New Revision: 342230 URL: http://llvm.org/viewvc/llvm-project?rev=342230&view=rev Log: [clangd] Don't override the preamble while completing inside it, it doesn't work. Summary: To stay fast, enable single-file-mode instead. This is fine since completions in the preamble are simple. The net effect for now is to suppress the spurious TopLevel completions when completing inside the preamble. Once Sema has include directive completion, this will be more important. Reviewers: ilya-biryukov Subscribers: ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D52071 Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=342230&r1=342229&r2=342230&view=diff == --- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original) +++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Fri Sep 14 05:36:06 2018 @@ -40,6 +40,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Index/USRGeneration.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/Sema.h" #include "clang/Tooling/Core/Replacement.h" @@ -1053,11 +1054,19 @@ bool semaCodeComplete(std::unique_ptrgetLangOpts(), ContentsBuffer.get(), 0).Size > + *Offset; // NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise // the remapped buffers do not get freed. auto Clang = prepareCompilerInstance( - std::move(CI), Input.Preamble, std::move(ContentsBuffer), - std::move(Input.PCHs), std::move(Input.VFS), DummyDiagsConsumer); + std::move(CI), CompletingInPreamble ? nullptr : Input.Preamble, + std::move(ContentsBuffer), std::move(Input.PCHs), std::move(Input.VFS), + DummyDiagsConsumer); + Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble; Clang->setCodeCompletionConsumer(Consumer.release()); SyntaxOnlyAction Action; Modified: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp?rev=342230&r1=342229&r2=342230&view=diff == --- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp (original) +++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Fri Sep 14 05:36:06 2018 @@ -657,6 +657,22 @@ TEST(CompletionTest, IndexSuppressesPrea UnorderedElementsAre(Named("local"), Named("preamble"))); } +// This verifies that we get normal preprocessor completions in the preamble. +// This is a regression test for an old bug: if we override the preamble and +// try to complete inside it, clang kicks our completion point just outside the +// preamble, resulting in always getting top-level completions. +TEST(CompletionTest, CompletionInPreamble) { + EXPECT_THAT(completions(R"cpp( +#ifnd^ef FOO_H_ +#define BAR_H_ +#include +int foo() {} +#endif +)cpp") + .Completions, + ElementsAre(Named("ifndef"))); +}; + TEST(CompletionTest, DynamicIndexMultiFile) { MockFSProvider FS; MockCompilationDatabase CDB; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52071: [clangd] Don't override the preamble while completing inside it, it doesn't work.
This revision was automatically updated to reflect the committed changes. Closed by commit rL342230: [clangd] Don't override the preamble while completing inside it, it doesn't… (authored by sammccall, committed by ). Herald added a subscriber: llvm-commits. Repository: rL LLVM https://reviews.llvm.org/D52071 Files: clang-tools-extra/trunk/clangd/CodeComplete.cpp clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp === --- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp +++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp @@ -657,6 +657,22 @@ UnorderedElementsAre(Named("local"), Named("preamble"))); } +// This verifies that we get normal preprocessor completions in the preamble. +// This is a regression test for an old bug: if we override the preamble and +// try to complete inside it, clang kicks our completion point just outside the +// preamble, resulting in always getting top-level completions. +TEST(CompletionTest, CompletionInPreamble) { + EXPECT_THAT(completions(R"cpp( +#ifnd^ef FOO_H_ +#define BAR_H_ +#include +int foo() {} +#endif +)cpp") + .Completions, + ElementsAre(Named("ifndef"))); +}; + TEST(CompletionTest, DynamicIndexMultiFile) { MockFSProvider FS; MockCompilationDatabase CDB; Index: clang-tools-extra/trunk/clangd/CodeComplete.cpp === --- clang-tools-extra/trunk/clangd/CodeComplete.cpp +++ clang-tools-extra/trunk/clangd/CodeComplete.cpp @@ -40,6 +40,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Index/USRGeneration.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/Sema.h" #include "clang/Tooling/Core/Replacement.h" @@ -1053,11 +1054,19 @@ // We reuse the preamble whether it's valid or not. This is a // correctness/performance tradeoff: building without a preamble is slow, and // completion is latency-sensitive. + // However, if we're completing *inside* the preamble section of the draft, + // overriding the preamble will break sema completion. Fortunately we can just + // skip all includes in this case; these completions are really simple. + bool CompletingInPreamble = + ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0).Size > + *Offset; // NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise // the remapped buffers do not get freed. auto Clang = prepareCompilerInstance( - std::move(CI), Input.Preamble, std::move(ContentsBuffer), - std::move(Input.PCHs), std::move(Input.VFS), DummyDiagsConsumer); + std::move(CI), CompletingInPreamble ? nullptr : Input.Preamble, + std::move(ContentsBuffer), std::move(Input.PCHs), std::move(Input.VFS), + DummyDiagsConsumer); + Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble; Clang->setCodeCompletionConsumer(Consumer.release()); SyntaxOnlyAction Action; Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp === --- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp +++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp @@ -657,6 +657,22 @@ UnorderedElementsAre(Named("local"), Named("preamble"))); } +// This verifies that we get normal preprocessor completions in the preamble. +// This is a regression test for an old bug: if we override the preamble and +// try to complete inside it, clang kicks our completion point just outside the +// preamble, resulting in always getting top-level completions. +TEST(CompletionTest, CompletionInPreamble) { + EXPECT_THAT(completions(R"cpp( +#ifnd^ef FOO_H_ +#define BAR_H_ +#include +int foo() {} +#endif +)cpp") + .Completions, + ElementsAre(Named("ifndef"))); +}; + TEST(CompletionTest, DynamicIndexMultiFile) { MockFSProvider FS; MockCompilationDatabase CDB; Index: clang-tools-extra/trunk/clangd/CodeComplete.cpp === --- clang-tools-extra/trunk/clangd/CodeComplete.cpp +++ clang-tools-extra/trunk/clangd/CodeComplete.cpp @@ -40,6 +40,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Index/USRGeneration.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/Sema.h" #include "clang/Tooling/Core/Replacement.h" @@ -1053,11 +1054,19 @@ // We reuse the preamble whether it's valid or not. This is a // correctness/performance tradeoff: building without a preamble is slow, and //
[PATCH] D52071: [clangd] Don't override the preamble while completing inside it, it doesn't work.
This revision was automatically updated to reflect the committed changes. Closed by commit rCTE342230: [clangd] Don't override the preamble while completing inside it, it doesn't… (authored by sammccall, committed by ). Changed prior to commit: https://reviews.llvm.org/D52071?vs=165421&id=165474#toc Repository: rL LLVM https://reviews.llvm.org/D52071 Files: clangd/CodeComplete.cpp unittests/clangd/CodeCompleteTests.cpp Index: clangd/CodeComplete.cpp === --- clangd/CodeComplete.cpp +++ clangd/CodeComplete.cpp @@ -40,6 +40,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Index/USRGeneration.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/Sema.h" #include "clang/Tooling/Core/Replacement.h" @@ -1053,11 +1054,19 @@ // We reuse the preamble whether it's valid or not. This is a // correctness/performance tradeoff: building without a preamble is slow, and // completion is latency-sensitive. + // However, if we're completing *inside* the preamble section of the draft, + // overriding the preamble will break sema completion. Fortunately we can just + // skip all includes in this case; these completions are really simple. + bool CompletingInPreamble = + ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0).Size > + *Offset; // NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise // the remapped buffers do not get freed. auto Clang = prepareCompilerInstance( - std::move(CI), Input.Preamble, std::move(ContentsBuffer), - std::move(Input.PCHs), std::move(Input.VFS), DummyDiagsConsumer); + std::move(CI), CompletingInPreamble ? nullptr : Input.Preamble, + std::move(ContentsBuffer), std::move(Input.PCHs), std::move(Input.VFS), + DummyDiagsConsumer); + Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble; Clang->setCodeCompletionConsumer(Consumer.release()); SyntaxOnlyAction Action; Index: unittests/clangd/CodeCompleteTests.cpp === --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -657,6 +657,22 @@ UnorderedElementsAre(Named("local"), Named("preamble"))); } +// This verifies that we get normal preprocessor completions in the preamble. +// This is a regression test for an old bug: if we override the preamble and +// try to complete inside it, clang kicks our completion point just outside the +// preamble, resulting in always getting top-level completions. +TEST(CompletionTest, CompletionInPreamble) { + EXPECT_THAT(completions(R"cpp( +#ifnd^ef FOO_H_ +#define BAR_H_ +#include +int foo() {} +#endif +)cpp") + .Completions, + ElementsAre(Named("ifndef"))); +}; + TEST(CompletionTest, DynamicIndexMultiFile) { MockFSProvider FS; MockCompilationDatabase CDB; Index: clangd/CodeComplete.cpp === --- clangd/CodeComplete.cpp +++ clangd/CodeComplete.cpp @@ -40,6 +40,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Index/USRGeneration.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/Sema.h" #include "clang/Tooling/Core/Replacement.h" @@ -1053,11 +1054,19 @@ // We reuse the preamble whether it's valid or not. This is a // correctness/performance tradeoff: building without a preamble is slow, and // completion is latency-sensitive. + // However, if we're completing *inside* the preamble section of the draft, + // overriding the preamble will break sema completion. Fortunately we can just + // skip all includes in this case; these completions are really simple. + bool CompletingInPreamble = + ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0).Size > + *Offset; // NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise // the remapped buffers do not get freed. auto Clang = prepareCompilerInstance( - std::move(CI), Input.Preamble, std::move(ContentsBuffer), - std::move(Input.PCHs), std::move(Input.VFS), DummyDiagsConsumer); + std::move(CI), CompletingInPreamble ? nullptr : Input.Preamble, + std::move(ContentsBuffer), std::move(Input.PCHs), std::move(Input.VFS), + DummyDiagsConsumer); + Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble; Clang->setCodeCompletionConsumer(Consumer.release()); SyntaxOnlyAction Action; Index: unittests/clangd/CodeCompleteTests.cpp === --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -657,6 +65
[PATCH] D52066: [Driver] Fix missing MultiArch include dir on powerpcspe
This revision was automatically updated to reflect the committed changes. Closed by commit rC342231: [Driver] Fix missing MultiArch include dir on powerpcspe (authored by kristina, committed by ). Repository: rL LLVM https://reviews.llvm.org/D52066 Files: lib/Driver/ToolChains/Linux.cpp Index: lib/Driver/ToolChains/Linux.cpp === --- lib/Driver/ToolChains/Linux.cpp +++ lib/Driver/ToolChains/Linux.cpp @@ -699,7 +699,8 @@ "/usr/include/mips64el-linux-gnu", "/usr/include/mips64el-linux-gnuabi64"}; const StringRef PPCMultiarchIncludeDirs[] = { - "/usr/include/powerpc-linux-gnu"}; + "/usr/include/powerpc-linux-gnu", + "/usr/include/powerpc-linux-gnuspe"}; const StringRef PPC64MultiarchIncludeDirs[] = { "/usr/include/powerpc64-linux-gnu"}; const StringRef PPC64LEMultiarchIncludeDirs[] = { Index: lib/Driver/ToolChains/Linux.cpp === --- lib/Driver/ToolChains/Linux.cpp +++ lib/Driver/ToolChains/Linux.cpp @@ -699,7 +699,8 @@ "/usr/include/mips64el-linux-gnu", "/usr/include/mips64el-linux-gnuabi64"}; const StringRef PPCMultiarchIncludeDirs[] = { - "/usr/include/powerpc-linux-gnu"}; + "/usr/include/powerpc-linux-gnu", + "/usr/include/powerpc-linux-gnuspe"}; const StringRef PPC64MultiarchIncludeDirs[] = { "/usr/include/powerpc64-linux-gnu"}; const StringRef PPC64LEMultiarchIncludeDirs[] = { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52066: [Driver] Fix missing MultiArch include dir on powerpcspe
This revision was automatically updated to reflect the committed changes. Closed by commit rL342231: [Driver] Fix missing MultiArch include dir on powerpcspe (authored by kristina, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D52066?vs=165393&id=165477#toc Repository: rL LLVM https://reviews.llvm.org/D52066 Files: cfe/trunk/lib/Driver/ToolChains/Linux.cpp Index: cfe/trunk/lib/Driver/ToolChains/Linux.cpp === --- cfe/trunk/lib/Driver/ToolChains/Linux.cpp +++ cfe/trunk/lib/Driver/ToolChains/Linux.cpp @@ -699,7 +699,8 @@ "/usr/include/mips64el-linux-gnu", "/usr/include/mips64el-linux-gnuabi64"}; const StringRef PPCMultiarchIncludeDirs[] = { - "/usr/include/powerpc-linux-gnu"}; + "/usr/include/powerpc-linux-gnu", + "/usr/include/powerpc-linux-gnuspe"}; const StringRef PPC64MultiarchIncludeDirs[] = { "/usr/include/powerpc64-linux-gnu"}; const StringRef PPC64LEMultiarchIncludeDirs[] = { Index: cfe/trunk/lib/Driver/ToolChains/Linux.cpp === --- cfe/trunk/lib/Driver/ToolChains/Linux.cpp +++ cfe/trunk/lib/Driver/ToolChains/Linux.cpp @@ -699,7 +699,8 @@ "/usr/include/mips64el-linux-gnu", "/usr/include/mips64el-linux-gnuabi64"}; const StringRef PPCMultiarchIncludeDirs[] = { - "/usr/include/powerpc-linux-gnu"}; + "/usr/include/powerpc-linux-gnu", + "/usr/include/powerpc-linux-gnuspe"}; const StringRef PPC64MultiarchIncludeDirs[] = { "/usr/include/powerpc64-linux-gnu"}; const StringRef PPC64LEMultiarchIncludeDirs[] = { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342231 - [Driver] Fix missing MultiArch include dir on powerpcspe
Author: kristina Date: Fri Sep 14 05:42:13 2018 New Revision: 342231 URL: http://llvm.org/viewvc/llvm-project?rev=342231&view=rev Log: [Driver] Fix missing MultiArch include dir on powerpcspe On powerpc-linux-gnuspe, the header files are located in their own include directory named /usr/lib/powerpc-linux-gnuspe, so add this directory to PPCMultiarchIncludeDirs. Patch by glaubitz (John Paul Adrian Glaubitz) Differential Revision: https://reviews.llvm.org/D52066 Modified: cfe/trunk/lib/Driver/ToolChains/Linux.cpp Modified: cfe/trunk/lib/Driver/ToolChains/Linux.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/Linux.cpp?rev=342231&r1=342230&r2=342231&view=diff == --- cfe/trunk/lib/Driver/ToolChains/Linux.cpp (original) +++ cfe/trunk/lib/Driver/ToolChains/Linux.cpp Fri Sep 14 05:42:13 2018 @@ -699,7 +699,8 @@ void Linux::AddClangSystemIncludeArgs(co "/usr/include/mips64el-linux-gnu", "/usr/include/mips64el-linux-gnuabi64"}; const StringRef PPCMultiarchIncludeDirs[] = { - "/usr/include/powerpc-linux-gnu"}; + "/usr/include/powerpc-linux-gnu", + "/usr/include/powerpc-linux-gnuspe"}; const StringRef PPC64MultiarchIncludeDirs[] = { "/usr/include/powerpc64-linux-gnu"}; const StringRef PPC64LEMultiarchIncludeDirs[] = { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [clang-tools-extra] r342227 - [clangd] NFC: Fix IndexBenchmark CLI arguments handling
On Fri, Sep 14, 2018 at 3:21 PM, Kirill Bobyrev via cfe-commits wrote: > Author: omtcyfz > Date: Fri Sep 14 05:21:09 2018 > New Revision: 342227 > > URL: http://llvm.org/viewvc/llvm-project?rev=342227&view=rev > Log: > [clangd] NFC: Fix IndexBenchmark CLI arguments handling > > Modified: > clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp > > Modified: clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp?rev=342227&r1=342226&r2=342227&view=diff > == > --- clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp (original) > +++ clang-tools-extra/trunk/clangd/benchmarks/IndexBenchmark.cpp Fri Sep 14 > 05:21:09 2018 > @@ -101,9 +101,11 @@ int main(int argc, char *argv[]) { >} >IndexFilename = argv[1]; >RequestsFilename = argv[2]; > - // Trim first two arguments of the benchmark invocation. > - argv += 3; > - argc -= 3; > + // Trim first two arguments of the benchmark invocation and pretend no > + // arguments were passed in the first place. > + argv[2] = argv[0]; > + argv += 2; > + argc -= 2; >::benchmark::Initialize(&argc, argv); Passing-by thought: why is this being done in *this* order? Why not first let the ::benchmark::Initialize() consume it's flags first? >::benchmark::RunSpecifiedBenchmarks(); > } > Roman. > ___ > 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
r342232 - [VFS] vfs::directory_iterator yields path and file type instead of full Status
Author: sammccall Date: Fri Sep 14 05:47:38 2018 New Revision: 342232 URL: http://llvm.org/viewvc/llvm-project?rev=342232&view=rev Log: [VFS] vfs::directory_iterator yields path and file type instead of full Status Summary: Most callers I can find are using only `getName()`. Type is used by the recursive iterator. Now we don't have to call stat() on every listed file (on most platforms). Exceptions are e.g. Solaris where readdir() doesn't include type information. On those platforms we'll still stat() - see D51918. The result is significantly faster (stat() can be slow). My motivation: this may allow us to improve clang IO on large TUs with long include search paths. Caching readdir() results may allow us to skip many stat() and open() operations on nonexistent files. Reviewers: bkramer Subscribers: fedor.sergeev, cfe-commits Differential Revision: https://reviews.llvm.org/D51921 Modified: cfe/trunk/include/clang/Basic/VirtualFileSystem.h cfe/trunk/lib/Basic/VirtualFileSystem.cpp cfe/trunk/lib/Driver/ToolChains/BareMetal.cpp cfe/trunk/lib/Driver/ToolChains/Gnu.cpp cfe/trunk/lib/Frontend/CompilerInstance.cpp cfe/trunk/lib/Frontend/FrontendAction.cpp cfe/trunk/lib/Lex/HeaderSearch.cpp cfe/trunk/lib/Lex/ModuleMap.cpp cfe/trunk/lib/Lex/PPLexerChange.cpp cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp Modified: cfe/trunk/include/clang/Basic/VirtualFileSystem.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/VirtualFileSystem.h?rev=342232&r1=342231&r2=342232&view=diff == --- cfe/trunk/include/clang/Basic/VirtualFileSystem.h (original) +++ cfe/trunk/include/clang/Basic/VirtualFileSystem.h Fri Sep 14 05:47:38 2018 @@ -126,6 +126,21 @@ public: virtual std::error_code close() = 0; }; +/// A member of a directory, yielded by a directory_iterator. +/// Only information available on most platforms is included. +class directory_entry { + std::string Path; + llvm::sys::fs::file_type Type; + +public: + directory_entry() = default; + directory_entry(std::string Path, llvm::sys::fs::file_type Type) + : Path(std::move(Path)), Type(Type) {} + + llvm::StringRef path() const { return Path; } + llvm::sys::fs::file_type type() const { return Type; } +}; + namespace detail { /// An interface for virtual file systems to provide an iterator over the @@ -134,10 +149,10 @@ struct DirIterImpl { virtual ~DirIterImpl(); /// Sets \c CurrentEntry to the next entry in the directory on success, - /// or returns a system-defined \c error_code. + /// to directory_entry() at end, or returns a system-defined \c error_code. virtual std::error_code increment() = 0; - Status CurrentEntry; + directory_entry CurrentEntry; }; } // namespace detail @@ -151,7 +166,7 @@ public: directory_iterator(std::shared_ptr I) : Impl(std::move(I)) { assert(Impl.get() != nullptr && "requires non-null implementation"); -if (!Impl->CurrentEntry.isStatusKnown()) +if (Impl->CurrentEntry.path().empty()) Impl.reset(); // Normalize the end iterator to Impl == nullptr. } @@ -162,17 +177,17 @@ public: directory_iterator &increment(std::error_code &EC) { assert(Impl && "attempting to increment past end"); EC = Impl->increment(); -if (!Impl->CurrentEntry.isStatusKnown()) +if (Impl->CurrentEntry.path().empty()) Impl.reset(); // Normalize the end iterator to Impl == nullptr. return *this; } - const Status &operator*() const { return Impl->CurrentEntry; } - const Status *operator->() const { return &Impl->CurrentEntry; } + const directory_entry &operator*() const { return Impl->CurrentEntry; } + const directory_entry *operator->() const { return &Impl->CurrentEntry; } bool operator==(const directory_iterator &RHS) const { if (Impl && RHS.Impl) - return Impl->CurrentEntry.equivalent(RHS.Impl->CurrentEntry); + return Impl->CurrentEntry.path() == RHS.Impl->CurrentEntry.path(); return !Impl && !RHS.Impl; } bool operator!=(const directory_iterator &RHS) const { @@ -201,8 +216,8 @@ public: /// Equivalent to operator++, with an error code. recursive_directory_iterator &increment(std::error_code &EC); - const Status &operator*() const { return *State->top(); } - const Status *operator->() const { return &*State->top(); } + const directory_entry &operator*() const { return *State->top(); } + const directory_entry *operator->() const { return &*State->top(); } bool operator==(const recursive_directory_iterator &Other) const { return State == Other.State; // identity Modified: cfe/trunk/lib/Basic/VirtualFileSystem.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/VirtualFileSystem.cpp?rev=342232&r1=342231&r2=342232&view=diff == --- cfe/trunk/lib/Basic/VirtualFileSystem.cpp (origin
[PATCH] D51921: [VFS] vfs::directory_iterator yields path and file type instead of full Status
This revision was automatically updated to reflect the committed changes. Closed by commit rC342232: [VFS] vfs::directory_iterator yields path and file type instead of full Status (authored by sammccall, committed by ). Changed prior to commit: https://reviews.llvm.org/D51921?vs=165250&id=165480#toc Repository: rC Clang https://reviews.llvm.org/D51921 Files: include/clang/Basic/VirtualFileSystem.h lib/Basic/VirtualFileSystem.cpp lib/Driver/ToolChains/BareMetal.cpp lib/Driver/ToolChains/Gnu.cpp lib/Frontend/CompilerInstance.cpp lib/Frontend/FrontendAction.cpp lib/Lex/HeaderSearch.cpp lib/Lex/ModuleMap.cpp lib/Lex/PPLexerChange.cpp unittests/Basic/VirtualFileSystemTest.cpp Index: include/clang/Basic/VirtualFileSystem.h === --- include/clang/Basic/VirtualFileSystem.h +++ include/clang/Basic/VirtualFileSystem.h @@ -126,18 +126,33 @@ virtual std::error_code close() = 0; }; +/// A member of a directory, yielded by a directory_iterator. +/// Only information available on most platforms is included. +class directory_entry { + std::string Path; + llvm::sys::fs::file_type Type; + +public: + directory_entry() = default; + directory_entry(std::string Path, llvm::sys::fs::file_type Type) + : Path(std::move(Path)), Type(Type) {} + + llvm::StringRef path() const { return Path; } + llvm::sys::fs::file_type type() const { return Type; } +}; + namespace detail { /// An interface for virtual file systems to provide an iterator over the /// (non-recursive) contents of a directory. struct DirIterImpl { virtual ~DirIterImpl(); /// Sets \c CurrentEntry to the next entry in the directory on success, - /// or returns a system-defined \c error_code. + /// to directory_entry() at end, or returns a system-defined \c error_code. virtual std::error_code increment() = 0; - Status CurrentEntry; + directory_entry CurrentEntry; }; } // namespace detail @@ -151,7 +166,7 @@ directory_iterator(std::shared_ptr I) : Impl(std::move(I)) { assert(Impl.get() != nullptr && "requires non-null implementation"); -if (!Impl->CurrentEntry.isStatusKnown()) +if (Impl->CurrentEntry.path().empty()) Impl.reset(); // Normalize the end iterator to Impl == nullptr. } @@ -162,17 +177,17 @@ directory_iterator &increment(std::error_code &EC) { assert(Impl && "attempting to increment past end"); EC = Impl->increment(); -if (!Impl->CurrentEntry.isStatusKnown()) +if (Impl->CurrentEntry.path().empty()) Impl.reset(); // Normalize the end iterator to Impl == nullptr. return *this; } - const Status &operator*() const { return Impl->CurrentEntry; } - const Status *operator->() const { return &Impl->CurrentEntry; } + const directory_entry &operator*() const { return Impl->CurrentEntry; } + const directory_entry *operator->() const { return &Impl->CurrentEntry; } bool operator==(const directory_iterator &RHS) const { if (Impl && RHS.Impl) - return Impl->CurrentEntry.equivalent(RHS.Impl->CurrentEntry); + return Impl->CurrentEntry.path() == RHS.Impl->CurrentEntry.path(); return !Impl && !RHS.Impl; } bool operator!=(const directory_iterator &RHS) const { @@ -201,8 +216,8 @@ /// Equivalent to operator++, with an error code. recursive_directory_iterator &increment(std::error_code &EC); - const Status &operator*() const { return *State->top(); } - const Status *operator->() const { return &*State->top(); } + const directory_entry &operator*() const { return *State->top(); } + const directory_entry *operator->() const { return &*State->top(); } bool operator==(const recursive_directory_iterator &Other) const { return State == Other.State; // identity Index: lib/Basic/VirtualFileSystem.cpp === --- lib/Basic/VirtualFileSystem.cpp +++ lib/Basic/VirtualFileSystem.cpp @@ -315,27 +315,16 @@ public: RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) { -if (Iter != llvm::sys::fs::directory_iterator()) { - llvm::sys::fs::file_status S; - std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true); - CurrentEntry = Status::copyWithNewName(S, Iter->path()); - if (!EC) -EC = ErrorCode; -} +if (Iter != llvm::sys::fs::directory_iterator()) + CurrentEntry = directory_entry(Iter->path(), Iter->type()); } std::error_code increment() override { std::error_code EC; Iter.increment(EC); -if (Iter == llvm::sys::fs::directory_iterator()) { - CurrentEntry = Status(); -} else { - llvm::sys::fs::file_status S; - std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true); - CurrentEntry = Status::copyWithNewName(S, Iter->path()); - if (!EC) -EC = ErrorCode; -} +CurrentEntry = (Iter == llvm::sys::fs::directory_iterator()
[PATCH] D52089: [clangd] Get rid of AST matchers in SymbolCollector. NFC
ioeric created this revision. ioeric added reviewers: ilya-biryukov, kadircet. Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52089 Files: clangd/index/SymbolCollector.cpp Index: clangd/index/SymbolCollector.cpp === --- clangd/index/SymbolCollector.cpp +++ clangd/index/SymbolCollector.cpp @@ -15,12 +15,16 @@ #include "Logger.h" #include "SourceCode.h" #include "URI.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" #include "clang/Index/IndexSymbol.h" #include "clang/Index/USRGeneration.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -235,6 +239,13 @@ return static_cast(static_cast(RefKind::All) & Roles); } +template bool explicitTemplateSpecialization(const NamedDecl &ND) { + if (const auto *TD = llvm::dyn_cast(&ND)) +if (TD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return true; + return false; +} + } // namespace SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {} @@ -271,21 +282,33 @@ // FunctionDecl, BlockDecl, ObjCMethodDecl and OMPDeclareReductionDecl. // FIXME: Need a matcher for ExportDecl in order to include symbols declared // within an export. - auto InNonLocalContext = hasDeclContext(anyOf( - translationUnitDecl(), namespaceDecl(), linkageSpecDecl(), recordDecl(), - enumDecl(), objcProtocolDecl(), objcInterfaceDecl(), objcCategoryDecl(), - objcCategoryImplDecl(), objcImplementationDecl())); - // Don't index template specializations and expansions in main files. - auto IsSpecialization = - anyOf(functionDecl(isExplicitTemplateSpecialization()), -cxxRecordDecl(isExplicitTemplateSpecialization()), -varDecl(isExplicitTemplateSpecialization())); - if (match(decl(allOf(unless(isExpansionInMainFile()), InNonLocalContext, - unless(IsSpecialization))), -ND, ASTCtx) - .empty()) + const auto *DeclCtx = ND.getDeclContext(); + switch (DeclCtx->getDeclKind()) { + case Decl::TranslationUnit: + case Decl::Namespace: + case Decl::LinkageSpec: + case Decl::Enum: + case Decl::ObjCProtocol: + case Decl::ObjCInterface: + case Decl::ObjCCategory: + case Decl::ObjCCategoryImpl: + case Decl::ObjCImplementation: +break; + default: +// Record has a few derivations (e.g. CXXRecord, Class specialization), it's +// easier to cast. +if (!llvm::isa(DeclCtx)) + return false; + } + if (explicitTemplateSpecialization(ND) || + explicitTemplateSpecialization(ND) || + explicitTemplateSpecialization(ND)) return false; + const auto &SM = ASTCtx.getSourceManager(); + // Skip decls in the main file. + if (SM.isInMainFile(SM.getExpansionLoc(ND.getBeginLoc( +return false; // Avoid indexing internal symbols in protobuf generated headers. if (isPrivateProtoDecl(ND)) return false; Index: clangd/index/SymbolCollector.cpp === --- clangd/index/SymbolCollector.cpp +++ clangd/index/SymbolCollector.cpp @@ -15,12 +15,16 @@ #include "Logger.h" #include "SourceCode.h" #include "URI.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" #include "clang/Index/IndexSymbol.h" #include "clang/Index/USRGeneration.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -235,6 +239,13 @@ return static_cast(static_cast(RefKind::All) & Roles); } +template bool explicitTemplateSpecialization(const NamedDecl &ND) { + if (const auto *TD = llvm::dyn_cast(&ND)) +if (TD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return true; + return false; +} + } // namespace SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {} @@ -271,21 +282,33 @@ // FunctionDecl, BlockDecl, ObjCMethodDecl and OMPDeclareReductionDecl. // FIXME: Need a matcher for ExportDecl in order to include symbols declared // within an export. - auto InNonLocalContext = hasDeclContext(anyOf( - translationUnitDecl(), namespaceDecl(), linkageSpecDecl(), recordDecl(), - enumDecl(), objcProtocolDecl(), objcInterfaceDecl(), objcCategoryDecl(), - objcCategoryImplDecl(), objcImplementationDecl())); - // Don't index template specializations and expansions in main f
[PATCH] D52066: [Driver] Fix missing MultiArch include dir on powerpcspe
lebedev.ri added inline comments. Comment at: cfe/trunk/lib/Driver/ToolChains/Linux.cpp:701 "/usr/include/mips64el-linux-gnuabi64"}; const StringRef PPCMultiarchIncludeDirs[] = { + "/usr/include/powerpc-linux-gnu", This is probably missing test coverage? It //seems//, some of these are tested, but not all: ``` clang/test$ find -iname include | grep tree | wc -l 112 ``` Repository: rL LLVM https://reviews.llvm.org/D52066 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52066: [Driver] Fix missing MultiArch include dir on powerpcspe
glaubitz added a comment. Not sure how this is supposed to be tested as this requires a proper Debian powerpcspe chroot. I also checked saw that not all mips64 include paths are covered by the testsuite. Repository: rL LLVM https://reviews.llvm.org/D52066 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52076: [CodeComplete] Add completions for filenames in #include directives.
sammccall added a comment. Thanks a lot, great comments! I haven't made changes yet (I will) but there's a few questions to work out first... Comment at: lib/Lex/Lexer.cpp:1931 + StringRef PartialPath(AfterQuote, CurPtr - 1 - AfterQuote); + auto Slash = PartialPath.rfind('/'); + StringRef Dir = ilya-biryukov wrote: > It's also valid to use `\` for path separators on Windows, maybe also handle > those? > Clang also supports this when running e.g. `clang-cl /c foo.cpp`. Ah yuck, that's true (for some value of "valid"). Pre-C++11 it was explicitly UB... So if a codebase consistently uses backslashes, we're going to break that style at least sometimes: we can't know whether to complete `#include `? Anything else is going to be fiddly, probably only help a few users a little bit, and leave edge cases. Comment at: lib/Lex/Lexer.cpp:2065 +if (C == '\n' || C == '\r' ||// Newline. +(C == 0 && (CurPtr - 1 == BufferEnd))) { // End of file. // If the filename is unterminated, then it must just be a lone < ilya-biryukov wrote: > Does that mean we're losing completion at the end of file? > Not sure if it's a big deal. The only common pattern I can come up with is > starting with an empty file and writing: > ``` > #include "^ > ``` > > Should we handle that? WDYT? Ah no, it doesn't, though I thought so at first. First: the address of `C` is `CurPtr-1` (getAndAdvanceChar is in spirit `return *CurPtr++`). Second: the buffer is null-terminated one-past-the-end (`*BufferEnd == 0`) and **also** has an embedded null at the completion point. So when completing at EOF it looks like: ``` # i n c l u d e < a \0 \0 ^C ^CurPtr ^BufferStart^BufPtr^BufferEnd ``` and we hit the case below. We only hit this case if we never saw a completion point. Comment at: lib/Sema/SemaCodeComplete.cpp:8021 +// Directory completion is up to the slash, e.g. ' : '"'); +auto R = SeenResults.insert(TypedChunk); ilya-biryukov wrote: > Could we avoid adding `/`, `>` and `"` if it's currently missing? > Otherwise it'll be annoying for editors that auto-add closing quotes and > completions when editing existing includes, i.e. > ``` > // It's cool if we complete bar.h" (with closing quote) here: > #include "foo/^ > // It's annoying if we complete an extra closing quote here: > #include "foo/^" > ``` Don't editors that add quotes/parens typically avoid duplicating them when they're typed/completed? This isn't actually easy to do, because after completing `file.h` you want the cursor after the closing quote, and after completing `dir/` you want the cursor inside the closing quote. I don't see a way to do this with CodeCompletionString other than generating the quote in the former case but not the latter. (At least not one that doesn't break something else...) Comment at: lib/Sema/SemaCodeComplete.cpp:8028 +CodeCompleter->getCodeCompletionTUInfo()); + Builder.AddTextChunk(InternedPrefix); + Builder.AddTypedTextChunk(InternedTyped); ilya-biryukov wrote: > Maybe leave this out? > When completing `std::^` the completion is `vector`, not `std::vector`. > In the same spirit, for includes I would expect completions for `#include > ` to be `bar.h`, not ``. I tried a few iterations here and this was the only one that didn't seem totally odd. Basically it's about the fact that these are quoted strings. Ergonomically, having the closing quote completed after a filename *feels* right - you can hit enter afterwards and go to the next line. If the closing quote is inserted, it has to be displayed (can't be avoided, also would be confusing). So if you make the completion range just the filename, you end up with a completion list like: ``` #include baz/ backwards.h> ``` vs the current ``` #include ``` So I see your point here but I'm not sure the other behavior is actually better. Comment at: lib/Sema/SemaCodeComplete.cpp:8057 + if (!(Filename.endswith(".h") || Filename.endswith(".hh") || +Filename.endswith(".H") || Filename.endswith(".hpp") || +Filename.endswith(".inc"))) ilya-biryukov wrote: > Maybe do case-insensitive matching? > A corner case, but still... This matches Driver's behavior (I'd reuse it but I don't think Sema can/should depend on Driver). Clang doesn't think "HPP" is a valid c++ header filename. I'll add a comment. Repository: rC Clang https://reviews.llvm.org/D52076 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52089: [clangd] Get rid of AST matchers in SymbolCollector. NFC
kadircet accepted this revision. kadircet added a comment. This revision is now accepted and ready to land. LGTM Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52093: [ToolChains] Linux.cpp: Use the same style across all all multi-arch includes. NFC.
kristina created this revision. kristina added a reviewer: rsmith. kristina added a project: clang. Herald added a subscriber: cfe-commits. Currently it seems like a mess in terms of where newlines are used. Cleaning it up so all of them use newlines and are aligned and moving the default switch case to the top. Making a differential to see if anyone has objections to the style used. Repository: rC Clang https://reviews.llvm.org/D52093 Files: lib/Driver/ToolChains/Linux.cpp Index: lib/Driver/ToolChains/Linux.cpp === --- lib/Driver/ToolChains/Linux.cpp +++ lib/Driver/ToolChains/Linux.cpp @@ -671,14 +671,16 @@ // FIXME: These are older forms of multiarch. It's not clear that they're // in use in any released version of Debian, so we should consider // removing them. - "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"}; + "/usr/include/i686-linux-gnu/64", + "/usr/include/i486-linux-gnu/64"}; const StringRef X86MultiarchIncludeDirs[] = { "/usr/include/i386-linux-gnu", // FIXME: These are older forms of multiarch. It's not clear that they're // in use in any released version of Debian, so we should consider // removing them. - "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu", + "/usr/include/x86_64-linux-gnu/32", + "/usr/include/i686-linux-gnu", "/usr/include/i486-linux-gnu"}; const StringRef AArch64MultiarchIncludeDirs[] = { "/usr/include/aarch64-linux-gnu"}; @@ -690,11 +692,13 @@ "/usr/include/armeb-linux-gnueabi"}; const StringRef ARMEBHFMultiarchIncludeDirs[] = { "/usr/include/armeb-linux-gnueabihf"}; - const StringRef MIPSMultiarchIncludeDirs[] = {"/usr/include/mips-linux-gnu"}; + const StringRef MIPSMultiarchIncludeDirs[] = { + "/usr/include/mips-linux-gnu"}; const StringRef MIPSELMultiarchIncludeDirs[] = { "/usr/include/mipsel-linux-gnu"}; const StringRef MIPS64MultiarchIncludeDirs[] = { - "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"}; + "/usr/include/mips64-linux-gnu", + "/usr/include/mips64-linux-gnuabi64"}; const StringRef MIPS64ELMultiarchIncludeDirs[] = { "/usr/include/mips64el-linux-gnu", "/usr/include/mips64el-linux-gnuabi64"}; @@ -713,6 +717,8 @@ "/usr/include/s390x-linux-gnu"}; ArrayRef MultiarchIncludeDirs; switch (getTriple().getArch()) { + default: +break; case llvm::Triple::x86_64: MultiarchIncludeDirs = X86_64MultiarchIncludeDirs; break; @@ -767,8 +773,6 @@ case llvm::Triple::systemz: MultiarchIncludeDirs = SYSTEMZMultiarchIncludeDirs; break; - default: -break; } const std::string AndroidMultiarchIncludeDir = Index: lib/Driver/ToolChains/Linux.cpp === --- lib/Driver/ToolChains/Linux.cpp +++ lib/Driver/ToolChains/Linux.cpp @@ -671,14 +671,16 @@ // FIXME: These are older forms of multiarch. It's not clear that they're // in use in any released version of Debian, so we should consider // removing them. - "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"}; + "/usr/include/i686-linux-gnu/64", + "/usr/include/i486-linux-gnu/64"}; const StringRef X86MultiarchIncludeDirs[] = { "/usr/include/i386-linux-gnu", // FIXME: These are older forms of multiarch. It's not clear that they're // in use in any released version of Debian, so we should consider // removing them. - "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu", + "/usr/include/x86_64-linux-gnu/32", + "/usr/include/i686-linux-gnu", "/usr/include/i486-linux-gnu"}; const StringRef AArch64MultiarchIncludeDirs[] = { "/usr/include/aarch64-linux-gnu"}; @@ -690,11 +692,13 @@ "/usr/include/armeb-linux-gnueabi"}; const StringRef ARMEBHFMultiarchIncludeDirs[] = { "/usr/include/armeb-linux-gnueabihf"}; - const StringRef MIPSMultiarchIncludeDirs[] = {"/usr/include/mips-linux-gnu"}; + const StringRef MIPSMultiarchIncludeDirs[] = { + "/usr/include/mips-linux-gnu"}; const StringRef MIPSELMultiarchIncludeDirs[] = { "/usr/include/mipsel-linux-gnu"}; const StringRef MIPS64MultiarchIncludeDirs[] = { - "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"}; + "/usr/include/mips64-linux-gnu", + "/usr/include/mips64-linux-gnuabi64"}; const StringRef MIPS64ELMultiarchIncludeDirs[] = { "/usr/include/mips64el-linux-gnu", "/usr/include/mips64el-linux-gnuabi64"}; @@ -713,6 +717,8 @@ "/usr/include/s390x-linux-gnu"}; ArrayRef MultiarchIncludeDirs; switch (getTriple().getArch()) { + default: +break; case llvm::Triple::x86_64: MultiarchIncludeDirs = X86_64MultiarchIncludeDirs; break; @@ -767,8 +773,6 @@ ca
[PATCH] D52058: Add Parameters to DW_AT_name Attribute of Template Variables
JDevlieghere added inline comments. Comment at: lib/CodeGen/CGDebugInfo.cpp:3126 + } else { +templateParameters = nullptr;//llvm::DINodeArray().get(); + } What's the meaning of this comment? Comment at: lib/CodeGen/CGDebugInfo.h:654 + StringRef &LinkageName, + llvm::MDTuple *&templateParameters, + llvm::DIScope *&VDContext); s/templateParameters/TemplateParameters/ (same for the rest of this patch) Repository: rC Clang https://reviews.llvm.org/D52058 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52074: [PowerPC] [Clang] Add vector int128 pack/unpack builtins
nemanjai added a comment. LGTM. Repository: rC Clang https://reviews.llvm.org/D52074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52008: [analyzer] Handle forwarding reference better in ExprMutationAnalyzer.
JonasToth added a comment. The `std::move` as cast is a follow up patch? From my side only the nits are left. Comment at: lib/Analysis/ExprMutationAnalyzer.cpp:333 +const auto *Parm = Nodes.getNodeAs("parm"); +const auto AllParams = +Func->getPrimaryTemplate()->getTemplatedDecl()->parameters(); Please spell out the type here Comment at: lib/Analysis/ExprMutationAnalyzer.cpp:339 +->getType(); +if (auto *T = ParmType->getAs()) + ParmType = T->getPattern(); could `T` be a const pointer? Comment at: lib/Analysis/ExprMutationAnalyzer.cpp:344 +// definition and see whether the param is mutated inside. +if (auto *RefType = ParmType->getAs()) { + if (!RefType->getPointeeType().getQualifiers() && could `RefType` be a const pointer? Comment at: lib/Analysis/ExprMutationAnalyzer.cpp:347 + RefType->getPointeeType()->getAs()) { +auto &Analyzer = FuncParmAnalyzer[Func]; +if (!Analyzer) Please spell out the type here Comment at: lib/Analysis/ExprMutationAnalyzer.cpp:381 +FunctionParmMutationAnalyzer::findMutation(const ParmVarDecl *Parm) { + const auto Memoized = Results.find(Parm); + if (Memoized != Results.end()) Please spell out the type here Repository: rC Clang https://reviews.llvm.org/D52008 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51332: [clang-tidy] Replace deprecated std::ios_base aliases
JonasToth added a comment. LG from my side, please rebase that patch on top of master. Currently the Release Notes would conflict (and please sort the release note alphabetically). If the other reviewers do not say anything within a reasonable time it can be committed. Do you have commit rights? https://reviews.llvm.org/D51332 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51332: [clang-tidy] Replace deprecated std::ios_base aliases
JonasToth added a comment. And i forgot: Could you please run this over a real code base, if you know one that actually uses these types? I assume not so many code bases actually use these. https://reviews.llvm.org/D51332 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48714: [clang-tidy] fix PR37913, templated exception factory diagnosed correctly
JonasToth marked 9 inline comments as done. JonasToth added a comment. I do consider the diagnostic thing as resolved given the lack of further comments. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D48714 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45444: [clang-tidy] implement new check for const-correctness
JonasToth updated this revision to Diff 165497. JonasToth added a comment. - update to ExprMutAnalyzer living in clang now Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D45444 Files: clang-tidy/cppcoreguidelines/CMakeLists.txt clang-tidy/cppcoreguidelines/ConstCorrectnessCheck.cpp clang-tidy/cppcoreguidelines/ConstCorrectnessCheck.h clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp docs/ReleaseNotes.rst docs/clang-tidy/checks/cppcoreguidelines-const-correctness.rst docs/clang-tidy/checks/list.rst test/clang-tidy/cppcoreguidelines-const-correctness-pointer-as-values.cpp test/clang-tidy/cppcoreguidelines-const-correctness-values.cpp Index: test/clang-tidy/cppcoreguidelines-const-correctness-values.cpp === --- /dev/null +++ test/clang-tidy/cppcoreguidelines-const-correctness-values.cpp @@ -0,0 +1,563 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-const-correctness %t + +// --- Provide test samples for primitive builtins - +// - every 'p_*' variable is a 'potential_const_*' variable +// - every 'np_*' variable is a 'non_potential_const_*' variable + +bool global; +char np_global = 0; // globals can't be known to be const + +namespace foo { +int scoped; +float np_scoped = 1; // namespace variables are like globals +} // namespace foo + +// Lambdas should be ignored, because they do not follow the normal variable +// semantic (e.g. the type is only known to the compiler). +void lambdas() { + auto Lambda = [](int i) { return i < 0; }; +} + +void some_function(double, wchar_t); + +void some_function(double np_arg0, wchar_t np_arg1) { + int p_local0 = 2; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' + + int np_local0; + const int np_local1 = 42; + + unsigned int np_local2 = 3; + np_local2 <<= 4; + + int np_local3 = 4; + ++np_local3; + int np_local4 = 4; + np_local4++; + + int np_local5 = 4; + --np_local5; + int np_local6 = 4; + np_local6--; +} + +void nested_scopes() { + int p_local0 = 2; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' + int np_local0 = 42; + + { +int p_local1 = 42; +// CHECK-MESSAGES: [[@LINE-1]]:5: warning: variable 'p_local1' of type 'int' can be declared 'const' +np_local0 *= 2; + } +} + +void some_lambda_environment_capture_all_by_reference(double np_arg0) { + int np_local0 = 0; + int p_local0 = 1; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' + + int np_local2; + const int np_local3 = 2; + + // Capturing all variables by reference prohibits making them const. + [&]() { ++np_local0; }; + + int p_local1 = 0; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const' +} + +void some_lambda_environment_capture_all_by_value(double np_arg0) { + int np_local0 = 0; + int p_local0 = 1; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' + + int np_local1; + const int np_local2 = 2; + + // Capturing by value has no influence on them. + [=]() { (void)p_local0; }; + + np_local0 += 10; +} + +void function_inout_pointer(int *inout); +void function_in_pointer(const int *in); + +void some_pointer_taking(int *out) { + int np_local0 = 42; + const int *const p0_np_local0 = &np_local0; + int *const p1_np_local0 = &np_local0; + + int np_local1 = 42; + const int *const p0_np_local1 = &np_local1; + int *const p1_np_local1 = &np_local1; + *p1_np_local0 = 43; + + int np_local2 = 42; + function_inout_pointer(&np_local2); + + // Prevents const. + int np_local3 = 42; + out = &np_local3; // This returns and invalid address, its just about the AST + + int p_local1 = 42; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const' + const int *const p0_p_local1 = &p_local1; + + int p_local2 = 42; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'int' can be declared 'const' + function_in_pointer(&p_local2); +} + +void function_inout_ref(int &inout); +void function_in_ref(const int &in); + +void some_reference_taking() { + int np_local0 = 42; + const int &r0_np_local0 = np_local0; + int &r1_np_local0 = np_local0; + r1_np_local0 = 43; + const int &r2_np_local0 = r1_np_local0; + + int np_local1 = 42; + function_inout_ref(np_local1); + + int p_local0 = 42; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' + const int &r0_p_local0 = p_local0; + + int p_local1 = 42; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const' + function_in_ref(p_local1); +} + +double *non_const_pointer_return() { + double p_local0 = 0.0; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double' c
r342238 - [clang] Make sure attributes on member classes are applied properly
Author: ldionne Date: Fri Sep 14 07:07:16 2018 New Revision: 342238 URL: http://llvm.org/viewvc/llvm-project?rev=342238&view=rev Log: [clang] Make sure attributes on member classes are applied properly Summary: Attributes on member classes of class templates and member class templates of class templates are not currently instantiated. This was discovered by Richard Smith here: http://lists.llvm.org/pipermail/cfe-dev/2018-September/059291.html This commit makes sure that attributes are instantiated properly. This commit does not fix the broken behavior for member partial and explicit specializations of class templates. PR38913 Reviewers: rsmith Subscribers: dexonsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D51997 Added: cfe/trunk/test/SemaCXX/PR38913.cpp Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=342238&r1=342237&r2=342238&view=diff == --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Sep 14 07:07:16 2018 @@ -1258,6 +1258,9 @@ Decl *TemplateDeclInstantiator::VisitCla if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); + SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs, + StartingScope); + ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, RecordInst); @@ -1491,6 +1494,9 @@ Decl *TemplateDeclInstantiator::VisitCXX if (SubstQualifier(D, Record)) return nullptr; + SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs, + StartingScope); + Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that // the tag decls introduced by friend class declarations don't have an access Added: cfe/trunk/test/SemaCXX/PR38913.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR38913.cpp?rev=342238&view=auto == --- cfe/trunk/test/SemaCXX/PR38913.cpp (added) +++ cfe/trunk/test/SemaCXX/PR38913.cpp Fri Sep 14 07:07:16 2018 @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// PR38913 +// Check that we instantiate attributes on declarations for... + +// ...a member class of a class template specialization +template struct A { struct __attribute__((abi_tag("ATAG"))) X { }; }; +A::X* a() { return 0; } // CHECK-DAG: @_Z1aB4ATAGv + +// ...a member class template +template struct B { template struct __attribute__((abi_tag("BTAG"))) X { }; }; +B::X* b() { return 0; } // CHECK-DAG: @_Z1bB4BTAGv ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51997: [clang] Make sure attributes on member classes are applied properly
This revision was automatically updated to reflect the committed changes. Closed by commit rC342238: [clang] Make sure attributes on member classes are applied properly (authored by ldionne, committed by ). Changed prior to commit: https://reviews.llvm.org/D51997?vs=165375&id=165502#toc Repository: rC Clang https://reviews.llvm.org/D51997 Files: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/PR38913.cpp Index: lib/Sema/SemaTemplateInstantiateDecl.cpp === --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1258,6 +1258,9 @@ if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); + SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs, + StartingScope); + ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, RecordInst); @@ -1491,6 +1494,9 @@ if (SubstQualifier(D, Record)) return nullptr; + SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs, + StartingScope); + Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that // the tag decls introduced by friend class declarations don't have an access Index: test/SemaCXX/PR38913.cpp === --- test/SemaCXX/PR38913.cpp +++ test/SemaCXX/PR38913.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// PR38913 +// Check that we instantiate attributes on declarations for... + +// ...a member class of a class template specialization +template struct A { struct __attribute__((abi_tag("ATAG"))) X { }; }; +A::X* a() { return 0; } // CHECK-DAG: @_Z1aB4ATAGv + +// ...a member class template +template struct B { template struct __attribute__((abi_tag("BTAG"))) X { }; }; +B::X* b() { return 0; } // CHECK-DAG: @_Z1bB4BTAGv Index: lib/Sema/SemaTemplateInstantiateDecl.cpp === --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1258,6 +1258,9 @@ if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); + SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs, + StartingScope); + ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, RecordInst); @@ -1491,6 +1494,9 @@ if (SubstQualifier(D, Record)) return nullptr; + SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs, + StartingScope); + Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that // the tag decls introduced by friend class declarations don't have an access Index: test/SemaCXX/PR38913.cpp === --- test/SemaCXX/PR38913.cpp +++ test/SemaCXX/PR38913.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// PR38913 +// Check that we instantiate attributes on declarations for... + +// ...a member class of a class template specialization +template struct A { struct __attribute__((abi_tag("ATAG"))) X { }; }; +A::X* a() { return 0; } // CHECK-DAG: @_Z1aB4ATAGv + +// ...a member class template +template struct B { template struct __attribute__((abi_tag("BTAG"))) X { }; }; +B::X* b() { return 0; } // CHECK-DAG: @_Z1bB4BTAGv ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51789: [WIP][clang] Add the no_extern_template attribute
ldionne updated this revision to Diff 165507. ldionne added a comment. Fix the tests and remove some warnings that I wasn't able to generate properly (to avoid false positives). Repository: rC Clang https://reviews.llvm.org/D51789 Files: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/test/CodeGenCXX/attr-no_extern_template.dont_assume_extern_instantiation.cpp clang/test/Misc/pragma-attribute-supported-attributes-list.test clang/test/SemaCXX/attr-no_extern_template.diagnose_on_undefined_entity.cpp clang/test/SemaCXX/attr-no_extern_template.explicit_instantiation.cpp clang/test/SemaCXX/attr-no_extern_template.extern_declaration.cpp clang/test/SemaCXX/attr-no_extern_template.merge_redeclarations.cpp Index: clang/test/SemaCXX/attr-no_extern_template.merge_redeclarations.cpp === --- /dev/null +++ clang/test/SemaCXX/attr-no_extern_template.merge_redeclarations.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test that we properly merge the no_extern_template attribute on +// redeclarations. + +#define NO_EXTERN_TEMPLATE __attribute__((no_extern_template)) + +template +struct Foo { + // Declaration without the attribute, definition with the attribute. + void func1(); + + // Declaration with the attribute, definition without the attribute. + NO_EXTERN_TEMPLATE void func2(); + + // Declaration with the attribute, definition with the attribute. + NO_EXTERN_TEMPLATE void func3(); +}; + +template +NO_EXTERN_TEMPLATE void Foo::func1() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template +void Foo::func2() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template +NO_EXTERN_TEMPLATE void Foo::func3() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +struct Empty { }; +extern template struct Foo; + +int main() { + Foo foo; + foo.func1(); // expected-note{{in instantiation of}} + foo.func2(); // expected-note{{in instantiation of}} + foo.func3(); // expected-note{{in instantiation of}} +} Index: clang/test/SemaCXX/attr-no_extern_template.extern_declaration.cpp === --- /dev/null +++ clang/test/SemaCXX/attr-no_extern_template.extern_declaration.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -Wno-unused-local-typedef -fsyntax-only -verify %s + +// Test that extern instantiation declarations cause members marked with +// no_extern_template to be instantiated in the current TU. + +#define NO_EXTERN_TEMPLATE __attribute__((no_extern_template)) + +template +struct Foo { + NO_EXTERN_TEMPLATE inline void non_static_member_function1(); + + NO_EXTERN_TEMPLATE void non_static_member_function2(); + + NO_EXTERN_TEMPLATE static inline void static_member_function1(); + + NO_EXTERN_TEMPLATE static void static_member_function2(); + + NO_EXTERN_TEMPLATE static int static_data_member; + + struct NO_EXTERN_TEMPLATE member_class1 { +static void static_member_function() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + }; + + struct member_class2 { +NO_EXTERN_TEMPLATE static void static_member_function() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + }; +}; + +template +inline void Foo::non_static_member_function1() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template +void Foo::non_static_member_function2() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template +inline void Foo::static_member_function1() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template +void Foo::static_member_function2() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template +int Foo::static_data_member = T::invalid; // expected-error{{no member named 'invalid' in 'Empty'}} + +struct Empty { }; +extern template struct Foo; + +int main() { + Foo foo; + foo.non_static_member_function1(); // expected-note{{in instantiation of}} + foo.non_static_member_function2(); // expected-note{{in instantiation of}} + Foo::static_member_function1(); // expected-note{{in instantiation of}} + Foo::static_member_function2(); // expected-note{{in instantiation of}} + (void)foo.static_data_member;// expected-note{{in instantiation of}} + Foo::member_class1::static_member_function(); // expected-note{{in instantiation of}} + Foo::member_class2::
[PATCH] D51789: [clang] Add the no_extern_template attribute
ldionne added a comment. I think now's a good time to bikeshed the name of the attribute if you have other suggestions. Repository: rC Clang https://reviews.llvm.org/D51789 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52097: [OPENMP] Move OMPClauseReader/Writer classes to ASTReader/Writer - NFC
patricklyster created this revision. patricklyster added reviewers: ABataev, Hahnfeld, RaviNarayanaswamy, mikerice, kkwli0, hfinkel, gtbercea. patricklyster added projects: OpenMP, clang. Herald added subscribers: cfe-commits, jfb, guansong. Move declarations for `OMPClauseReader`, `OMPClauseWriter` to ASTReader.h and ASTWriter.h and move implementation to ASTReader.cpp and ASTWriter.cpp. This NFC will help generalize the serialization of OpenMP clauses and will be used in the future implementation of new OpenMP directives (e.g. `omp requires`). Repository: rC Clang https://reviews.llvm.org/D52097 Files: clang/include/clang/AST/OpenMPClause.h clang/include/clang/AST/StmtVisitor.h clang/include/clang/Serialization/ASTReader.h clang/include/clang/Serialization/ASTWriter.h clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriter.cpp clang/lib/Serialization/ASTWriterStmt.cpp Index: clang/lib/Serialization/ASTWriterStmt.cpp === --- clang/lib/Serialization/ASTWriterStmt.cpp +++ clang/lib/Serialization/ASTWriterStmt.cpp @@ -1803,485 +1803,6 @@ } //===--===// -// OpenMP Clauses. -//===--===// - -namespace clang { -class OMPClauseWriter : public OMPClauseVisitor { - ASTRecordWriter &Record; -public: - OMPClauseWriter(ASTRecordWriter &Record) : Record(Record) {} -#define OPENMP_CLAUSE(Name, Class)\ - void Visit##Class(Class *S); -#include "clang/Basic/OpenMPKinds.def" - void writeClause(OMPClause *C); - void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C); - void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C); -}; -} - -void OMPClauseWriter::writeClause(OMPClause *C) { - Record.push_back(C->getClauseKind()); - Visit(C); - Record.AddSourceLocation(C->getBeginLoc()); - Record.AddSourceLocation(C->getEndLoc()); -} - -void OMPClauseWriter::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) { - Record.push_back(C->getCaptureRegion()); - Record.AddStmt(C->getPreInitStmt()); -} - -void OMPClauseWriter::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) { - VisitOMPClauseWithPreInit(C); - Record.AddStmt(C->getPostUpdateExpr()); -} - -void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) { - VisitOMPClauseWithPreInit(C); - Record.push_back(C->getNameModifier()); - Record.AddSourceLocation(C->getNameModifierLoc()); - Record.AddSourceLocation(C->getColonLoc()); - Record.AddStmt(C->getCondition()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) { - Record.AddStmt(C->getCondition()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { - VisitOMPClauseWithPreInit(C); - Record.AddStmt(C->getNumThreads()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) { - Record.AddStmt(C->getSafelen()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) { - Record.AddStmt(C->getSimdlen()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) { - Record.AddStmt(C->getNumForLoops()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) { - Record.push_back(C->getDefaultKind()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getDefaultKindKwLoc()); -} - -void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) { - Record.push_back(C->getProcBindKind()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getProcBindKindKwLoc()); -} - -void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) { - VisitOMPClauseWithPreInit(C); - Record.push_back(C->getScheduleKind()); - Record.push_back(C->getFirstScheduleModifier()); - Record.push_back(C->getSecondScheduleModifier()); - Record.AddStmt(C->getChunkSize()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getFirstScheduleModifierLoc()); - Record.AddSourceLocation(C->getSecondScheduleModifierLoc()); - Record.AddSourceLocation(C->getScheduleKindLoc()); - Record.AddSourceLocation(C->getCommaLoc()); -} - -void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) { - Record.push_back(C->getLoopNumIterations().size()); - Record.AddStmt(C->getNumForLoops()); - for (Expr *NumIter : C->getLoopNumIterations()) -Record.AddStmt(NumIter); - for (unsigned I = 0, E = C->getLoopNumIterations().size(); I getLoopCunter(I)); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *) {} - -void O
[PATCH] D52098: [Index] Add an option to collect macros from preprocesor.
ioeric created this revision. ioeric added a reviewer: ilya-biryukov. Herald added subscribers: cfe-commits, mgorny. Also added unit tests for the index library; lit+c-index-test is painful... Repository: rC Clang https://reviews.llvm.org/D52098 Files: include/clang/Index/IndexingAction.h lib/Index/IndexingAction.cpp unittests/CMakeLists.txt unittests/Index/CMakeLists.txt unittests/Index/IndexTests.cpp Index: unittests/Index/IndexTests.cpp === --- /dev/null +++ unittests/Index/IndexTests.cpp @@ -0,0 +1,136 @@ +//===--- IndexTests.cpp - Test indexing actions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/Decl.h" +#include "clang/Basic/VirtualFileSystem.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Index/IndexDataConsumer.h" +#include "clang/Index/IndexSymbol.h" +#include "clang/Index/IndexingAction.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/StringRef.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include + +namespace clang { +namespace index { + +struct TestSymbol { + std::string QName; + SymbolRoleSet Roles; + SymbolInfo Info; + // FIXME: add more information. +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TestSymbol &S) { + return OS << S.QName; +} + +namespace { +class Indexer : public IndexDataConsumer { +public: + bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, + ArrayRef, SourceLocation, + ASTNodeInfo) override { +llvm::errs() << "Handle decl: \n"; +const auto *ND = llvm::dyn_cast(D); +if (!ND) + return true; +llvm::errs() << "ND: " << ND->getQualifiedNameAsString() << "\n"; +TestSymbol S; +S.QName = ND->getQualifiedNameAsString(); +S.Roles = Roles; +S.Info = getSymbolInfo(ND); +Symbols.push_back(std::move(S)); +return true; + } + + bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI, +SymbolRoleSet Roles, SourceLocation) override { +TestSymbol S; +S.QName = Name->getName(); +S.Roles = Roles; +if (MI) + S.Info = getSymbolInfoForMacro(*MI); +Symbols.push_back(std::move(S)); +return true; + } + + std::vector Symbols; +}; + +class IndexAction : public ASTFrontendAction { +public: + IndexAction(std::shared_ptr Index, + IndexingOptions Opts = IndexingOptions()) + : Index(std::move(Index)), Opts(Opts) {} + +protected: + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override { +class Consumer : public ASTConsumer { + std::shared_ptr Index; + std::shared_ptr PP; + IndexingOptions Opts; + +public: + Consumer(std::shared_ptr Index, std::shared_ptr PP, + IndexingOptions Opts) + : Index(std::move(Index)), PP(std::move(PP)), Opts(Opts) {} + + void HandleTranslationUnit(ASTContext &Ctx) override { +llvm::errs() << "Handle TU : " << Ctx.getTranslationUnitDecl() << "\n"; +Ctx.getTranslationUnitDecl()->dump(); +std::vector DeclsToIndex( +Ctx.getTranslationUnitDecl()->decls().begin(), +Ctx.getTranslationUnitDecl()->decls().end()); +indexTopLevelDecls(Ctx, *PP, DeclsToIndex, *Index, Opts); + } +}; +return llvm::make_unique(Index, CI.getPreprocessorPtr(), Opts); + } + +private: + std::shared_ptr Index; + IndexingOptions Opts; +}; + +using testing::Contains; +using testing::Not; +using testing::UnorderedElementsAre; + +MATCHER_P(QName, Name, "") { return arg.QName == Name; } + +TEST(IndexTest, Simple) { + auto Index = std::make_shared(); + tooling::runToolOnCode(new IndexAction(Index), "class X {}; void f() {}"); + EXPECT_THAT(Index->Symbols, UnorderedElementsAre(QName("X"), QName("f"))); +} + +TEST(IndexTest, IndexPreprocessorMacros) { + std::string Code = "#define INDEX_MAC 1"; + auto Index = std::make_shared(); + IndexingOptions Opts; + Opts.IndexMacrosInPreprocessor = true; + tooling::runToolOnCode(new IndexAction(Index, Opts), Code); + EXPECT_THAT(Index->Symbols, Contains(QName("INDEX_MAC"))); + + Opts.IndexMacrosInPreprocessor = false; + Index->Symbols.clear(); + tooling::runToolOnCode(new IndexAction(Index, Opts), Code); + EXPECT_THAT(Index->Symbols, UnorderedElementsAre()); +} + +} // namespace +} // namespace index +} // namespace clang Index: unittests/Index/CMakeLists.txt === --- /dev/nul
[PATCH] D52098: [Index] Add an option to collect macros from preprocesor.
ioeric updated this revision to Diff 165514. ioeric added a comment. - remove debug message. Repository: rC Clang https://reviews.llvm.org/D52098 Files: include/clang/Index/IndexingAction.h lib/Index/IndexingAction.cpp unittests/CMakeLists.txt unittests/Index/CMakeLists.txt unittests/Index/IndexTests.cpp Index: unittests/Index/IndexTests.cpp === --- /dev/null +++ unittests/Index/IndexTests.cpp @@ -0,0 +1,132 @@ +//===--- IndexTests.cpp - Test indexing actions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/Decl.h" +#include "clang/Basic/VirtualFileSystem.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Index/IndexDataConsumer.h" +#include "clang/Index/IndexSymbol.h" +#include "clang/Index/IndexingAction.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/StringRef.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include + +namespace clang { +namespace index { + +struct TestSymbol { + std::string QName; + SymbolRoleSet Roles; + SymbolInfo Info; + // FIXME: add more information. +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TestSymbol &S) { + return OS << S.QName; +} + +namespace { +class Indexer : public IndexDataConsumer { +public: + bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, + ArrayRef, SourceLocation, + ASTNodeInfo) override { +const auto *ND = llvm::dyn_cast(D); +if (!ND) + return true; +TestSymbol S; +S.QName = ND->getQualifiedNameAsString(); +S.Roles = Roles; +S.Info = getSymbolInfo(ND); +Symbols.push_back(std::move(S)); +return true; + } + + bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI, +SymbolRoleSet Roles, SourceLocation) override { +TestSymbol S; +S.QName = Name->getName(); +S.Roles = Roles; +if (MI) + S.Info = getSymbolInfoForMacro(*MI); +Symbols.push_back(std::move(S)); +return true; + } + + std::vector Symbols; +}; + +class IndexAction : public ASTFrontendAction { +public: + IndexAction(std::shared_ptr Index, + IndexingOptions Opts = IndexingOptions()) + : Index(std::move(Index)), Opts(Opts) {} + +protected: + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override { +class Consumer : public ASTConsumer { + std::shared_ptr Index; + std::shared_ptr PP; + IndexingOptions Opts; + +public: + Consumer(std::shared_ptr Index, std::shared_ptr PP, + IndexingOptions Opts) + : Index(std::move(Index)), PP(std::move(PP)), Opts(Opts) {} + + void HandleTranslationUnit(ASTContext &Ctx) override { +std::vector DeclsToIndex( +Ctx.getTranslationUnitDecl()->decls().begin(), +Ctx.getTranslationUnitDecl()->decls().end()); +indexTopLevelDecls(Ctx, *PP, DeclsToIndex, *Index, Opts); + } +}; +return llvm::make_unique(Index, CI.getPreprocessorPtr(), Opts); + } + +private: + std::shared_ptr Index; + IndexingOptions Opts; +}; + +using testing::Contains; +using testing::Not; +using testing::UnorderedElementsAre; + +MATCHER_P(QName, Name, "") { return arg.QName == Name; } + +TEST(IndexTest, Simple) { + auto Index = std::make_shared(); + tooling::runToolOnCode(new IndexAction(Index), "class X {}; void f() {}"); + EXPECT_THAT(Index->Symbols, UnorderedElementsAre(QName("X"), QName("f"))); +} + +TEST(IndexTest, IndexPreprocessorMacros) { + std::string Code = "#define INDEX_MAC 1"; + auto Index = std::make_shared(); + IndexingOptions Opts; + Opts.IndexMacrosInPreprocessor = true; + tooling::runToolOnCode(new IndexAction(Index, Opts), Code); + EXPECT_THAT(Index->Symbols, Contains(QName("INDEX_MAC"))); + + Opts.IndexMacrosInPreprocessor = false; + Index->Symbols.clear(); + tooling::runToolOnCode(new IndexAction(Index, Opts), Code); + EXPECT_THAT(Index->Symbols, UnorderedElementsAre()); +} + +} // namespace +} // namespace index +} // namespace clang Index: unittests/Index/CMakeLists.txt === --- /dev/null +++ unittests/Index/CMakeLists.txt @@ -0,0 +1,18 @@ +set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + Support + ) + +add_clang_unittest(IndexTests + IndexTests.cpp + ) + +target_link_libraries(IndexTests + PRIVATE + clangAST + clangBasic + clangFrontend + clangIndex + clangLex + clangTooling + ) Index: unittests/CMake
[PATCH] D52097: [OPENMP] Move OMPClauseReader/Writer classes to ASTReader/Writer - NFC
ABataev accepted this revision. ABataev added a comment. This revision is now accepted and ready to land. LG Repository: rC Clang https://reviews.llvm.org/D52097 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45444: [clang-tidy] implement new check for const-correctness
xbolva00 added a comment. Yeah, it would be super useful if Clang can add const to all places where possible :) love this work, great! Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D45444 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52098: [Index] Add an option to collect macros from preprocesor.
ioeric updated this revision to Diff 165516. ioeric added a comment. - another cleanup... Repository: rC Clang https://reviews.llvm.org/D52098 Files: include/clang/Index/IndexingAction.h lib/Index/IndexingAction.cpp unittests/CMakeLists.txt unittests/Index/CMakeLists.txt unittests/Index/IndexTests.cpp Index: unittests/Index/IndexTests.cpp === --- /dev/null +++ unittests/Index/IndexTests.cpp @@ -0,0 +1,132 @@ +//===--- IndexTests.cpp - Test indexing actions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/Decl.h" +#include "clang/Basic/VirtualFileSystem.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Index/IndexDataConsumer.h" +#include "clang/Index/IndexSymbol.h" +#include "clang/Index/IndexingAction.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/StringRef.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include + +namespace clang { +namespace index { + +struct TestSymbol { + std::string QName; + SymbolRoleSet Roles; + SymbolInfo Info; + // FIXME: add more information. +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TestSymbol &S) { + return OS << S.QName; +} + +namespace { +class Indexer : public IndexDataConsumer { +public: + bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, + ArrayRef, SourceLocation, + ASTNodeInfo) override { +const auto *ND = llvm::dyn_cast(D); +if (!ND) + return true; +TestSymbol S; +S.QName = ND->getQualifiedNameAsString(); +S.Roles = Roles; +S.Info = getSymbolInfo(ND); +Symbols.push_back(std::move(S)); +return true; + } + + bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI, +SymbolRoleSet Roles, SourceLocation) override { +TestSymbol S; +S.QName = Name->getName(); +S.Roles = Roles; +if (MI) + S.Info = getSymbolInfoForMacro(*MI); +Symbols.push_back(std::move(S)); +return true; + } + + std::vector Symbols; +}; + +class IndexAction : public ASTFrontendAction { +public: + IndexAction(std::shared_ptr Index, + IndexingOptions Opts = IndexingOptions()) + : Index(std::move(Index)), Opts(Opts) {} + +protected: + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override { +class Consumer : public ASTConsumer { + std::shared_ptr Index; + std::shared_ptr PP; + IndexingOptions Opts; + +public: + Consumer(std::shared_ptr Index, std::shared_ptr PP, + IndexingOptions Opts) + : Index(std::move(Index)), PP(std::move(PP)), Opts(Opts) {} + + void HandleTranslationUnit(ASTContext &Ctx) override { +std::vector DeclsToIndex( +Ctx.getTranslationUnitDecl()->decls().begin(), +Ctx.getTranslationUnitDecl()->decls().end()); +indexTopLevelDecls(Ctx, *PP, DeclsToIndex, *Index, Opts); + } +}; +return llvm::make_unique(Index, CI.getPreprocessorPtr(), Opts); + } + +private: + std::shared_ptr Index; + IndexingOptions Opts; +}; + +using testing::Contains; +using testing::Not; +using testing::UnorderedElementsAre; + +MATCHER_P(QName, Name, "") { return arg.QName == Name; } + +TEST(IndexTest, Simple) { + auto Index = std::make_shared(); + tooling::runToolOnCode(new IndexAction(Index), "class X {}; void f() {}"); + EXPECT_THAT(Index->Symbols, UnorderedElementsAre(QName("X"), QName("f"))); +} + +TEST(IndexTest, IndexPreprocessorMacros) { + std::string Code = "#define INDEX_MAC 1"; + auto Index = std::make_shared(); + IndexingOptions Opts; + Opts.IndexMacrosInPreprocessor = true; + tooling::runToolOnCode(new IndexAction(Index, Opts), Code); + EXPECT_THAT(Index->Symbols, Contains(QName("INDEX_MAC"))); + + Opts.IndexMacrosInPreprocessor = false; + Index->Symbols.clear(); + tooling::runToolOnCode(new IndexAction(Index, Opts), Code); + EXPECT_THAT(Index->Symbols, UnorderedElementsAre()); +} + +} // namespace +} // namespace index +} // namespace clang Index: unittests/Index/CMakeLists.txt === --- /dev/null +++ unittests/Index/CMakeLists.txt @@ -0,0 +1,18 @@ +set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + Support + ) + +add_clang_unittest(IndexTests + IndexTests.cpp + ) + +target_link_libraries(IndexTests + PRIVATE + clangAST + clangBasic + clangFrontend + clangIndex + clangLex + clangTooling + ) Index: unittests/CMakeLis
r342240 - [clang-cl] Fix PR38934: failing to dllexport class template member w/ explicit instantiation and PCH
Author: hans Date: Fri Sep 14 08:18:30 2018 New Revision: 342240 URL: http://llvm.org/viewvc/llvm-project?rev=342240&view=rev Log: [clang-cl] Fix PR38934: failing to dllexport class template member w/ explicit instantiation and PCH The code in ASTContext::DeclMustBeEmitted was supposed to handle this, but didn't take into account that synthesized members such as operator= might not get marked as template specializations, because they're synthesized on the instantiation directly when handling the class-level dllexport attribute. Modified: cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/test/CodeGen/pch-dllexport.cpp Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=342240&r1=342239&r2=342240&view=diff == --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Fri Sep 14 08:18:30 2018 @@ -9724,6 +9724,14 @@ bool ASTContext::DeclMustBeEmitted(const cast(D)->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; +// Implicit member function definitions, such as operator= might not be +// marked as template specializations, since they're not coming from a +// template but synthesized directly on the class. +IsExpInstDef |= +isa(D) && +cast(D)->getParent()->getTemplateSpecializationKind() == +TSK_ExplicitInstantiationDefinition; + if (getExternalSource()->DeclIsFromPCHWithObjectFile(D) && !IsExpInstDef) return false; } Modified: cfe/trunk/test/CodeGen/pch-dllexport.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pch-dllexport.cpp?rev=342240&r1=342239&r2=342240&view=diff == --- cfe/trunk/test/CodeGen/pch-dllexport.cpp (original) +++ cfe/trunk/test/CodeGen/pch-dllexport.cpp Fri Sep 14 08:18:30 2018 @@ -57,6 +57,13 @@ extern template void explicitInstantiati template T __declspec(dllexport) variableTemplate; extern template int variableTemplate; +namespace pr38934 { +template struct S {}; +extern template struct S; +// The use here causes the S::operator= decl to go into the PCH. +inline void use(S *a, S *b) { *a = *b; }; +} + #else void use() { @@ -81,4 +88,9 @@ template void __declspec(dllexport) expl template int __declspec(dllexport) variableTemplate; // PCHWITHOBJVARS: @"??$variableTemplate@H@@3HA" = weak_odr dso_local dllexport global +// PR38934: Make sure S::operator= gets emitted. While it itself isn't a +// template specialization, its parent is. +template struct __declspec(dllexport) pr38934::S; +// PCHWITHOBJ: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %"struct.pr38934::S"* @"??4?$S@H@pr38934@@QAEAAU01@ABU01@@Z" + #endif ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52078: [clangd] Store preamble macros in dynamic index.
ioeric updated this revision to Diff 165517. ioeric added a comment. - Move macro collection to indexTopLevelDecls. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52078 Files: clangd/ClangdServer.cpp clangd/FindSymbols.cpp clangd/XRefs.cpp clangd/index/FileIndex.cpp clangd/index/FileIndex.h unittests/clangd/CodeCompleteTests.cpp unittests/clangd/FileIndexTests.cpp unittests/clangd/IndexTests.cpp unittests/clangd/TestTU.cpp Index: unittests/clangd/TestTU.cpp === --- unittests/clangd/TestTU.cpp +++ unittests/clangd/TestTU.cpp @@ -51,7 +51,7 @@ std::unique_ptr TestTU::index() const { auto AST = build(); auto Content = indexAST(AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); return MemIndex::build(std::move(Content.first), std::move(Content.second)); } Index: unittests/clangd/IndexTests.cpp === --- unittests/clangd/IndexTests.cpp +++ unittests/clangd/IndexTests.cpp @@ -244,7 +244,7 @@ Test.Filename = "test.cc"; auto AST = Test.build(); Dyn.update(Test.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); // Build static index for test.cc. Test.HeaderCode = HeaderCode; @@ -254,7 +254,7 @@ // Add stale refs for test.cc. StaticIndex.update(Test.Filename, &StaticAST.getASTContext(), StaticAST.getPreprocessorPtr(), - StaticAST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, StaticAST.getLocalTopLevelDecls()); // Add refs for test2.cc Annotations Test2Code(R"(class $Foo[[Foo]] {};)"); @@ -265,7 +265,7 @@ StaticAST = Test2.build(); StaticIndex.update(Test2.Filename, &StaticAST.getASTContext(), StaticAST.getPreprocessorPtr(), - StaticAST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, StaticAST.getLocalTopLevelDecls()); RefsRequest Request; Request.IDs = {Foo.ID}; Index: unittests/clangd/FileIndexTests.cpp === --- unittests/clangd/FileIndexTests.cpp +++ unittests/clangd/FileIndexTests.cpp @@ -15,6 +15,7 @@ #include "index/FileIndex.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/PCHContainerOperations.h" +#include "clang/Index/IndexSymbol.h" #include "clang/Lex/Preprocessor.h" #include "clang/Tooling/CompilationDatabase.h" #include "gtest/gtest.h" @@ -135,7 +136,8 @@ File.HeaderFilename = (Basename + ".h").str(); File.HeaderCode = Code; auto AST = File.build(); - M.update(File.Filename, &AST.getASTContext(), AST.getPreprocessorPtr()); + M.update(File.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), + /*IndexMacros=*/true); } TEST(FileIndexTest, CustomizedURIScheme) { @@ -333,23 +335,38 @@ Test.Filename = "test.cc"; auto AST = Test.build(); Index.update(Test.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); // Add test2.cc TestTU Test2; Test2.HeaderCode = HeaderCode; Test2.Code = MainCode.code(); Test2.Filename = "test2.cc"; AST = Test2.build(); Index.update(Test2.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(), - AST.getLocalTopLevelDecls()); + /*IndexMacros=*/false, AST.getLocalTopLevelDecls()); EXPECT_THAT(getRefs(Index, Foo.ID), RefsAre({AllOf(RefRange(MainCode.range("foo")), FileURI("unittest:///test.cc")), AllOf(RefRange(MainCode.range("foo")), FileURI("unittest:///test2.cc"))})); } +TEST(FileIndexTest, CollectMacros) { + FileIndex M; + update(M, "f", "#define CLANGD 1"); + + FuzzyFindRequest Req; + Req.Query = ""; + bool SeenSymbol = false; + M.fuzzyFind(Req, [&](const Symbol &Sym) { +EXPECT_EQ(Sym.Name, "CLANGD"); +EXPECT_EQ(Sym.SymInfo.Kind, index::SymbolKind::Macro); +SeenSymbol = true; + }); + EXPECT_TRUE(SeenSymbol); +} + } // namespace } // namespace clangd } // namespace clang Index: unittests/clangd/CodeCompleteTests.cpp === --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -223,12 +223,13 @@ void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) { auto Results = completions( R"cpp( - #define MACRO X - int global_var; int global_func(); + // Make sure this is not in preamble. + #define MACRO X + struct Global
[PATCH] D52078: [clangd] Store preamble macros in dynamic index.
ioeric added a comment. In https://reviews.llvm.org/D52078#1234667, @ilya-biryukov wrote: > ~1% increase in memory usage seems totally fine. Actually surprised it's that > small. Tested on a larger file: it's ~5% for `ClangdServer.cpp`. I think it's still worth it for the speedup. Comment at: clangd/index/FileIndex.cpp:84 +Merged.insert(Macro); + for (const auto &Sym : Collector.takeSymbols()) +Merged.insert(Sym); ilya-biryukov wrote: > ioeric wrote: > > ilya-biryukov wrote: > > > Why make an extra copy of the symbols? Why not add macros to the same > > > builder used in collector? > > `index::indexTopLevelDecls` will re-`initialize` the collector. This is > > safe with the current implementation, but I can imagine it goes wrong when > > we do more cleanup in the initialization. > Sorry, missed the comment about it. > And if we do this after `indexTopLevelDecls`, than we'll be calling after the > `finish` call. **Sigh**... > > Doing an extra copy of the symbols here is wasteful and makes the code more > complicated than it should be. > > We have alternatives that could fix this: > 1. Move `IndexMacro` logic into `index::indexTopLevelDecls` > 2. Move macro collection to `SymbolCollector::finish()` > 3. Extract a function that creates a symbol for macro definition, so we don't > need to call `handleMacroOccurence` and add can add extra macro symbols after > `SymbolCollector` finishes. > > > (1) seems to be the cleanest option, WDYT? (1) sounds good. D52098 Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D52078 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52058: Add Parameters to DW_AT_name Attribute of Template Variables
ormris added inline comments. Comment at: lib/CodeGen/CGDebugInfo.cpp:3126 + } else { +templateParameters = nullptr;//llvm::DINodeArray().get(); + } JDevlieghere wrote: > What's the meaning of this comment? Hmm... That should be removed. Comment at: lib/CodeGen/CGDebugInfo.h:654 + StringRef &LinkageName, + llvm::MDTuple *&templateParameters, + llvm::DIScope *&VDContext); JDevlieghere wrote: > s/templateParameters/TemplateParameters/ (same for the rest of this patch) OK. Will fix. Repository: rC Clang https://reviews.llvm.org/D52058 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D43783: [OpenCL] Remove block invoke function from emitted block literal struct
Anastasia added a comment. Ping! Do you still plan to do this? :) Repository: rC Clang https://reviews.llvm.org/D43783 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51411: [OpenCL] Improve diagnostic of argument in address space conversion builtins
Anastasia accepted this revision. Anastasia added a comment. This revision is now accepted and ready to land. LGTM! https://reviews.llvm.org/D51411 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51789: [clang] Add the no_extern_template attribute
rsmith added a comment. In https://reviews.llvm.org/D51789#1234903, @ldionne wrote: > I think now's a good time to bikeshed the name of the attribute if you have > other suggestions. OK, so the semantics of this attribute are "explicit instantiation declarations or definitions applied to the enclosing class do not apply to this member", right? So it opts the member out of both `extern template` and (non-`extern`) `template`, but only when applied to an enclosing class. Maybe something like `exclude_from_explicit_instantiation`? That's a little longer than I'd like, but if it's going to be hidden behind a macro most of the time I could live with it. Or maybe `no_transitive_instantiation`? That's less explicit about the purpose of the attribute, but is a more comfortable length. Repository: rC Clang https://reviews.llvm.org/D51789 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51789: [clang] Add the no_extern_template attribute
ldionne added a comment. In https://reviews.llvm.org/D51789#1235096, @rsmith wrote: > In https://reviews.llvm.org/D51789#1234903, @ldionne wrote: > > > I think now's a good time to bikeshed the name of the attribute if you have > > other suggestions. > > > OK, so the semantics of this attribute are "explicit instantiation > declarations or definitions applied to the enclosing class do not apply to > this member", right? So it opts the member out of both `extern template` and > (non-`extern`) `template`, but only when applied to an enclosing class. Yes, but it also (obviously) opts the member out when applied to the member itself, not only to an enclosing class. > Maybe something like `exclude_from_explicit_instantiation`? That's a little > longer than I'd like, but if it's going to be hidden behind a macro most of > the time I could live with it. I like this a lot too. I thought about that one and was deterred by the length, but it may be acceptable. Realistically, it's also not an attribute we want people to use most of the time. > Or maybe `no_transitive_instantiation`? That's less explicit about the > purpose of the attribute, but is a more comfortable length. I'm not sure this one describes what the attribute is doing sufficiently closely. Unless we get a better suggestion soonish, I'll change it to `exclude_from_explicit_instantiation` and update the diff. Repository: rC Clang https://reviews.llvm.org/D51789 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52036: [Analyzer] Use diff_plist in tests, NFC
george.karpenkov accepted this revision. george.karpenkov added a comment. This revision is now accepted and ready to land. Thanks! A substitution would probably need to be defined in a different file though. https://reviews.llvm.org/D52036 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51789: [clang] Add the no_extern_template attribute
rsmith added a comment. In https://reviews.llvm.org/D51789#1235100, @ldionne wrote: > In https://reviews.llvm.org/D51789#1235096, @rsmith wrote: > > > OK, so the semantics of this attribute are "explicit instantiation > > declarations or definitions applied to the enclosing class do not apply to > > this member", right? So it opts the member out of both `extern template` > > and (non-`extern`) `template`, but only when applied to an enclosing class. > > > Yes, but it also (obviously) opts the member out when applied to the member > itself, not only to an enclosing class. Assuming I'm understanding you correctly, I don't think the current implementation does that (nor does the documentation change say that), and I think that's a feature not a bug. For example, given: template struct A { [[clang::no_extern_template]] void f() {} void g() {} }; template struct A; // instantiates A and definition of A::g(), does not instantiate definition of A::f() template void A::f(); // instantiates definition of A::f() despite attribute ... the attribute affects the first explicit instantiation but not the second (I think you're saying it should affect both, and make the second explicit instantiation have no effect). I think the current behavior in this patch is appropriate: making the attribute also affect the second case makes it strictly less useful. If you didn't want to actually explictly instantiate `A::f()`, you can just leave out that explicit instantiation. But the current implementation gives you extra capabilities: // A::g() is instantiated somewhere else, A::f() still needs to be implicitly instantiated when used extern template struct A; // A::f() and A::g() are both instantiated somewhere else extern template struct A; extern template void A::f(); You can't do that if an explicit instantiation of a member with the attribute has no effect. Repository: rC Clang https://reviews.llvm.org/D51789 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51946: [analyzer] Remove PseudoConstantAnalysis
george.karpenkov accepted this revision. george.karpenkov added a comment. This revision is now accepted and ready to land. Great, thanks! Seems that your code is a better version of this check. Repository: rC Clang https://reviews.llvm.org/D51946 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D52008: [analyzer] Handle forwarding reference better in ExprMutationAnalyzer.
george.karpenkov added a comment. This looks very useful! Repository: rC Clang https://reviews.llvm.org/D52008 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
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&view=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&view=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&r1=342245&r2=342246&view=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 &getParentMap(); - 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&r1=342245&r2=342246&view=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 &AnalysisDeclContext::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&r1=342245&r2=342246&view=diff == --- cfe/trunk/lib/Analysis/CMakeLists.txt (origin
[PATCH] D51946: [analyzer] Remove PseudoConstantAnalysis
This revision was automatically updated to reflect the committed changes. Closed by commit rL342246: Remove PseudoConstantAnalysis (authored by shuaiwang, committed by ). Herald added a subscriber: llvm-commits. Repository: rL LLVM https://reviews.llvm.org/D51946 Files: cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp cfe/trunk/lib/Analysis/CMakeLists.txt cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp Index: cfe/trunk/lib/Analysis/CMakeLists.txt === --- cfe/trunk/lib/Analysis/CMakeLists.txt +++ cfe/trunk/lib/Analysis/CMakeLists.txt @@ -23,7 +23,6 @@ PostOrderCFGView.cpp PrintfFormatString.cpp ProgramPoint.cpp - PseudoConstantAnalysis.cpp ReachableCode.cpp ScanfFormatString.cpp ThreadSafety.cpp Index: cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp === --- cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp +++ cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp @@ -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 @@ 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 Index: cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h === --- cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h +++ cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h @@ -40,7 +40,6 @@ class LocationContext; class LocationContextManager; class ParentMap; -class PseudoConstantAnalysis; class StackFrameContext; class Stmt; class VarDecl; @@ -84,7 +83,6 @@ 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 @@ bool isCFGBuilt() const { return builtCFG; } ParentMap &getParentMap(); - PseudoConstantAnalysis *getPseudoConstantAnalysis(); using referenced_decls_iterator = const VarDecl * const *; Index: cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp === --- cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp +++ cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp @@ -1,226 +0,0 @@ -//== PseudoConstantAnalysis.cpp - Find Pseudoconstants 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. -// -//===--===// - -#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Stmt.h" -#include "llvm/ADT/SmallPtrSet.h" -#include - -using namespace clang; - -typedef llvm::SmallPtrSet VarDeclSet; - -PseudoConstantAnalysis::PseudoConstantAnalysis(const Stmt *DeclBody) : - DeclBody(DeclBody), Analyzed(false) { - NonConstantsImpl = new VarDeclSet; - UsedVarsImpl = new VarDeclSet; -} - -PseudoConstantAnalysis::~PseudoConstantAnalysis() { - delete (VarDeclSet*)NonConstantsImpl; - delete (VarDeclSet*)UsedVarsImpl; -} - -// Returns true if the given ValueDecl is never written to in the given DeclBody -bool PseudoConstantAnalysis::isPseudoConstant(const VarDecl *VD) { - // Only local and static variables can be pseudoconstants - if (!VD->hasLocalStorage() && !VD->isStaticLocal()) -return false; - - if (!Analyzed) { -RunAnalysis(); -Analyzed = true; - } - - VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl; - - return !NonConstants->count(VD); -} - -// Returns true if the variable was used (self assignments don't count) -bool PseudoConstantAnalysis::wasReferenced(const VarDecl *VD) { - if (!Analyzed) { -RunAnalysis(); -Analyzed = true; - } - - VarDeclSet *UsedVars = (VarDeclSet*)UsedVarsImpl; - - return UsedVars->count(VD); -} - -// Returns a Decl from a (
[PATCH] D43783: [OpenCL] Remove block invoke function from emitted block literal struct
yaxunl added a comment. In https://reviews.llvm.org/D43783#1235090, @Anastasia wrote: > Ping! Do you still plan to do this? :) Sorry I caught up in something else. Since there are some subsequent commits, it may take some efforts to revert it. Repository: rC Clang https://reviews.llvm.org/D43783 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51789: [clang] Add the no_extern_template attribute
ldionne added a comment. In https://reviews.llvm.org/D51789#1235113, @rsmith wrote: > In https://reviews.llvm.org/D51789#1235100, @ldionne wrote: > > > In https://reviews.llvm.org/D51789#1235096, @rsmith wrote: > > > > > OK, so the semantics of this attribute are "explicit instantiation > > > declarations or definitions applied to the enclosing class do not apply > > > to this member", right? So it opts the member out of both `extern > > > template` and (non-`extern`) `template`, but only when applied to an > > > enclosing class. > > > > > > Yes, but it also (obviously) opts the member out when applied to the member > > itself, not only to an enclosing class. > > > Assuming I'm understanding you correctly, I don't think the current > implementation does that (nor does the documentation change say that), and I > think that's a feature not a bug. For example, given: > > template struct A { > [[clang::no_extern_template]] void f() {} > void g() {} > }; > template struct A; // instantiates A and definition of > A::g(), does not instantiate definition of A::f() > template void A::f(); // instantiates definition of A::f() > despite attribute > > > ... the attribute affects the first explicit instantiation but not the second > (I think you're saying it should affect both, and make the second explicit > instantiation have no effect). I think the current behavior in this patch is > appropriate: making the attribute also affect the second case makes it > strictly less useful. [...] Sorry, that's a misunderstanding. We're on the same page. What I meant is that if you apply the attribute to the entity itself but explicitly instantiate the enclosing class, then the entity is not instantiated. It's very obvious, but your previous comment: > So it opts the member out of both `extern template` and (non-`extern`) > `template`, but only when applied to an enclosing class. suggested that it only applied in the following case: template struct Foo { struct __attribute__((no_extern_template)) nested { static void f() { } }; }; template struct Foo; // Foo::nested::f not instantiated Repository: rC Clang https://reviews.llvm.org/D51789 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits