[clang] Introduce paged vector (PR #66430)
@@ -0,0 +1,84 @@ +//===- llvm/unittest/ADT/PagedVectorTest.cpp --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// PagedVector unit tests. +// +//===--===// + +#include "llvm/ADT/PagedVector.h" +#include "gtest/gtest.h" + +namespace llvm { +TEST(PagedVectorTest, FunctionalityTest) { ktf wrote: Thank you for your comments. I have updated the test to check for clear, empty and at. I tried to use EXPECT_DEATH but I get: ``` [WARNING] /Users/ktf/src/sw/SOURCES/llvm-upstream/master/0/third-party/unittest/googletest/src/gtest-death-test.cc:1102:: Death tests use fork(), which is unsafe particularly in a threaded context. For this test, Google Test detected 11 threads. See https://github.com/google/googletest/blob/main/docs/advanced.md#death-tests-and-threads for more explanation and suggested solutions, especially if this is the last message you see before your test times out. ``` could you please advise? https://github.com/llvm/llvm-project/pull/66430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Introduce paged vector (PR #66430)
https://github.com/ktf updated https://github.com/llvm/llvm-project/pull/66430 >From b952f0577dfe8112f394bd5392212f843c0cc86e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+...@users.noreply.github.com> Date: Thu, 14 Sep 2023 21:58:21 +0200 Subject: [PATCH 01/13] Introduce PagedVector class The goal of the class is to be an (almost) drop in replacement for SmallVector and std::vector when those are presized and filled later, as it happens in SourceManager and ASTReader. By splitting the actual vector in pages of the same size and allocating the pages only when they are needed, using this containers reduces the memory usage by a factor 4 for the cases relevant to the ALICE experiment ROOT / cling usage. --- llvm/include/llvm/ADT/PagedVector.h | 96 + 1 file changed, 96 insertions(+) create mode 100644 llvm/include/llvm/ADT/PagedVector.h diff --git a/llvm/include/llvm/ADT/PagedVector.h b/llvm/include/llvm/ADT/PagedVector.h new file mode 100644 index 000..dab0d249aa706e4 --- /dev/null +++ b/llvm/include/llvm/ADT/PagedVector.h @@ -0,0 +1,96 @@ +//===- llvm/ADT/PagedVector.h - 'Lazyly allocated' vectors *- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file defines the PagedVector class. +// +//===--===// +#ifndef LLVM_ADT_PAGEDVECTOR_H +#define LLVM_ADT_PAGEDVECTOR_H + +#include + +// Notice that this does not have iterators, because if you +// have iterators it probably means you are going to touch +// all the memory in any case, so better use a std::vector in +// the first place. +template class PagedVector { + size_t Size = 0; + // Index of where to find a given page in the data + mutable std::vector Lookup; + // Actual data + mutable std::vector Data; + +public: + // Add a range to the vector. + // When vector is accessed, it will call the callback to fill the range + // with data. + + // Lookup an element at position i. + // If the given range is not filled, it will be filled. + // If the given range is filled, return the element. + T [](int Index) const { return at(Index); } + + T (int Index) const { +auto = Lookup[Index / PAGE_SIZE]; +// If the range is not filled, fill it +if (PageId == -1) { + int OldSize = Data.size(); + PageId = OldSize / PAGE_SIZE; + // Allocate the memory + Data.resize(OldSize + PAGE_SIZE); + // Fill the whole capacity with empty elements + for (int I = 0; I < PAGE_SIZE; ++I) { +Data[I + OldSize] = T(); + } +} +// Return the element +return Data[Index % PAGE_SIZE + PAGE_SIZE * PageId]; + } + + // Return the size of the vector + size_t capacity() const { return Lookup.size() * PAGE_SIZE; } + + size_t size() const { return Size; } + + // Expands the vector to the given size. + // If the vector is already bigger, does nothing. + void expand(size_t NewSize) { +// You cannot shrink the vector, otherwise +// you would have to invalidate +assert(NewSize >= Size); +if (NewSize <= Size) { + return; +} +if (NewSize <= capacity()) { + Size = NewSize; + return; +} +auto Pages = NewSize / PAGE_SIZE; +auto Remainder = NewSize % PAGE_SIZE; +if (Remainder) { + Pages += 1; +} +assert(Pages > Lookup.size()); +Lookup.resize(Pages, -1); +Size = NewSize; + } + + // Return true if the vector is empty + bool empty() const { return Size == 0; } + /// Clear the vector + void clear() { +Size = 0; +Lookup.clear(); +Data.clear(); + } + + std::vector const () const { return Data; } +}; + +#endif // LLVM_ADT_PAGEDVECTOR_H >From f0c75c8af0fea27b5b758e2e5775787f33595de3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+...@users.noreply.github.com> Date: Thu, 14 Sep 2023 22:20:29 +0200 Subject: [PATCH 02/13] Use PagedVector to reduce memory usage of sparsely populated vectors --- clang/include/clang/Basic/SourceManager.h | 3 ++- clang/include/clang/Serialization/ASTReader.h | 5 +++-- clang/lib/Basic/SourceManager.cpp | 12 ++-- clang/lib/Serialization/ASTReader.cpp | 9 + 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 2f846502d6f3327..b1942a3d86afc37 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -43,6 +43,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/PagedVector.h" #include "llvm/ADT/PointerIntPair.h" #include
[clang] Fix math-errno issue (PR #66381)
https://github.com/zahiraam unassigned https://github.com/llvm/llvm-project/pull/66381 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix math-errno issue (PR #66381)
https://github.com/zahiraam unassigned https://github.com/llvm/llvm-project/pull/66381 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix math-errno issue (PR #66381)
https://github.com/zahiraam unassigned https://github.com/llvm/llvm-project/pull/66381 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix math-errno issue (PR #66381)
https://github.com/zahiraam unassigned https://github.com/llvm/llvm-project/pull/66381 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Handle AttributedStmts (PR #66495)
https://github.com/cor3ntin approved this pull request. https://github.com/llvm/llvm-project/pull/66495 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Handle AttributedStmts (PR #66495)
@@ -628,6 +630,12 @@ bool ByteCodeStmtGen::visitAsmStmt(const AsmStmt *S) { return this->emitInvalid(S); } +template +bool ByteCodeStmtGen::visitAttributedStmt(const AttributedStmt *S) { + // Ignore all attributes. cor3ntin wrote: At compile time, i suppose so! https://github.com/llvm/llvm-project/pull/66495 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Introduce paged vector (PR #66430)
https://github.com/shafik commented: Thank you for this contributions, I just have one comment so far on testing. We should make sure any new ADT is very well tested before landing it. https://github.com/llvm/llvm-project/pull/66430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Introduce paged vector (PR #66430)
https://github.com/shafik edited https://github.com/llvm/llvm-project/pull/66430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Introduce paged vector (PR #66430)
@@ -0,0 +1,84 @@ +//===- llvm/unittest/ADT/PagedVectorTest.cpp --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// PagedVector unit tests. +// +//===--===// + +#include "llvm/ADT/PagedVector.h" +#include "gtest/gtest.h" + +namespace llvm { +TEST(PagedVectorTest, FunctionalityTest) { shafik wrote: I don't see tests for `clear()`, `empty()` or `at(..)` and I think we should have `EXPECT_DEATH` tests for assertions that are testable. https://github.com/llvm/llvm-project/pull/66430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D159522: [Clang][C] Fixed a bug where we reject an _Atomic qualified integer in a switch statment
to268 created this revision. to268 added a reviewer: aaron.ballman. to268 added a project: clang. Herald added a project: All. to268 requested review of this revision. Herald added a subscriber: cfe-commits. We are currently rejecting an _Atomic qualified integer in a switch statment. This fixes the issue by doing an Lvalue conversion before trying to match on the type. Fixes #65557 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D159522 Files: clang/lib/Sema/SemaOverload.cpp clang/test/Sema/atomic-expr.c Index: clang/test/Sema/atomic-expr.c === --- clang/test/Sema/atomic-expr.c +++ clang/test/Sema/atomic-expr.c @@ -216,3 +216,9 @@ struct T { int a; }; (void)(_Atomic struct T)s; // expected-error {{used type 'struct T' where arithmetic or pointer type is required}} } + +// Test if we can handle an _Atomic qualified integer in a switch statement. +void func_19(void) { + _Atomic int a = 0; + switch (a) { } +} Index: clang/lib/Sema/SemaOverload.cpp === --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -6302,8 +6302,10 @@ From = result.get(); } + // Try converting the expression to an Lvalue first, to get rid of qualifiers. + ExprResult Converted = DefaultLvalueConversion(From); + QualType T = Converted.isUsable() ? Converted.get()->getType() : QualType(); // If the expression already has a matching type, we're golden. - QualType T = From->getType(); if (Converter.match(T)) return DefaultLvalueConversion(From); Index: clang/test/Sema/atomic-expr.c === --- clang/test/Sema/atomic-expr.c +++ clang/test/Sema/atomic-expr.c @@ -216,3 +216,9 @@ struct T { int a; }; (void)(_Atomic struct T)s; // expected-error {{used type 'struct T' where arithmetic or pointer type is required}} } + +// Test if we can handle an _Atomic qualified integer in a switch statement. +void func_19(void) { + _Atomic int a = 0; + switch (a) { } +} Index: clang/lib/Sema/SemaOverload.cpp === --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -6302,8 +6302,10 @@ From = result.get(); } + // Try converting the expression to an Lvalue first, to get rid of qualifiers. + ExprResult Converted = DefaultLvalueConversion(From); + QualType T = Converted.isUsable() ? Converted.get()->getType() : QualType(); // If the expression already has a matching type, we're golden. - QualType T = From->getType(); if (Converter.match(T)) return DefaultLvalueConversion(From); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D147844: [clang][Sema]Print diagnostic warning about precedence when integer expression is used without parentheses in an conditional operator expression
MaskRay added a comment. FWIW: adding parentheses for expressions, such as `overflow = (4608 * 1024 * 1024) ? 4608 * 1024 * 1024 : 0;`, and `results.reason = (actions & _UA_SEARCH_PHASE) ? ... : ...`, looks unnatural and is too noisy to me. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D147844/new/ https://reviews.llvm.org/D147844 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][deps] Load module map file from PCM (PR #66389)
@@ -1307,6 +1307,9 @@ void ModuleMap::setInferredModuleAllowedBy(Module *M, std::error_code ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl ) { + FileManager = SourceMgr.getFileManager(); + FM.makeAbsolutePath(Path); benlangmuir wrote: Is the idea that because the paths used by the scanner is now indirected through the (implicit) pcm that whatever ASTWriter does to make the path relative will apply to the explicit module invocation? Before your current changes the scanner was using `canonicalizeModuleMapPath` directly on the path in the invocation, which is what I was naively thinking of. https://github.com/llvm/llvm-project/pull/66389 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D159519: [clang][AST][ASTImporter] improve AST comparasion on VarDecl & GotoStmt
jcsxky updated this revision to Diff 556861. jcsxky added a comment. update according to llvm convention. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D159519/new/ https://reviews.llvm.org/D159519 Files: clang/lib/AST/ASTStructuralEquivalence.cpp clang/unittests/AST/StructuralEquivalenceTest.cpp Index: clang/unittests/AST/StructuralEquivalenceTest.cpp === --- clang/unittests/AST/StructuralEquivalenceTest.cpp +++ clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -1,5 +1,6 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTStructuralEquivalence.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Frontend/ASTUnit.h" @@ -1801,10 +1802,10 @@ TEST_F(StructuralEquivalenceCacheTest, ReturnStmtNonEq) { auto TU = makeTuDecls( R"( - bool x(){ return true; } + bool x() { return true; } )", R"( - bool x(){ return false; } + bool x() { return false; } )", Lang_CXX03); @@ -1817,6 +1818,60 @@ } +TEST_F(StructuralEquivalenceCacheTest, VarDeclNoEq) { + auto TU = makeTuDecls( + R"( + int p; + )", + R"( + int q; + )", + Lang_CXX03); + + StructuralEquivalenceContext Ctx( + get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); + + auto Var = findDeclPair(TU, varDecl()); + EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second)); +} + +TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) { + auto TU = makeTuDecls( + R"( + int p; + )", + R"( + static int p; + )", + Lang_CXX03); + + StructuralEquivalenceContext Ctx( + get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); + + auto Var = findDeclPair(TU, varDecl()); + EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second)); +} + +TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) { + auto TU = makeTuDecls( + R"( + int p = 1; + )", + R"( + int p = 2; + )", + Lang_CXX03); + + StructuralEquivalenceContext Ctx( + get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); + + auto Var = findDeclPair(TU, varDecl()); + EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second)); +} + TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) { auto TU = makeTuDecls( R"( @@ -2320,5 +2375,23 @@ EXPECT_TRUE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceCacheTest, GotoStmtNoEq) { + auto S = makeStmts( + R"( + void foo() { +goto L1; +L1: foo(); + } + )", + R"( + void foo() { +goto L2; +L2: foo(); + } + )", + Lang_CXX03, gotoStmt()); + EXPECT_FALSE(testStructuralMatch(S)); +} + } // end namespace ast_matchers } // end namespace clang Index: clang/lib/AST/ASTStructuralEquivalence.cpp === --- clang/lib/AST/ASTStructuralEquivalence.cpp +++ clang/lib/AST/ASTStructuralEquivalence.cpp @@ -277,6 +277,17 @@ bool IsStmtEquivalent(const Stmt *S1, const Stmt *S2) { return true; } + bool IsStmtEquivalent(const GotoStmt *S1, const GotoStmt *S2) { +LabelDecl *L1 = S1->getLabel(); +LabelDecl *L2 = S2->getLabel(); +if (!L1 || !L2) + return L1 == L2; + +IdentifierInfo *Name1 = L1->getIdentifier(); +IdentifierInfo *Name2 = L2->getIdentifier(); +return ::IsStructurallyEquivalent(Name1, Name2); + } + bool IsStmtEquivalent(const SourceLocExpr *E1, const SourceLocExpr *E2) { return E1->getIdentKind() == E2->getIdentKind(); } @@ -1295,6 +1306,22 @@ return true; } +static bool IsStructurallyEquivalent(StructuralEquivalenceContext , + VarDecl *D1, VarDecl *D2) { + if (D1->getStorageClass() != D2->getStorageClass()) +return false; + + IdentifierInfo *Name1 = D1->getIdentifier(); + IdentifierInfo *Name2 = D2->getIdentifier(); + if (!::IsStructurallyEquivalent(Name1, Name2)) +return false; + + if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) +return false; + + return IsStructurallyEquivalent(Context, D1->getInit(), D2->getInit()); +} + static bool IsStructurallyEquivalent(StructuralEquivalenceContext , FieldDecl *Field1, FieldDecl *Field2, QualType Owner2Type) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][deps] Load module map file from PCM (PR #66389)
@@ -1307,6 +1307,9 @@ void ModuleMap::setInferredModuleAllowedBy(Module *M, std::error_code ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl ) { + FileManager = SourceMgr.getFileManager(); + FM.makeAbsolutePath(Path); jansvoboda11 wrote: I don't understand how would this impact explicit module invocations? These can still use relative module map paths, it's just that the compiler will use the absolute canonical path internally (IIUC in an non-observable way). https://github.com/llvm/llvm-project/pull/66389 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [RISCV] Install sifive_vector.h to riscv-resource-headers (PR #66330)
@@ -623,6 +623,11 @@ install( EXCLUDE_FROM_ALL COMPONENT riscv-resource-headers) +install( topperc wrote: Aren't we also missing `sifive_files` from `add_header_target("riscv-resource-headers" "${riscv_files};${riscv_generated_files}")`? Is there any reason to have `sifive_files`? Should we put sifive_vector.h in `riscv_files`? https://github.com/llvm/llvm-project/pull/66330 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Prevent calling the projection more than three times (PR #66315)
https://github.com/pandaninjas updated https://github.com/llvm/llvm-project/pull/66315 >From ead65bfcb70be46788bc9e88c891e7ae7f91b8d7 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 13 Sep 2023 17:38:17 -0700 Subject: [PATCH 1/8] [libc++] Prevent calling the projection more than three times --- libcxx/include/__algorithm/ranges_clamp.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 9613f7f37720a6c..ca46675eb4b3041 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,9 +37,10 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); -if (std::invoke(__comp, std::invoke(__proj, __value), std::invoke(__proj, __low))) +auto = std::invoke(__proj, __value); +if (std::invoke(__comp, projection, std::invoke(__proj, __low))) return __low; -else if (std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __value))) +else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) return __high; else return __value; >From c18d60870ac342a95a5528396a8e0c7b91717cbb Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 13 Sep 2023 18:56:44 -0700 Subject: [PATCH 2/8] [libc++] Run clang-format on file --- libcxx/include/__algorithm/ranges_clamp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index ca46675eb4b3041..3469a6419b2270f 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,7 +37,7 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); -auto = std::invoke(__proj, __value); +auto& projection = std::invoke(__proj, __value); if (std::invoke(__comp, projection, std::invoke(__proj, __low))) return __low; else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) >From b40e791f0e9fedbb19936851e1e71decf00331fa Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano Date: Wed, 13 Sep 2023 19:11:20 -0700 Subject: [PATCH 3/8] [libcxx] CamelCase projection and make variable name more descriptive --- libcxx/include/__algorithm/ranges_clamp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 3469a6419b2270f..3adb5fa828e1ee5 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,7 +37,7 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); -auto& projection = std::invoke(__proj, __value); +auto& ValueProjection = std::invoke(__proj, __value); if (std::invoke(__comp, projection, std::invoke(__proj, __low))) return __low; else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) >From a8907624defa4cc4f47520a2d93a8bd042816aa2 Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano Date: Wed, 13 Sep 2023 19:11:47 -0700 Subject: [PATCH 4/8] [libcxx] properly change variable name --- libcxx/include/__algorithm/ranges_clamp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 3adb5fa828e1ee5..3d7a224b3649a3f 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -38,9 +38,9 @@ struct __fn { "Bad bounds passed to std::ranges::clamp"); auto& ValueProjection = std::invoke(__proj, __value); -if (std::invoke(__comp, projection, std::invoke(__proj, __low))) +if (std::invoke(__comp, ValueProjection, std::invoke(__proj, __low))) return __low; -else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) +else if (std::invoke(__comp, std::invoke(__proj, __high), ValueProjection)) return __high; else return __value; >From 15d3b2b79fbd61f97b0312e0913cede36b5b202d Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano Date: Thu, 14 Sep 2023 10:37:34 -0700 Subject: [PATCH 5/8] Apply suggestions from code review --- libcxx/include/__algorithm/ranges_clamp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 3d7a224b3649a3f..a97538e4c0e3f65 100644 ---
[clang-tools-extra] [libc++] Prevent calling the projection more than three times (PR #66315)
https://github.com/pandaninjas updated https://github.com/llvm/llvm-project/pull/66315 >From ead65bfcb70be46788bc9e88c891e7ae7f91b8d7 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 13 Sep 2023 17:38:17 -0700 Subject: [PATCH 1/8] [libc++] Prevent calling the projection more than three times --- libcxx/include/__algorithm/ranges_clamp.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 9613f7f37720a6c..ca46675eb4b3041 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,9 +37,10 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); -if (std::invoke(__comp, std::invoke(__proj, __value), std::invoke(__proj, __low))) +auto = std::invoke(__proj, __value); +if (std::invoke(__comp, projection, std::invoke(__proj, __low))) return __low; -else if (std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __value))) +else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) return __high; else return __value; >From c18d60870ac342a95a5528396a8e0c7b91717cbb Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 13 Sep 2023 18:56:44 -0700 Subject: [PATCH 2/8] [libc++] Run clang-format on file --- libcxx/include/__algorithm/ranges_clamp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index ca46675eb4b3041..3469a6419b2270f 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,7 +37,7 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); -auto = std::invoke(__proj, __value); +auto& projection = std::invoke(__proj, __value); if (std::invoke(__comp, projection, std::invoke(__proj, __low))) return __low; else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) >From b40e791f0e9fedbb19936851e1e71decf00331fa Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano Date: Wed, 13 Sep 2023 19:11:20 -0700 Subject: [PATCH 3/8] [libcxx] CamelCase projection and make variable name more descriptive --- libcxx/include/__algorithm/ranges_clamp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 3469a6419b2270f..3adb5fa828e1ee5 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,7 +37,7 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); -auto& projection = std::invoke(__proj, __value); +auto& ValueProjection = std::invoke(__proj, __value); if (std::invoke(__comp, projection, std::invoke(__proj, __low))) return __low; else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) >From a8907624defa4cc4f47520a2d93a8bd042816aa2 Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano Date: Wed, 13 Sep 2023 19:11:47 -0700 Subject: [PATCH 4/8] [libcxx] properly change variable name --- libcxx/include/__algorithm/ranges_clamp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 3adb5fa828e1ee5..3d7a224b3649a3f 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -38,9 +38,9 @@ struct __fn { "Bad bounds passed to std::ranges::clamp"); auto& ValueProjection = std::invoke(__proj, __value); -if (std::invoke(__comp, projection, std::invoke(__proj, __low))) +if (std::invoke(__comp, ValueProjection, std::invoke(__proj, __low))) return __low; -else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) +else if (std::invoke(__comp, std::invoke(__proj, __high), ValueProjection)) return __high; else return __value; >From 15d3b2b79fbd61f97b0312e0913cede36b5b202d Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano Date: Thu, 14 Sep 2023 10:37:34 -0700 Subject: [PATCH 5/8] Apply suggestions from code review --- libcxx/include/__algorithm/ranges_clamp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 3d7a224b3649a3f..a97538e4c0e3f65 100644 ---
[clang] [clang][doc] Add documentation for the ASTs used to represent C++ templates (PR #66436)
tahonermann wrote: Hi, Scott! It's nice to see you pop up here! :) I'm a little concerned about maintenance of this documentation going forward. As you know, the Clang AST is not intended to be stable and, even though I don't expect dramatic changes to how templates are represented, it will take some effort to ensure the code and the documentation stay in sync. Do you have any thoughts regarding how we can implement an automated process to ensure the documentation is updated? For anyone not familiar, [ded](https://github.com/smcpeak/ded) is a diagram editor that Scott developed. I've used it in the past and found it to be lightweight and easy to use. https://github.com/llvm/llvm-project/pull/66436 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [RISCV] Support predefined marcro __riscv_misaligned_{fast,avoid}. (PR #65756)
@@ -1220,3 +1220,15 @@ // RUN: -march=rv64i_zve32x_zvkt1p0 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZVKT-EXT %s // CHECK-ZVKT-EXT: __riscv_zvkt 100{{$}} + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32i -x c -E -dM %s \ topperc wrote: Should we update this test file to use `--target=` for all test cases in another patch? Getting a review comment for copy and pasting from an existing test case is frustrating. https://github.com/llvm/llvm-project/pull/65756 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Inliner] Improve attribute propagation to callsites when inlining. (PR #66036)
goldsteinn wrote: > It occurs to me that the current return attribute propagation is currently > buggy for poison-generating attributes: https://llvm.godbolt.org/z/x8n18q9Mj > > In this case the argument to use() will now be poison as well, while before > inlining only the return value was poison. > > This code needs to distinguish poison and UB generating attributes. Good catch. I think this means basically `nonnull`, `noundef`, and `align` can only be propagated if there are no other uses in to-be-inlined function. That sound right or do you see any more robust way forward? https://github.com/llvm/llvm-project/pull/66036 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Inliner] Improve attribute propagation to callsites when inlining. (PR #66036)
nikic wrote: It occurs to me that the current return attribute propagation is currently buggy for poison-generating attributes: https://llvm.godbolt.org/z/x8n18q9Mj In this case the argument to use() will now be poison as well, while before inlining only the return value was poison. This code needs to distinguish poison and UB generating attributes. https://github.com/llvm/llvm-project/pull/66036 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-transformer] Allow stencils to read from system headers. (PR #66480)
https://github.com/ymand approved this pull request. Thanks! https://github.com/llvm/llvm-project/pull/66480 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-cl] Fix for __FUNCTION__ in c++. (PR #66120)
@@ -2218,6 +2218,9 @@ printTo(raw_ostream , ArrayRef Args, const PrintingPolicy , } else { if (!FirstArg) OS << Comma; + //if (Argument.getKind() == TemplateArgument::Type) + // OS << "class "; + zahiraam wrote: TODO: if we go with this solution, this needs to happen here, but it should be under some conditions? https://github.com/llvm/llvm-project/pull/66120 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e edited https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -567,6 +567,58 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(S.getFunctionScopes().back()); + + auto captureVar = [&](VarDecl *VD) { +LSI->addCapture(VD, /*isBlock=*/false, /*isByref=*/false, +/*isNested=*/false, VD->getBeginLoc(), SourceLocation(), +VD->getType(), /*Invalid=*/false); + }; + 0x59616e wrote: I couldn't find where the logic is in `LambdaScopeForCallOperatorInstantiationRAII`. Would you mind giving more hints ? Thanks. https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] e8b1af9 - Fix clang-tidy sphinx docs
Author: Aaron Ballman Date: 2023-09-15T10:11:10-04:00 New Revision: e8b1af9a55764e91015a4f9bbabdb39cf95caf94 URL: https://github.com/llvm/llvm-project/commit/e8b1af9a55764e91015a4f9bbabdb39cf95caf94 DIFF: https://github.com/llvm/llvm-project/commit/e8b1af9a55764e91015a4f9bbabdb39cf95caf94.diff LOG: Fix clang-tidy sphinx docs This addresses issues found by: https://lab.llvm.org/buildbot/#/builders/115/builds/53446 Added: Modified: clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst Removed: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst index 8b6749938957e86..a8293297c121211 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst @@ -7,6 +7,7 @@ Detects unspecified behavior about equality comparison between pointer to member virtual function and anything other than null-pointer-constant. .. code-block:: c++ + struct A { void f1(); void f2(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Setup whitespace detection and clang-format as Github actions (PR #66509)
https://github.com/ldionne closed https://github.com/llvm/llvm-project/pull/66509 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Setup whitespace detection and clang-format as Github actions (PR #66509)
ldionne wrote: I guess I'll close this and reopen when I have something that actually works for handling trailing whitespace. https://github.com/llvm/llvm-project/pull/66509 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Diagnostics] Highlight code snippets (PR #66514)
llvmbot wrote: @llvm/pr-subscribers-clang Changes Add some primitive syntax highlighting to our code snippet output. Before: ![Screenshot from 2023-09-15 16-00-23](https://github.com/llvm/llvm-project/assets/49720664/8e43767a-d939-4c9f-ac2d-65e2df5de1f2) After: ![Screenshot from 2023-09-15 15-55-35](https://github.com/llvm/llvm-project/assets/49720664/714b536c-377f-4a0d-921c-b103b90c5706) _Obviously_ this is kinda WIP and more of a hack in general, but IMO it increases readability of the source snippets (which people look at highlighted all the time anyway...) and LLDB does something similar, so let's see. -- Full diff: https://github.com/llvm/llvm-project/pull/66514.diff 5 Files Affected: - (added) clang/include/clang/Frontend/CodeSnippetHighlighter.h (+46) - (modified) clang/include/clang/Frontend/TextDiagnostic.h (+3-1) - (modified) clang/lib/Frontend/CMakeLists.txt (+1) - (added) clang/lib/Frontend/CodeSnippetHighlighter.cpp (+120) - (modified) clang/lib/Frontend/TextDiagnostic.cpp (+29-2) diff --git a/clang/include/clang/Frontend/CodeSnippetHighlighter.h b/clang/include/clang/Frontend/CodeSnippetHighlighter.h new file mode 100644 index 000..776954b59e2e1a8 --- /dev/null +++ b/clang/include/clang/Frontend/CodeSnippetHighlighter.h @@ -0,0 +1,46 @@ +//===--- CodeSnippetHighlighter.h - Code snippet highlighting ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_FRONTEND_CODESNIPPETHIGHLIGHTER_H +#define LLVM_CLANG_FRONTEND_CODESNIPPETHIGHLIGHTER_H + +#include quot;clang/Basic/LangOptions.hquot; +#include quot;llvm/ADT/SmallSet.hquot; +#include quot;llvm/Support/raw_ostream.hquot; +#include lt;vectorgt; + +namespace clang { + +struct StyleRange { + unsigned Start; + unsigned End; + const enum llvm::raw_ostream::Colors c; +}; + +class CodeSnippetHighlighter final { +public: + CodeSnippetHighlighter() = default; + + /// Produce StyleRanges for the given line. + /// The returned vector contains non-overlapping style ranges. They are sorted + /// from beginning of the line to the end. + std::vectorlt;StyleRangegt; highlightLine(llvm::StringRef SourceLine, +const LangOptions amp;LangOpts); + +private: + bool Initialized = false; + /// Fills Keywords and Literals. + void ensureTokenData(); + + llvm::SmallSetlt;StringRef, 12gt; Keywords; + llvm::SmallSetlt;StringRef, 12gt; Literals; +}; + +} // namespace clang + +#endif diff --git a/clang/include/clang/Frontend/TextDiagnostic.h b/clang/include/clang/Frontend/TextDiagnostic.h index 7eb0ab0cdc9bca8..39e09fe553dd4b9 100644 --- a/clang/include/clang/Frontend/TextDiagnostic.h +++ b/clang/include/clang/Frontend/TextDiagnostic.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H #define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H +#include quot;clang/Frontend/CodeSnippetHighlighter.hquot; #include quot;clang/Frontend/DiagnosticRenderer.hquot; namespace clang { @@ -33,6 +34,7 @@ namespace clang { /// printing coming out of libclang. class TextDiagnostic : public DiagnosticRenderer { raw_ostream amp;OS; + CodeSnippetHighlighter SnippetHighlighter; public: TextDiagnostic(raw_ostream amp;OS, @@ -104,7 +106,7 @@ class TextDiagnostic : public DiagnosticRenderer { ArrayReflt;FixItHintgt; Hints); void emitSnippet(StringRef SourceLine, unsigned MaxLineNoDisplayWidth, - unsigned LineNo); + unsigned LineNo, bool A, const SourceManager amp;SM); void emitParseableFixits(ArrayReflt;FixItHintgt; Hints, const SourceManager amp;SM); }; diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index 1e5f0a859dfd568..f3547f771593093 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -42,6 +42,7 @@ add_clang_library(clangFrontend TextDiagnosticPrinter.cpp VerifyDiagnosticConsumer.cpp InterfaceStubFunctionsConsumer.cpp + CodeSnippetHighlighter.cpp DEPENDS ClangDriverOptions diff --git a/clang/lib/Frontend/CodeSnippetHighlighter.cpp b/clang/lib/Frontend/CodeSnippetHighlighter.cpp new file mode 100644 index 000..829a533ad2692e5 --- /dev/null +++ b/clang/lib/Frontend/CodeSnippetHighlighter.cpp @@ -0,0 +1,120 @@ + +#include quot;clang/Frontend/CodeSnippetHighlighter.hquot; +#include quot;clang/Basic/DiagnosticOptions.hquot; +#include quot;clang/Basic/SourceManager.hquot; +#include quot;clang/Lex/Lexer.hquot; +#include quot;llvm/Support/raw_ostream.hquot; + +using namespace clang; + +void CodeSnippetHighlighter::ensureTokenData() { + if (Initialized) +return; + + // List of keywords, literals and types
[clang] [clang][Diagnostics] Highlight code snippets (PR #66514)
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/66514 Add some primitive syntax highlighting to our code snippet output. Before: ![Screenshot from 2023-09-15 16-00-23](https://github.com/llvm/llvm-project/assets/49720664/8e43767a-d939-4c9f-ac2d-65e2df5de1f2) After: ![Screenshot from 2023-09-15 15-55-35](https://github.com/llvm/llvm-project/assets/49720664/714b536c-377f-4a0d-921c-b103b90c5706) _Obviously_ this is kinda WIP and more of a hack in general, but IMO it increases readability of the source snippets (which people look at highlighted all the time anyway...) and LLDB does something similar, so let's see. >From b4f4d29c8780752629f78b4debb86bd9f9dff0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 15 Sep 2023 15:51:39 +0200 Subject: [PATCH] [clang][Diagnostics] Highlight code snippets Add some primitive syntax highlighting to our code snippet output. --- .../clang/Frontend/CodeSnippetHighlighter.h | 46 +++ clang/include/clang/Frontend/TextDiagnostic.h | 4 +- clang/lib/Frontend/CMakeLists.txt | 1 + clang/lib/Frontend/CodeSnippetHighlighter.cpp | 120 ++ clang/lib/Frontend/TextDiagnostic.cpp | 31 - 5 files changed, 199 insertions(+), 3 deletions(-) create mode 100644 clang/include/clang/Frontend/CodeSnippetHighlighter.h create mode 100644 clang/lib/Frontend/CodeSnippetHighlighter.cpp diff --git a/clang/include/clang/Frontend/CodeSnippetHighlighter.h b/clang/include/clang/Frontend/CodeSnippetHighlighter.h new file mode 100644 index 000..776954b59e2e1a8 --- /dev/null +++ b/clang/include/clang/Frontend/CodeSnippetHighlighter.h @@ -0,0 +1,46 @@ +//===--- CodeSnippetHighlighter.h - Code snippet highlighting ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_FRONTEND_CODESNIPPETHIGHLIGHTER_H +#define LLVM_CLANG_FRONTEND_CODESNIPPETHIGHLIGHTER_H + +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace clang { + +struct StyleRange { + unsigned Start; + unsigned End; + const enum llvm::raw_ostream::Colors c; +}; + +class CodeSnippetHighlighter final { +public: + CodeSnippetHighlighter() = default; + + /// Produce StyleRanges for the given line. + /// The returned vector contains non-overlapping style ranges. They are sorted + /// from beginning of the line to the end. + std::vector highlightLine(llvm::StringRef SourceLine, +const LangOptions ); + +private: + bool Initialized = false; + /// Fills Keywords and Literals. + void ensureTokenData(); + + llvm::SmallSet Keywords; + llvm::SmallSet Literals; +}; + +} // namespace clang + +#endif diff --git a/clang/include/clang/Frontend/TextDiagnostic.h b/clang/include/clang/Frontend/TextDiagnostic.h index 7eb0ab0cdc9bca8..39e09fe553dd4b9 100644 --- a/clang/include/clang/Frontend/TextDiagnostic.h +++ b/clang/include/clang/Frontend/TextDiagnostic.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H #define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H +#include "clang/Frontend/CodeSnippetHighlighter.h" #include "clang/Frontend/DiagnosticRenderer.h" namespace clang { @@ -33,6 +34,7 @@ namespace clang { /// printing coming out of libclang. class TextDiagnostic : public DiagnosticRenderer { raw_ostream + CodeSnippetHighlighter SnippetHighlighter; public: TextDiagnostic(raw_ostream , @@ -104,7 +106,7 @@ class TextDiagnostic : public DiagnosticRenderer { ArrayRef Hints); void emitSnippet(StringRef SourceLine, unsigned MaxLineNoDisplayWidth, - unsigned LineNo); + unsigned LineNo, bool A, const SourceManager ); void emitParseableFixits(ArrayRef Hints, const SourceManager ); }; diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index 1e5f0a859dfd568..f3547f771593093 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -42,6 +42,7 @@ add_clang_library(clangFrontend TextDiagnosticPrinter.cpp VerifyDiagnosticConsumer.cpp InterfaceStubFunctionsConsumer.cpp + CodeSnippetHighlighter.cpp DEPENDS ClangDriverOptions diff --git a/clang/lib/Frontend/CodeSnippetHighlighter.cpp b/clang/lib/Frontend/CodeSnippetHighlighter.cpp new file mode 100644 index 000..829a533ad2692e5 --- /dev/null +++ b/clang/lib/Frontend/CodeSnippetHighlighter.cpp @@ -0,0 +1,120 @@ + +#include "clang/Frontend/CodeSnippetHighlighter.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,312 @@ +//===- StdVariantChecker.cpp -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "clang/AST/Type.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" + +#include "TaggedUnionModeling.h" + +using namespace clang; +using namespace ento; +using namespace variant_modeling; + +REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType) + +namespace clang { +namespace ento { +namespace variant_modeling { + +// Returns the CallEvent representing the caller of the function +// It is needed because the CallEvent class does not contain enough information +// to tell who called it. Checker context is needed. +CallEventRef<> getCaller(const CallEvent , const ProgramStateRef ) { + const auto *CallLocationContext = Call.getLocationContext(); + if (!CallLocationContext) { +return nullptr; + } + + if (CallLocationContext->inTopFrame()) { +return nullptr; + } + const auto *CallStackFrameContext = CallLocationContext->getStackFrame(); + if (!CallStackFrameContext) { +return nullptr; + } + + CallEventManager = State->getStateManager().getCallEventManager(); + return CEMgr.getCaller(CallStackFrameContext, State); +} + +const CXXConstructorDecl * +getConstructorDeclarationForCall(const CallEvent ) { + const auto *ConstructorCall = dyn_cast(); + if (!ConstructorCall) { +return nullptr; + } + return ConstructorCall->getDecl(); +} + +bool isCopyConstructorCall(const CallEvent ) { + const CXXConstructorDecl *ConstructorDecl = + getConstructorDeclarationForCall(Call); + if (!ConstructorDecl) { +return false; + } + return ConstructorDecl->isCopyConstructor(); +} + +bool isCopyAssignmentCall(const CallEvent ) { + const Decl *CopyAssignmentDecl = Call.getDecl(); + if (!CopyAssignmentDecl) { +return false; + } + const auto *AsMethodDecl = dyn_cast(CopyAssignmentDecl); + if (!AsMethodDecl) { +return false; + } + return AsMethodDecl->isCopyAssignmentOperator(); +} + +bool isMoveConstructorCall(const CallEvent ) { + const CXXConstructorDecl *ConstructorDecl = + getConstructorDeclarationForCall(Call); + if (!ConstructorDecl) { +return false; + } + return ConstructorDecl->isMoveConstructor(); +} + +bool isMoveAssignmentCall(const CallEvent ) { + const Decl *CopyAssignmentDecl = Call.getDecl(); + if (!CopyAssignmentDecl) { +return false; + } + const auto *AsMethodDecl = dyn_cast(CopyAssignmentDecl); + if (!AsMethodDecl) { +return false; + } + return AsMethodDecl->isMoveAssignmentOperator(); +} + +const TemplateArgument (const CallEvent ) { + const CallExpr *CE = cast(Call.getOriginExpr()); + const FunctionDecl *FD = CE->getDirectCallee(); + assert(1 <= FD->getTemplateSpecializationArgs()->asArray().size() && + "std::get should have at least 1 template argument!"); + return FD->getTemplateSpecializationArgs()->asArray()[0]; +} + +bool isStdType(const Type *Type, const std::string ) { + auto *Decl = Type->getAsRecordDecl(); + if (!Decl) { +return false; + } + + return (Decl->getNameAsString() == TypeName) && Decl->isInStdNamespace(); +} + +bool isStdVariant(const Type *Type) { + return isStdType(Type, std::string("variant")); +} + +bool calledFromSystemHeader(const CallEvent , +const ProgramStateRef ) { + auto Caller = getCaller(Call, State); + if (Caller) { +return Caller->isInSystemHeader(); + } + return false; +} + +bool calledFromSystemHeader(const CallEvent , CheckerContext ) { + return calledFromSystemHeader(Call, C.getState()); +} + +} // end of namespace variant_modeling +} // end of namespace ento +} // end of namespace clang + +static ArrayRef +getTemplateArgsFromVariant(const Type *VariantType) { + const auto *TempSpecType = VariantType->getAs(); + assert(TempSpecType && + "We are in a variant instance. It must be a template specialization!"); DonatNagyE wrote: As above, this depends on user input, so it should be an early return (and not an assert). https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,128 @@ +//===- TaggedUnionModeling.h -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" +#include + +namespace clang { +namespace ento { +namespace variant_modeling { + +// The implementation of all these functions can be found in the +// StdVariantChecker.cpp file under the same directory as this file. +CallEventRef<> getCaller(const CallEvent , CheckerContext ); +const TemplateArgument (const CallEvent ); +bool isCopyConstructorCall(const CallEvent ); +bool isCopyAssignmentCall(const CallEvent ); +bool isMoveAssignmentCall(const CallEvent ); +bool isMoveConstructorCall(const CallEvent ); +bool isStdType(const Type *Type, const std::string ); +bool isStdVariant(const Type *Type); +bool calledFromSystemHeader(const CallEvent , CheckerContext ); + +// When invalidating regions we also have to follow that with our data +// storages in the program state. +template +ProgramStateRef +removeInformationStoredForDeadInstances(const CallEvent *Call, +ProgramStateRef State, +ArrayRef Regions) { + // If we do not know anything about the call we shall not continue. + if (!Call) { +return State; + } + + // If the call is coming from a system header it is implementation detail. + // We should not take it into consideration. + if (Call->isInSystemHeader()) { +return State; + } + + // Remove the information we know about the invalidate region. + // It is not relevant anymore. + State = std::accumulate( + Regions.begin(), Regions.end(), State, + [](ProgramStateRef State, const MemRegion *CurrentMemRegion) { +if (State->contains(CurrentMemRegion)) { + State = State->remove(CurrentMemRegion); +} +return State; + }); + return State; +} + +template +void handleConstructorAndAssignment(const CallEvent , CheckerContext , +const SVal ) { + ProgramStateRef State = Call.getState(); + + auto ArgSVal = Call.getArgSVal(0); + const auto *ThisRegion = ThisSVal.getAsRegion(); + const auto *ArgMemRegion = ArgSVal.getAsRegion(); + + // Make changes to the state according to type of constructor/assignment + State = [&]() { +bool IsCopy = isCopyConstructorCall(Call) || isCopyAssignmentCall(Call); +bool IsMove = isMoveConstructorCall(Call) || isMoveAssignmentCall(Call); + +// First we handle copy and move operations +if (IsCopy || IsMove) { + // If the argument of a copy constructor or assignment is unknown then + // we will not know the argument of the copied to object. + bool OtherQTypeKnown = State->contains(ArgMemRegion); + + const QualType *OtherQType; + if (OtherQTypeKnown) { +OtherQType = State->get(ArgMemRegion); + } else { +return State->contains(ThisRegion) + ? State->remove(ThisRegion) + : State; + } + + // When move semantics is used we can only know that the moved from + // object must be in a destructible state. Other usage of the object + // than destruction is undefined. + if (IsMove) { +State = State->contains(ArgMemRegion) +? State->remove(ArgMemRegion) +: State; + } + return State->set(ThisRegion, *OtherQType); +} +// Then the other constructor/assignment where the argument is the new +// object held by the std::variant or std::any DonatNagyE wrote: Perhaps include the signature of the referenced constructors / assignment operators (here and above) for the sake of lazy readers like me :) https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,128 @@ +//===- TaggedUnionModeling.h -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" +#include + +namespace clang { +namespace ento { +namespace variant_modeling { + +// The implementation of all these functions can be found in the +// StdVariantChecker.cpp file under the same directory as this file. +CallEventRef<> getCaller(const CallEvent , CheckerContext ); +const TemplateArgument (const CallEvent ); +bool isCopyConstructorCall(const CallEvent ); +bool isCopyAssignmentCall(const CallEvent ); +bool isMoveAssignmentCall(const CallEvent ); +bool isMoveConstructorCall(const CallEvent ); +bool isStdType(const Type *Type, const std::string ); +bool isStdVariant(const Type *Type); +bool calledFromSystemHeader(const CallEvent , CheckerContext ); + +// When invalidating regions we also have to follow that with our data +// storages in the program state. +template +ProgramStateRef +removeInformationStoredForDeadInstances(const CallEvent *Call, +ProgramStateRef State, +ArrayRef Regions) { + // If we do not know anything about the call we shall not continue. + if (!Call) { +return State; + } + + // If the call is coming from a system header it is implementation detail. + // We should not take it into consideration. + if (Call->isInSystemHeader()) { +return State; + } + + // Remove the information we know about the invalidate region. + // It is not relevant anymore. + State = std::accumulate( + Regions.begin(), Regions.end(), State, + [](ProgramStateRef State, const MemRegion *CurrentMemRegion) { +if (State->contains(CurrentMemRegion)) { + State = State->remove(CurrentMemRegion); +} +return State; + }); + return State; +} + +template +void handleConstructorAndAssignment(const CallEvent , CheckerContext , +const SVal ) { + ProgramStateRef State = Call.getState(); + + auto ArgSVal = Call.getArgSVal(0); + const auto *ThisRegion = ThisSVal.getAsRegion(); + const auto *ArgMemRegion = ArgSVal.getAsRegion(); + + // Make changes to the state according to type of constructor/assignment + State = [&]() { +bool IsCopy = isCopyConstructorCall(Call) || isCopyAssignmentCall(Call); +bool IsMove = isMoveConstructorCall(Call) || isMoveAssignmentCall(Call); + +// First we handle copy and move operations +if (IsCopy || IsMove) { + // If the argument of a copy constructor or assignment is unknown then + // we will not know the argument of the copied to object. + bool OtherQTypeKnown = State->contains(ArgMemRegion); + + const QualType *OtherQType; + if (OtherQTypeKnown) { +OtherQType = State->get(ArgMemRegion); + } else { +return State->contains(ThisRegion) + ? State->remove(ThisRegion) + : State; DonatNagyE wrote: Please check what `State->remove(ThisRegion)` does when the map does not contain `ThisRegion`. Its definition is very complex template magic, but I think it's plausible that it'll just return an unchanged state and then you can simplify code like this in many locations. https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,128 @@ +//===- TaggedUnionModeling.h -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" +#include + +namespace clang { +namespace ento { +namespace variant_modeling { + +// The implementation of all these functions can be found in the +// StdVariantChecker.cpp file under the same directory as this file. +CallEventRef<> getCaller(const CallEvent , CheckerContext ); +const TemplateArgument (const CallEvent ); +bool isCopyConstructorCall(const CallEvent ); +bool isCopyAssignmentCall(const CallEvent ); +bool isMoveAssignmentCall(const CallEvent ); +bool isMoveConstructorCall(const CallEvent ); +bool isStdType(const Type *Type, const std::string ); +bool isStdVariant(const Type *Type); +bool calledFromSystemHeader(const CallEvent , CheckerContext ); + +// When invalidating regions we also have to follow that with our data +// storages in the program state. +template +ProgramStateRef +removeInformationStoredForDeadInstances(const CallEvent *Call, +ProgramStateRef State, +ArrayRef Regions) { + // If we do not know anything about the call we shall not continue. + if (!Call) { +return State; + } + + // If the call is coming from a system header it is implementation detail. + // We should not take it into consideration. + if (Call->isInSystemHeader()) { +return State; + } + + // Remove the information we know about the invalidate region. + // It is not relevant anymore. + State = std::accumulate( + Regions.begin(), Regions.end(), State, + [](ProgramStateRef State, const MemRegion *CurrentMemRegion) { +if (State->contains(CurrentMemRegion)) { + State = State->remove(CurrentMemRegion); +} +return State; + }); + return State; +} + +template +void handleConstructorAndAssignment(const CallEvent , CheckerContext , +const SVal ) { + ProgramStateRef State = Call.getState(); + + auto ArgSVal = Call.getArgSVal(0); + const auto *ThisRegion = ThisSVal.getAsRegion(); + const auto *ArgMemRegion = ArgSVal.getAsRegion(); + + // Make changes to the state according to type of constructor/assignment + State = [&]() { DonatNagyE wrote: Remove this fat immediately executed lambda, it just obfuscates the control and data flow without any advantage. A plain old `State = /* do something with old State */` is much more readable than `return /*do something with old State*/` with a dangling `State =` for which you need to scroll up a screen. If you really like to jump around, use `break`s within a `do { } while (false)` or even plain `goto` instead of the early `return`s from the lambda -- but I think this logic can be clearly described with simple `else` branches. https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,312 @@ +//===- StdVariantChecker.cpp -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "clang/AST/Type.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" + +#include "TaggedUnionModeling.h" + +using namespace clang; +using namespace ento; +using namespace variant_modeling; + +REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType) + +namespace clang { +namespace ento { +namespace variant_modeling { + +// Returns the CallEvent representing the caller of the function +// It is needed because the CallEvent class does not contain enough information +// to tell who called it. Checker context is needed. +CallEventRef<> getCaller(const CallEvent , const ProgramStateRef ) { + const auto *CallLocationContext = Call.getLocationContext(); + if (!CallLocationContext) { +return nullptr; + } + + if (CallLocationContext->inTopFrame()) { +return nullptr; + } + const auto *CallStackFrameContext = CallLocationContext->getStackFrame(); + if (!CallStackFrameContext) { +return nullptr; + } + + CallEventManager = State->getStateManager().getCallEventManager(); + return CEMgr.getCaller(CallStackFrameContext, State); +} + +const CXXConstructorDecl * +getConstructorDeclarationForCall(const CallEvent ) { + const auto *ConstructorCall = dyn_cast(); + if (!ConstructorCall) { +return nullptr; + } + return ConstructorCall->getDecl(); +} + +bool isCopyConstructorCall(const CallEvent ) { + const CXXConstructorDecl *ConstructorDecl = + getConstructorDeclarationForCall(Call); + if (!ConstructorDecl) { +return false; + } + return ConstructorDecl->isCopyConstructor(); +} + +bool isCopyAssignmentCall(const CallEvent ) { + const Decl *CopyAssignmentDecl = Call.getDecl(); + if (!CopyAssignmentDecl) { +return false; + } + const auto *AsMethodDecl = dyn_cast(CopyAssignmentDecl); + if (!AsMethodDecl) { +return false; + } + return AsMethodDecl->isCopyAssignmentOperator(); +} + +bool isMoveConstructorCall(const CallEvent ) { + const CXXConstructorDecl *ConstructorDecl = + getConstructorDeclarationForCall(Call); + if (!ConstructorDecl) { +return false; + } + return ConstructorDecl->isMoveConstructor(); +} + +bool isMoveAssignmentCall(const CallEvent ) { + const Decl *CopyAssignmentDecl = Call.getDecl(); + if (!CopyAssignmentDecl) { +return false; + } + const auto *AsMethodDecl = dyn_cast(CopyAssignmentDecl); + if (!AsMethodDecl) { +return false; + } + return AsMethodDecl->isMoveAssignmentOperator(); +} + +const TemplateArgument (const CallEvent ) { + const CallExpr *CE = cast(Call.getOriginExpr()); + const FunctionDecl *FD = CE->getDirectCallee(); + assert(1 <= FD->getTemplateSpecializationArgs()->asArray().size() && + "std::get should have at least 1 template argument!"); + return FD->getTemplateSpecializationArgs()->asArray()[0]; +} + +bool isStdType(const Type *Type, const std::string ) { + auto *Decl = Type->getAsRecordDecl(); + if (!Decl) { +return false; + } + + return (Decl->getNameAsString() == TypeName) && Decl->isInStdNamespace(); +} + +bool isStdVariant(const Type *Type) { + return isStdType(Type, std::string("variant")); +} + +bool calledFromSystemHeader(const CallEvent , +const ProgramStateRef ) { + auto Caller = getCaller(Call, State); + if (Caller) { +return Caller->isInSystemHeader(); + } + return false; +} + +bool calledFromSystemHeader(const CallEvent , CheckerContext ) { + return calledFromSystemHeader(Call, C.getState()); +} + +} // end of namespace variant_modeling +} // end of namespace ento +} // end of namespace clang + +static ArrayRef +getTemplateArgsFromVariant(const Type *VariantType) { + const auto *TempSpecType = VariantType->getAs(); + assert(TempSpecType && + "We are in a variant instance. It must be a template specialization!"); + return TempSpecType->template_arguments(); +} + +static QualType getNthTemplateTypeArgFromVariant(const Type *varType, + unsigned i) { + return getTemplateArgsFromVariant(varType)[i].getAsType(); +} + +class StdVariantChecker : public Checker { + // Call descriptors to find relevant calls + CallDescription
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,312 @@ +//===- StdVariantChecker.cpp -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "clang/AST/Type.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" + +#include "TaggedUnionModeling.h" + +using namespace clang; +using namespace ento; +using namespace variant_modeling; + +REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType) + +namespace clang { +namespace ento { +namespace variant_modeling { + +// Returns the CallEvent representing the caller of the function +// It is needed because the CallEvent class does not contain enough information +// to tell who called it. Checker context is needed. +CallEventRef<> getCaller(const CallEvent , const ProgramStateRef ) { + const auto *CallLocationContext = Call.getLocationContext(); + if (!CallLocationContext) { +return nullptr; + } + + if (CallLocationContext->inTopFrame()) { +return nullptr; + } + const auto *CallStackFrameContext = CallLocationContext->getStackFrame(); + if (!CallStackFrameContext) { +return nullptr; + } DonatNagyE wrote: ```suggestion if (!CallStackFrameContext) return nullptr; ``` See the [LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements); also check the braces in the rest of the code. https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,128 @@ +//===- TaggedUnionModeling.h -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" +#include + +namespace clang { +namespace ento { +namespace variant_modeling { DonatNagyE wrote: Probably this should be renamed to e.g. "tagged_union_modeling" or just "tagged_unions". https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,312 @@ +//===- StdVariantChecker.cpp -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "clang/AST/Type.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" + +#include "TaggedUnionModeling.h" + +using namespace clang; +using namespace ento; +using namespace variant_modeling; + +REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType) + +namespace clang { +namespace ento { +namespace variant_modeling { + +// Returns the CallEvent representing the caller of the function +// It is needed because the CallEvent class does not contain enough information +// to tell who called it. Checker context is needed. +CallEventRef<> getCaller(const CallEvent , const ProgramStateRef ) { + const auto *CallLocationContext = Call.getLocationContext(); + if (!CallLocationContext) { +return nullptr; + } + + if (CallLocationContext->inTopFrame()) { +return nullptr; + } + const auto *CallStackFrameContext = CallLocationContext->getStackFrame(); + if (!CallStackFrameContext) { +return nullptr; + } + + CallEventManager = State->getStateManager().getCallEventManager(); + return CEMgr.getCaller(CallStackFrameContext, State); +} + +const CXXConstructorDecl * +getConstructorDeclarationForCall(const CallEvent ) { + const auto *ConstructorCall = dyn_cast(); + if (!ConstructorCall) { +return nullptr; + } + return ConstructorCall->getDecl(); +} + +bool isCopyConstructorCall(const CallEvent ) { + const CXXConstructorDecl *ConstructorDecl = + getConstructorDeclarationForCall(Call); + if (!ConstructorDecl) { +return false; + } + return ConstructorDecl->isCopyConstructor(); +} + +bool isCopyAssignmentCall(const CallEvent ) { + const Decl *CopyAssignmentDecl = Call.getDecl(); + if (!CopyAssignmentDecl) { +return false; + } + const auto *AsMethodDecl = dyn_cast(CopyAssignmentDecl); DonatNagyE wrote: ```suggestion const auto *AsMethodDecl = dyn_cast_or_null(CopyAssignmentDecl); ``` https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,128 @@ +//===- TaggedUnionModeling.h -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" +#include + +namespace clang { +namespace ento { +namespace variant_modeling { + +// The implementation of all these functions can be found in the +// StdVariantChecker.cpp file under the same directory as this file. +CallEventRef<> getCaller(const CallEvent , CheckerContext ); +const TemplateArgument (const CallEvent ); +bool isCopyConstructorCall(const CallEvent ); +bool isCopyAssignmentCall(const CallEvent ); +bool isMoveAssignmentCall(const CallEvent ); +bool isMoveConstructorCall(const CallEvent ); +bool isStdType(const Type *Type, const std::string ); +bool isStdVariant(const Type *Type); +bool calledFromSystemHeader(const CallEvent , CheckerContext ); + +// When invalidating regions we also have to follow that with our data +// storages in the program state. +template +ProgramStateRef +removeInformationStoredForDeadInstances(const CallEvent *Call, +ProgramStateRef State, +ArrayRef Regions) { + // If we do not know anything about the call we shall not continue. + if (!Call) { +return State; + } + + // If the call is coming from a system header it is implementation detail. DonatNagyE wrote: ```suggestion // If the call happens within a system header it is implementation detail. ``` If I understand it correctly, this check filters out calls _within the system header_ (as opposed to calls _of functions which are defined in_ a system header); if that's the case, then I'd suggest replacing "coming from" with a less ambiguous word choice. https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,128 @@ +//===- TaggedUnionModeling.h -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" +#include + +namespace clang { +namespace ento { +namespace variant_modeling { + +// The implementation of all these functions can be found in the +// StdVariantChecker.cpp file under the same directory as this file. DonatNagyE wrote: ```suggestion // file StdVariantChecker.cpp under the same directory as this file. ``` https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,128 @@ +//===- TaggedUnionModeling.h -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" +#include + +namespace clang { +namespace ento { +namespace variant_modeling { + +// The implementation of all these functions can be found in the +// StdVariantChecker.cpp file under the same directory as this file. +CallEventRef<> getCaller(const CallEvent , CheckerContext ); +const TemplateArgument (const CallEvent ); +bool isCopyConstructorCall(const CallEvent ); +bool isCopyAssignmentCall(const CallEvent ); +bool isMoveAssignmentCall(const CallEvent ); +bool isMoveConstructorCall(const CallEvent ); +bool isStdType(const Type *Type, const std::string ); +bool isStdVariant(const Type *Type); +bool calledFromSystemHeader(const CallEvent , CheckerContext ); + +// When invalidating regions we also have to follow that with our data +// storages in the program state. +template +ProgramStateRef +removeInformationStoredForDeadInstances(const CallEvent *Call, +ProgramStateRef State, +ArrayRef Regions) { + // If we do not know anything about the call we shall not continue. + if (!Call) { +return State; + } + + // If the call is coming from a system header it is implementation detail. + // We should not take it into consideration. + if (Call->isInSystemHeader()) { +return State; + } + + // Remove the information we know about the invalidate region. + // It is not relevant anymore. + State = std::accumulate( + Regions.begin(), Regions.end(), State, + [](ProgramStateRef State, const MemRegion *CurrentMemRegion) { +if (State->contains(CurrentMemRegion)) { + State = State->remove(CurrentMemRegion); +} +return State; + }); DonatNagyE wrote: ```suggestion for (const MemRegion *CurrentMemRegion : Regions) { if (State->contains(CurrentMemRegion)) { State = State->remove(CurrentMemRegion); } } ``` This is not Haskell, we have perfectly fine `for` loops ;) https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,312 @@ +//===- StdVariantChecker.cpp -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "clang/AST/Type.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" + +#include "TaggedUnionModeling.h" + +using namespace clang; +using namespace ento; +using namespace variant_modeling; + +REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType) + +namespace clang { +namespace ento { +namespace variant_modeling { + +// Returns the CallEvent representing the caller of the function +// It is needed because the CallEvent class does not contain enough information +// to tell who called it. Checker context is needed. +CallEventRef<> getCaller(const CallEvent , const ProgramStateRef ) { + const auto *CallLocationContext = Call.getLocationContext(); + if (!CallLocationContext) { +return nullptr; + } + + if (CallLocationContext->inTopFrame()) { +return nullptr; + } DonatNagyE wrote: ```suggestion if (!CallLocationContext || CallLocationContext->inTopFrame()) return nullptr; ``` https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
@@ -0,0 +1,128 @@ +//===- TaggedUnionModeling.h -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" +#include + +namespace clang { +namespace ento { +namespace variant_modeling { + +// The implementation of all these functions can be found in the +// StdVariantChecker.cpp file under the same directory as this file. +CallEventRef<> getCaller(const CallEvent , CheckerContext ); +const TemplateArgument (const CallEvent ); +bool isCopyConstructorCall(const CallEvent ); +bool isCopyAssignmentCall(const CallEvent ); +bool isMoveAssignmentCall(const CallEvent ); +bool isMoveConstructorCall(const CallEvent ); +bool isStdType(const Type *Type, const std::string ); +bool isStdVariant(const Type *Type); +bool calledFromSystemHeader(const CallEvent , CheckerContext ); + +// When invalidating regions we also have to follow that with our data +// storages in the program state. DonatNagyE wrote: ```suggestion // When invalidating regions, we have to follow that by invalidating // the corresponding custom data in the program state. ``` https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
https://github.com/DonatNagyE commented: Very promising checker with straightforward and clean logic! I have lots of comments, but they are all minor/cosmetic issues. https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
https://github.com/DonatNagyE edited https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix math-errno issue (PR #66381)
https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/66381 >From 997e3b69ac5c20a9130b957c86c08b16d23af07c Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat Date: Thu, 14 Sep 2023 06:27:35 -0700 Subject: [PATCH 1/4] Fix math-errno issue --- clang/lib/CodeGen/CGBuiltin.cpp| 41 +- clang/test/CodeGen/math-builtins.c | 2 ++ clang/test/CodeGen/math-libcalls.c | 2 ++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 8b19bf85d47a19f..c69ccdb0eb522bf 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2313,14 +2313,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, FD->hasAttr() ? 0 : BuiltinID; bool ErrnoOverriden = false; + bool ErrnoOverrideValue = false; // True if math-errno is overriden via the // '#pragma float_control(precise, on)'. This pragma disables fast-math, // which implies math-errno. if (E->hasStoredFPFeatures()) { FPOptionsOverride OP = E->getFPFeatures(); -if (OP.hasMathErrnoOverride()) - ErrnoOverriden = OP.getMathErrnoOverride(); +if (OP.hasMathErrnoOverride()) { + ErrnoOverriden = true; + ErrnoOverrideValue = OP.getMathErrnoOverride(); +} } + // True if 'atttibute__((optnone)) is used. This attibute overrides // fast-math which implies math-errno. bool OptNone = CurFuncDecl && CurFuncDecl->hasAttr(); @@ -2329,8 +2333,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // using the '#pragma float_control(precise, off)', and // attribute opt-none hasn't been seen. bool ErrnoOverridenToFalseWithOpt = - !ErrnoOverriden && !OptNone && - CGM.getCodeGenOpts().OptimizationLevel != 0; + ErrnoOverriden && !ErrnoOverrideValue && !OptNone && + CGM.getCodeGenOpts().OptimizationLevel != 0; // There are LLVM math intrinsics/instructions corresponding to math library // functions except the LLVM op will never set errno while the math library @@ -2339,6 +2343,28 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // LLVM counterparts if the call is marked 'const' (known to never set errno). // In case FP exceptions are enabled, the experimental versions of the // intrinsics model those. + bool ConstAlways = + getContext().BuiltinInfo.isConst(BuiltinID); + + // There's a special case with the fma builtins where they are always const + // if the target environment is GNU or the target is OS is Windows and we're + // targeting the MSVCRT.dll environment. + switch (BuiltinID) { + case Builtin::BI__builtin_fma: + case Builtin::BI__builtin_fmaf: + case Builtin::BI__builtin_fmal: + case Builtin::BIfma: + case Builtin::BIfmaf: + case Builtin::BIfmal: { +auto = CGM.getTriple(); +if (Trip.isGNUEnvironment() || Trip.isOSMSVCRT()) + ConstAlways = true; +break; +} + default: +break; + } + bool ConstWithoutErrnoAndExceptions = getContext().BuiltinInfo.isConstWithoutErrnoAndExceptions(BuiltinID); bool ConstWithoutExceptions = @@ -2362,14 +2388,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, bool ConstWithoutErrnoOrExceptions = ConstWithoutErrnoAndExceptions || ConstWithoutExceptions; bool GenerateIntrinsics = - FD->hasAttr() && !ErrnoOverriden && !OptNone; + (ConstAlways && !OptNone) || + (!getLangOpts().MathErrno && !(ErrnoOverriden && ErrnoOverrideValue) && + !OptNone); if (!GenerateIntrinsics) { GenerateIntrinsics = ConstWithoutErrnoOrExceptions && !ConstWithoutErrnoAndExceptions; if (!GenerateIntrinsics) GenerateIntrinsics = ConstWithoutErrnoOrExceptions && - (!getLangOpts().MathErrno && !ErrnoOverriden && !OptNone); + (!getLangOpts().MathErrno && + !(ErrnoOverriden && ErrnoOverrideValue) && !OptNone); if (!GenerateIntrinsics) GenerateIntrinsics = ConstWithoutErrnoOrExceptions && ErrnoOverridenToFalseWithOpt; diff --git a/clang/test/CodeGen/math-builtins.c b/clang/test/CodeGen/math-builtins.c index 962e311698f5755..554c604219957ca 100644 --- a/clang/test/CodeGen/math-builtins.c +++ b/clang/test/CodeGen/math-builtins.c @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm %s | FileCheck %s -check-prefix=NO__ERRNO // RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s -check-prefix=HAS_ERRNO +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm -disable-llvm-passes -O2 %s | FileCheck %s -check-prefix=NO__ERRNO +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm -disable-llvm-passes -O2 -fmath-errno %s | FileCheck %s -check-prefix=HAS_ERRNO //
[clang] [NFC][CodeGen] Change CodeGenOpt::Level/CodeGenFileType into enum classes (PR #66295)
@@ -661,27 +661,27 @@ static bool FixupInvocation(CompilerInvocation , static unsigned getOptimizationLevel(ArgList , InputKind IK, DiagnosticsEngine ) { - unsigned DefaultOpt = llvm::CodeGenOpt::None; + unsigned DefaultOpt = 0; if ((IK.getLanguage() == Language::OpenCL || IK.getLanguage() == Language::OpenCLCXX) && !Args.hasArg(OPT_cl_opt_disable)) -DefaultOpt = llvm::CodeGenOpt::Default; +DefaultOpt = 2; pogo59 wrote: Actually it looks to me like clang only cares about 0/not-0, and the specific non-zero number is irrelevant. So, internally clang codegen would be better off with a simple Optimize bool. (It looks like LangOpts does it this way already.) CodeGenOpts probably does need to track the actual user-specified level to pass down to LLVM, but it doesn't need it for its own purposes. https://github.com/llvm/llvm-project/pull/66295 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Setup whitespace detection and clang-format as Github actions (PR #66509)
ldionne wrote: @tru Sounds good! I gave you https://github.com/llvm/llvm-project/issues/66468 too. https://github.com/llvm/llvm-project/pull/66509 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Setup whitespace detection and clang-format as Github actions (PR #66509)
tru wrote: @ldionne thanks for the whitespace check! I have already put some work into the clang-format action on my end. Would you mind dropping it from this PR and let me push mine first? My action is not just restricted to the clang subdir. https://github.com/llvm/llvm-project/pull/66509 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Fix StackAddrEscapeChecker crash on temporary object fields (PR #66493)
@@ -398,7 +400,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS, }(Referrer->getMemorySpace()); // This cast supposed to succeed. steakhal wrote: > I think the best would be either a comment that explains _why_ we expect a > `VarRegion` here (e.g. it's already checked in function `fooBar()` etc.) or > if possible, then a crash-less logic (converting an earlier `isa`-like check > + this `cast` into a single `getAs`). There is nothing that would directly imply this. It's like, ATM I don't know of any other situations where it could be not a `VarRegion`, and so far it didn't appear in practice that would disprove this. I'm not exactly sure if a comment like that would suffice. Would you accept it? And do you think it's necessary? Another alternative could be a combination: ```c++ if (!isa(Referrer)) { assert(false && "We should really only have VarRegions here"); continue; } // ... cast(Referrer)... ``` https://github.com/llvm/llvm-project/pull/66493 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Setup whitespace detection and clang-format as Github actions (PR #66509)
llvmbot wrote: @llvm/pr-subscribers-github-workflow Changes Instead of using the BuildKite jobs, use GitHub actions to detect clang-format violations and trailing whitespace in PRs. Fixes #66468 -- Full diff: https://github.com/llvm/llvm-project/pull/66509.diff 6 Files Affected: - (added) .github/workflows/clang/pr-check-trailing-whitespace.yml (+14) - (added) .github/workflows/clang/pr-clang-format.yml (+18) - (modified) clang/lib/AST/Expr.cpp (+1-1) - (modified) clang/lib/AST/ExprClassification.cpp (+6) - (modified) clang/utils/ci/buildkite-pipeline.yml (-11) - (modified) clang/utils/ci/run-buildbot (-3) diff --git a/.github/workflows/clang/pr-check-trailing-whitespace.yml b/.github/workflows/clang/pr-check-trailing-whitespace.yml new file mode 100644 index 000..b08f1e24d785ac5 --- /dev/null +++ b/.github/workflows/clang/pr-check-trailing-whitespace.yml @@ -0,0 +1,14 @@ +name: Ensure there are no trailing whitespace + +on: + pull_request: +paths: +- #x27;clang/**#x27; + +jobs: + example: +name: Find Trailing Whitespace +runs-on: ubuntu-latest +steps: + - uses: actions/checkout@v3 + - uses: harupy/find-trailing-whitespace@master diff --git a/.github/workflows/clang/pr-clang-format.yml b/.github/workflows/clang/pr-clang-format.yml new file mode 100644 index 000..2589b815a480f09 --- /dev/null +++ b/.github/workflows/clang/pr-clang-format.yml @@ -0,0 +1,18 @@ +name: clang-format Check + +on: + pull_request: +paths: +- #x27;clang/**#x27; + +jobs: + formatting-check: +name: Formatting Check +runs-on: ubuntu-latest +steps: +- uses: actions/checkout@v3 +- name: Run clang-format style check + uses: jidicula/clang-format-action@v4.11.0 + with: +clang-format-version: #x27;16#x27; +check-path: #x27;clang/#x27; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 4f3837371b3fc5e..342a7e3e47144bd 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -63,7 +63,7 @@ const Expr *Expr::getBestDynamicClassTypeExpr() const { } return E; -} +} const CXXRecordDecl *Expr::getBestDynamicClassType() const { const Expr *E = getBestDynamicClassTypeExpr(); diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 12193b7812f9bf8..18d35d1d47cfb82 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -79,6 +79,12 @@ Cl Expr::ClassifyImpl(ASTContext amp;Ctx, SourceLocation *Loc) const { return Classification(kind, modifiable); } +static int not_well_formatted_code(int i) +{ + int hi = i ; +return hi; +} + /// Classify an expression which creates a temporary, based on its type. static Cl::Kinds ClassifyTemporary(QualType T) { if (T-gt;isRecordType()) diff --git a/clang/utils/ci/buildkite-pipeline.yml b/clang/utils/ci/buildkite-pipeline.yml index 7a679176038c693..22ee165d1edf4e1 100644 --- a/clang/utils/ci/buildkite-pipeline.yml +++ b/clang/utils/ci/buildkite-pipeline.yml @@ -17,17 +17,6 @@ env: # LLVM RELEASE bump version LLVM_HEAD_VERSION: quot;17quot; steps: - - label: quot;Formatquot; -commands: - - quot;clang/utils/ci/run-buildbot check-formatquot; -agents: - queue: quot;linuxquot; -retry: - automatic: -- exit_status: -1 # Agent was lost - limit: 2 -timeout_in_minutes: 120 - - label: quot;Building and testing clang (Linux)quot; commands: - quot;clang/utils/ci/run-buildbot build-clangquot; diff --git a/clang/utils/ci/run-buildbot b/clang/utils/ci/run-buildbot index d117fccc7e3fbd8..56a1a9a8c8cfa22 100755 --- a/clang/utils/ci/run-buildbot +++ b/clang/utils/ci/run-buildbot @@ -69,9 +69,6 @@ cmake --version ninja --version case quot;${BUILDER}quot; in -check-format) -! grep -rnI #x27;[[:blank:]]$#x27; clang/lib clang/include clang/docs -;; build-clang) mkdir install # We use Release here to avoid including debug information. Otherwise, the https://github.com/llvm/llvm-project/pull/66509 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Setup whitespace detection and clang-format as Github actions (PR #66509)
https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/66509 Instead of using the BuildKite jobs, use GitHub actions to detect clang-format violations and trailing whitespace in PRs. Fixes #66468 >From 46330c22414ed8722e85ff349f502d4e5a1bac5d Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Fri, 15 Sep 2023 09:17:18 -0400 Subject: [PATCH] [clang] Setup whitespace detection and clang-format as Github actions Instead of using the BuildKite jobs, use GitHub actions to detect clang-format violations and trailing whitespace in PRs. Fixes #66468 --- .../clang/pr-check-trailing-whitespace.yml | 14 ++ .github/workflows/clang/pr-clang-format.yml| 18 ++ clang/lib/AST/Expr.cpp | 2 +- clang/lib/AST/ExprClassification.cpp | 6 ++ clang/utils/ci/buildkite-pipeline.yml | 11 --- clang/utils/ci/run-buildbot| 3 --- 6 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/clang/pr-check-trailing-whitespace.yml create mode 100644 .github/workflows/clang/pr-clang-format.yml diff --git a/.github/workflows/clang/pr-check-trailing-whitespace.yml b/.github/workflows/clang/pr-check-trailing-whitespace.yml new file mode 100644 index 000..b08f1e24d785ac5 --- /dev/null +++ b/.github/workflows/clang/pr-check-trailing-whitespace.yml @@ -0,0 +1,14 @@ +name: Ensure there are no trailing whitespace + +on: + pull_request: +paths: +- 'clang/**' + +jobs: + example: +name: Find Trailing Whitespace +runs-on: ubuntu-latest +steps: + - uses: actions/checkout@v3 + - uses: harupy/find-trailing-whitespace@master diff --git a/.github/workflows/clang/pr-clang-format.yml b/.github/workflows/clang/pr-clang-format.yml new file mode 100644 index 000..2589b815a480f09 --- /dev/null +++ b/.github/workflows/clang/pr-clang-format.yml @@ -0,0 +1,18 @@ +name: clang-format Check + +on: + pull_request: +paths: +- 'clang/**' + +jobs: + formatting-check: +name: Formatting Check +runs-on: ubuntu-latest +steps: +- uses: actions/checkout@v3 +- name: Run clang-format style check + uses: jidicula/clang-format-action@v4.11.0 + with: +clang-format-version: '16' +check-path: 'clang/' diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 4f3837371b3fc5e..342a7e3e47144bd 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -63,7 +63,7 @@ const Expr *Expr::getBestDynamicClassTypeExpr() const { } return E; -} +} const CXXRecordDecl *Expr::getBestDynamicClassType() const { const Expr *E = getBestDynamicClassTypeExpr(); diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 12193b7812f9bf8..18d35d1d47cfb82 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -79,6 +79,12 @@ Cl Expr::ClassifyImpl(ASTContext , SourceLocation *Loc) const { return Classification(kind, modifiable); } +static int not_well_formatted_code(int i) +{ + int hi = i ; +return hi; +} + /// Classify an expression which creates a temporary, based on its type. static Cl::Kinds ClassifyTemporary(QualType T) { if (T->isRecordType()) diff --git a/clang/utils/ci/buildkite-pipeline.yml b/clang/utils/ci/buildkite-pipeline.yml index 7a679176038c693..22ee165d1edf4e1 100644 --- a/clang/utils/ci/buildkite-pipeline.yml +++ b/clang/utils/ci/buildkite-pipeline.yml @@ -17,17 +17,6 @@ env: # LLVM RELEASE bump version LLVM_HEAD_VERSION: "17" steps: - - label: "Format" -commands: - - "clang/utils/ci/run-buildbot check-format" -agents: - queue: "linux" -retry: - automatic: -- exit_status: -1 # Agent was lost - limit: 2 -timeout_in_minutes: 120 - - label: "Building and testing clang (Linux)" commands: - "clang/utils/ci/run-buildbot build-clang" diff --git a/clang/utils/ci/run-buildbot b/clang/utils/ci/run-buildbot index d117fccc7e3fbd8..56a1a9a8c8cfa22 100755 --- a/clang/utils/ci/run-buildbot +++ b/clang/utils/ci/run-buildbot @@ -69,9 +69,6 @@ cmake --version ninja --version case "${BUILDER}" in -check-format) -! grep -rnI '[[:blank:]]$' clang/lib clang/include clang/docs -;; build-clang) mkdir install # We use Release here to avoid including debug information. Otherwise, the ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Model the fields that are accessed via inline accessors (PR #66368)
@@ -1446,6 +1446,51 @@ TEST(TransferTest, BaseClassInitializer) { llvm::Succeeded()); } +TEST(TransferTest, StructModeledFieldsWithAccessor) { + std::string Code = R"( +class S { + int *P; + int *Q; + int X; + int Y; + int Z; martinboehme wrote: Rename these to match the methods that return them (e.g. `Ptr`, `PtrNonConst` etc.)? This would make it easier to read the assertion below. https://github.com/llvm/llvm-project/pull/66368 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Model the fields that are accessed via inline accessors (PR #66368)
@@ -288,6 +288,18 @@ static void insertIfFunction(const Decl , Funcs.insert(FD); } +static Expr *getRetValueFromSingleReturnStmtMethod(const CXXMemberCallExpr ) { + auto *D = cast_or_null(C.getMethodDecl()->getDefinition()); + if (!D) +return nullptr; + auto *S = cast(D->getBody()); + if (S->size() != 1) +return nullptr; + if (auto *RS = dyn_cast(*S->body_begin())) +return RS->getRetValue()->IgnoreParenImpCasts(); + return nullptr; martinboehme wrote: ```suggestion auto *Body = dyn_cast(C.getBody()); if (!Body || Body->size() != 1) return nullptr; if (auto *RS = dyn_cast(*Body->body_begin())) return RS->getRetValue()->IgnoreParenImpCasts(); return nullptr; ``` - `getBody()` can be called on any declaration, not just the definition - Suggest renaming `S` to `Body` for clarity - The fact that `getBody()` returns just a `Stmt *` makes me wary that casting unconditionally to `CompoundStmt` may not be safe, so suggest using `dyn_cast` instead. https://github.com/llvm/llvm-project/pull/66368 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Model the fields that are accessed via inline accessors (PR #66368)
@@ -324,6 +336,12 @@ getFieldsGlobalsAndFuncs(const Stmt , FieldSet , } else if (auto *E = dyn_cast()) { insertIfGlobal(*E->getDecl(), Vars); insertIfFunction(*E->getDecl(), Funcs); + } else if (const auto *C = dyn_cast()) { +// If this is a method that returns a member variable but does nothing else, +// model the field of the return value. +if (MemberExpr *E = dyn_cast_or_null( +getRetValueFromSingleReturnStmtMethod(*C))) + getFieldsGlobalsAndFuncs(*E, Fields, Vars, Funcs); martinboehme wrote: ```suggestion if (const auto *FD = dyn_cast(E->getMemberDecl())) Fields.insert(FD); ``` This is all of the logic that you really need from the recursive `getFieldsGlobalsAndFuncs()` call. I would suggest simply repeating these two lines here: - The intent is clearer - You save quite a few unnecessary `dyn_cast`s https://github.com/llvm/llvm-project/pull/66368 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Model the fields that are accessed via inline accessors (PR #66368)
@@ -1446,6 +1446,51 @@ TEST(TransferTest, BaseClassInitializer) { llvm::Succeeded()); } +TEST(TransferTest, StructModeledFieldsWithAccessor) { + std::string Code = R"( +class S { + int *P; + int *Q; + int X; + int Y; + int Z; +public: + int *getPtr() const { return P; } + int *getPtrNonConst() { return Q; } + int getInt(int i) const { return X; } martinboehme wrote: Can you add a case that returns a reference? This produces a slightly different shape of AST (without an `LValueToRValue` cast). https://github.com/llvm/llvm-project/pull/66368 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Model the fields that are accessed via inline accessors (PR #66368)
@@ -324,6 +336,12 @@ getFieldsGlobalsAndFuncs(const Stmt , FieldSet , } else if (auto *E = dyn_cast()) { insertIfGlobal(*E->getDecl(), Vars); insertIfFunction(*E->getDecl(), Funcs); + } else if (const auto *C = dyn_cast()) { +// If this is a method that returns a member variable but does nothing else, +// model the field of the return value. +if (MemberExpr *E = dyn_cast_or_null( martinboehme wrote: Maybe include the cast to `MemberExpr` in `getRetValueFromSingleReturnStmtMethod()`? This would put all of the checking in a single function and make the callsite here cleaner. The function should then be renamed to something like `getMemberForAccessor()`. https://github.com/llvm/llvm-project/pull/66368 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Model the fields that are accessed via inline accessors (PR #66368)
https://github.com/martinboehme approved this pull request. https://github.com/llvm/llvm-project/pull/66368 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Model the fields that are accessed via inline accessors (PR #66368)
https://github.com/martinboehme edited https://github.com/llvm/llvm-project/pull/66368 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66498)
https://github.com/steakhal closed https://github.com/llvm/llvm-project/pull/66498 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66498)
steakhal wrote: Pushed manually with an adjusted commit message: https://github.com/llvm/llvm-project/commit/7c9abbd8a41e85a7e82a454c62138ea72f981597 https://github.com/llvm/llvm-project/pull/66498 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 7c9abbd - Reapply [analyzer] Simplify SVal for simple NonLoc->Loc casts
Author: dingfei Date: 2023-09-15T15:07:39+02:00 New Revision: 7c9abbd8a41e85a7e82a454c62138ea72f981597 URL: https://github.com/llvm/llvm-project/commit/7c9abbd8a41e85a7e82a454c62138ea72f981597 DIFF: https://github.com/llvm/llvm-project/commit/7c9abbd8a41e85a7e82a454c62138ea72f981597.diff LOG: Reapply [analyzer] Simplify SVal for simple NonLoc->Loc casts Reapply after fixing the test by enabling the `debug.ExprInspection` checker. - NonLoc symbolic SVal to Loc casts are not supported except for nonloc::ConcreteInt. This change simplifies the source SVals so that the more casts can go through nonloc::ConcreteInt->loc::ConcreteInt path. For example: void test_simplified_before_cast_add(long long t1) { long long t2 = t1 + 3; if (!t2) { int *p = (int *) t2; clang_analyzer_eval(p == 0); // expected-warning{{TRUE}} } } If simplified, 't2' is 0, resulting 'p' is nullptr, otherwise 'p' is unknown. Fixes #62232 Added: Modified: clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp clang/test/Analysis/symbol-simplification-nonloc-loc.cpp Removed: diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 2a47116db55a1ad..7e431f7e598c4cb 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -264,7 +264,8 @@ ProgramStateRef ExprEngine::handleLValueBitCast( } // Delegate to SValBuilder to process. SVal OrigV = state->getSVal(Ex, LCtx); - SVal V = svalBuilder.evalCast(OrigV, T, ExTy); + SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV); + SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy); // Negate the result if we're treating the boolean as a signed i1 if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid()) V = svalBuilder.evalMinus(V.castAs()); diff --git a/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp b/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp index 485f68d9a5acfba..6cfe8da971429c3 100644 --- a/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp +++ b/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp @@ -1,6 +1,8 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core %s \ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection %s \ // RUN:-triple x86_64-pc-linux-gnu -verify +void clang_analyzer_eval(int); + #define BINOP(OP) [](auto x, auto y) { return x OP y; } template @@ -73,3 +75,27 @@ void zoo1backwards() { *(0 + p) = nullptr; // warn **(0 + p) = 'a'; // no-warning: this should be unreachable } + +void test_simplified_before_cast_add(long t1) { + long t2 = t1 + 3; + if (!t2) { +int *p = (int *) t2; +clang_analyzer_eval(p == 0); // expected-warning{{TRUE}} + } +} + +void test_simplified_before_cast_sub(long t1) { + long t2 = t1 - 3; + if (!t2) { +int *p = (int *) t2; +clang_analyzer_eval(p == 0); // expected-warning{{TRUE}} + } +} + +void test_simplified_before_cast_mul(long t1) { + long t2 = t1 * 3; + if (!t2) { +int *p = (int *) t2; +clang_analyzer_eval(p == 0); // expected-warning{{TRUE}} + } +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66463)
danix800 wrote: `auto-merge` might be disabled probably. I can't find the button mentioned [here](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request). https://github.com/llvm/llvm-project/pull/66463 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Driver] Link Flang runtime on Solaris (PR #65644)
rorth wrote: I'd argue that handling the Flang runtime libs like C++ is the right thing to do here. However, `flang-new` currently rejects all of `-r`, `-nostdlib`, and `-nodefaultlibs` on both Linux and Solaris. On top of that, Solaris `clang` doesn't handle `-r` correctly, passing `-e _start -Bdynamic` to `ld`, which makes it choke... https://github.com/llvm/llvm-project/pull/65644 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [RISCV] Support predefined marcro __riscv_misaligned_{fast,avoid}. (PR #65756)
yetingk wrote: Ping. https://github.com/llvm/llvm-project/pull/65756 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy]add new check `bugprone-compare-pointer-to-member-virtual-function` (PR #66055)
https://github.com/HerrCai0907 closed https://github.com/llvm/llvm-project/pull/66055 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tidy]add new check `bugprone-compare-pointer-to-member-virtual-function` (PR #66055)
https://github.com/HerrCai0907 closed https://github.com/llvm/llvm-project/pull/66055 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] 72d4d4e - [clang-tidy]add new check `bugprone-compare-pointer-to-member-virtual-function` (#66055)
Author: Congcong Cai Date: 2023-09-15T20:59:12+08:00 New Revision: 72d4d4e3b9f6b54582358ac5c1006e295b9ed58e URL: https://github.com/llvm/llvm-project/commit/72d4d4e3b9f6b54582358ac5c1006e295b9ed58e DIFF: https://github.com/llvm/llvm-project/commit/72d4d4e3b9f6b54582358ac5c1006e295b9ed58e.diff LOG: [clang-tidy]add new check `bugprone-compare-pointer-to-member-virtual-function` (#66055) Added: clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.h clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst clang-tools-extra/test/clang-tidy/checkers/bugprone/compare-pointer-to-member-virtual-function.cpp Modified: clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/list.rst Removed: diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index a67a91eedd10482..543c522899d7a52 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -16,6 +16,7 @@ #include "BadSignalToKillThreadCheck.h" #include "BoolPointerImplicitConversionCheck.h" #include "BranchCloneCheck.h" +#include "ComparePointerToMemberVirtualFunctionCheck.h" #include "CopyConstructorInitCheck.h" #include "DanglingHandleCheck.h" #include "DynamicStaticInitializersCheck.h" @@ -103,6 +104,8 @@ class BugproneModule : public ClangTidyModule { CheckFactories.registerCheck( "bugprone-bool-pointer-implicit-conversion"); CheckFactories.registerCheck("bugprone-branch-clone"); +CheckFactories.registerCheck( +"bugprone-compare-pointer-to-member-virtual-function"); CheckFactories.registerCheck( "bugprone-copy-constructor-init"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index 3c768021feb1502..0df9e439b715e5a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_library(clangTidyBugproneModule BoolPointerImplicitConversionCheck.cpp BranchCloneCheck.cpp BugproneTidyModule.cpp + ComparePointerToMemberVirtualFunctionCheck.cpp CopyConstructorInitCheck.cpp DanglingHandleCheck.cpp DynamicStaticInitializersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp new file mode 100644 index 000..9d1d92b989bf1f0 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp @@ -0,0 +1,106 @@ +//===--- ComparePointerToMemberVirtualFunctionCheck.cpp - clang-tidy --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "ComparePointerToMemberVirtualFunctionCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/Type.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "llvm/ADT/SmallVector.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +namespace { + +AST_MATCHER(CXXMethodDecl, isVirtual) { return Node.isVirtual(); } + +static const char *const ErrorMsg = +"comparing a pointer to member virtual function with other pointer is " +"unspecified behavior, only compare it with a null-pointer constant for " +"equality."; + +} // namespace + +void ComparePointerToMemberVirtualFunctionCheck::registerMatchers( +MatchFinder *Finder) { + + auto DirectMemberVirtualFunctionPointer = unaryOperator( + allOf(hasOperatorName("&"), +hasUnaryOperand(declRefExpr(to(cxxMethodDecl(isVirtual())); + auto IndirectMemberPointer = + ignoringImpCasts(declRefExpr().bind("indirect_member_pointer")); + + Finder->addMatcher( + binaryOperator( + allOf(hasAnyOperatorName("==", "!="), +hasEitherOperand( +hasType(memberPointerType(pointee(functionType(), +
[clang] [analyzer] Add std::variant checker (PR #66481)
https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/66481 From 5472e377f9a4b51a8c400f1cc1703aa83fa45d1b Mon Sep 17 00:00:00 2001 From: Gabor Spaits Date: Fri, 15 Sep 2023 10:21:30 +0200 Subject: [PATCH] [analyzer] Add std::variant checker Adding a checker that checks for bad std::variant type access. --- .../clang/StaticAnalyzer/Checkers/Checkers.td | 4 + .../StaticAnalyzer/Checkers/CMakeLists.txt| 1 + .../Checkers/StdVariantChecker.cpp| 312 + .../Checkers/TaggedUnionModeling.h| 128 +++ .../Inputs/system-header-simulator-cxx.h | 117 +++ .../diagnostics/explicit-suppression.cpp | 2 +- clang/test/Analysis/std-variant-checker.cpp | 326 ++ 7 files changed, 889 insertions(+), 1 deletion(-) create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp create mode 100644 clang/lib/StaticAnalyzer/Checkers/TaggedUnionModeling.h create mode 100644 clang/test/Analysis/std-variant-checker.cpp diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 65c1595eb6245dd..ec77ba1dc474d60 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -318,6 +318,10 @@ def C11LockChecker : Checker<"C11Lock">, Dependencies<[PthreadLockBase]>, Documentation; +def StdVariantChecker : Checker<"StdVariant">, + HelpText<"Check wether we access the right type stored in std::variant">, + Documentation; + } // end "alpha.core" //===--===// diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt index ae849f59f90d3d9..d7cb51e1a0819a8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -108,6 +108,7 @@ add_clang_library(clangStaticAnalyzerCheckers SmartPtrModeling.cpp StackAddrEscapeChecker.cpp StdLibraryFunctionsChecker.cpp + StdVariantChecker.cpp STLAlgorithmModeling.cpp StreamChecker.cpp StringChecker.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp new file mode 100644 index 000..314dab24650dcd2 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp @@ -0,0 +1,312 @@ +//===- StdVariantChecker.cpp -*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "clang/AST/Type.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/FoldingSet.h" + +#include "TaggedUnionModeling.h" + +using namespace clang; +using namespace ento; +using namespace variant_modeling; + +REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType) + +namespace clang { +namespace ento { +namespace variant_modeling { + +// Returns the CallEvent representing the caller of the function +// It is needed because the CallEvent class does not contain enough information +// to tell who called it. Checker context is needed. +CallEventRef<> getCaller(const CallEvent , const ProgramStateRef ) { + const auto *CallLocationContext = Call.getLocationContext(); + if (!CallLocationContext) { +return nullptr; + } + + if (CallLocationContext->inTopFrame()) { +return nullptr; + } + const auto *CallStackFrameContext = CallLocationContext->getStackFrame(); + if (!CallStackFrameContext) { +return nullptr; + } + + CallEventManager = State->getStateManager().getCallEventManager(); + return CEMgr.getCaller(CallStackFrameContext, State); +} + +const CXXConstructorDecl * +getConstructorDeclarationForCall(const CallEvent ) { + const auto *ConstructorCall = dyn_cast(); + if (!ConstructorCall) { +return nullptr; + } + return ConstructorCall->getDecl(); +} + +bool isCopyConstructorCall(const CallEvent ) { + const CXXConstructorDecl *ConstructorDecl = + getConstructorDeclarationForCall(Call); + if (!ConstructorDecl) { +return false; + } + return ConstructorDecl->isCopyConstructor(); +} + +bool isCopyAssignmentCall(const CallEvent ) { + const Decl *CopyAssignmentDecl = Call.getDecl(); + if (!CopyAssignmentDecl) { +
[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)
https://github.com/steakhal edited https://github.com/llvm/llvm-project/pull/65448 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)
https://github.com/steakhal commented: Uh, this isn't my expertiese. I'm a bit scared to do this alone. I'm also short on time to verify this patch at scale. https://github.com/llvm/llvm-project/pull/65448 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)
@@ -1824,6 +1835,94 @@ RangeSet SymbolicRangeInferrer::VisitBinaryOperator(Range LHS, return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)}; } +RangeSet SymbolicRangeInferrer::handleConcreteModulo(Range LHS, + llvm::APSInt Modulo, + QualType T) { + APSIntType ResultType = ValueFactory.getAPSIntType(T); + llvm::APSInt Zero = ResultType.getZeroValue(); + llvm::APSInt One = ResultType.getValue(1); + + if (Modulo == Zero) +return RangeFactory.getEmptySet(); + if (Modulo < 0) +Modulo = -Modulo; + + auto ComputeModuloN = [&](llvm::APSInt From, llvm::APSInt To, +llvm::APSInt N) -> RangeSet { +assert(N > Zero && "Non-positive N!"); +bool NonNegative = From >= Zero; +assert(NonNegative == (To >= Zero) && "Signedness mismatch!"); + +if (From > To) + return RangeFactory.getEmptySet(); + +llvm::APSInt N1 = N - One; steakhal wrote: APSInt cannot wrap, right? So if N was the minimum representable on the same number of bits, it would extend the number of bits used for the representation, which might be different from the bitwidth of `Zero` and friends. This could lead to constructing Ranges with APSInts of different widths, which is unexpected. https://github.com/llvm/llvm-project/pull/65448 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)
@@ -1824,6 +1835,94 @@ RangeSet SymbolicRangeInferrer::VisitBinaryOperator(Range LHS, return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)}; } +RangeSet SymbolicRangeInferrer::handleConcreteModulo(Range LHS, + llvm::APSInt Modulo, + QualType T) { + APSIntType ResultType = ValueFactory.getAPSIntType(T); + llvm::APSInt Zero = ResultType.getZeroValue(); + llvm::APSInt One = ResultType.getValue(1); + + if (Modulo == Zero) +return RangeFactory.getEmptySet(); + if (Modulo < 0) +Modulo = -Modulo; steakhal wrote: If we swap the sign of the RHS, we should also swap it on the LHS: `X % Y <=> -X % -Y` right? https://github.com/llvm/llvm-project/pull/65448 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Parse formulas from text (PR #66424)
@@ -258,114 +276,71 @@ TEST(SolverTest, IffWithUnits) { } TEST(SolverTest, IffWithUnitsConflict) { - ConstraintContext Ctx; - auto X = Ctx.atom(); - auto Y = Ctx.atom(); - auto XEqY = Ctx.iff(X, Y); - auto NotY = Ctx.neg(Y); - - // (X <=> Y) ^ X !Y - EXPECT_THAT(solve({XEqY, X, NotY}), unsat()); + Arena A; + auto Constraints = parseAll(A, R"( + (V0 = V1) + V0 + !V1 + )"); + EXPECT_THAT(solve(Constraints), unsat()); } TEST(SolverTest, IffTransitiveConflict) { - ConstraintContext Ctx; - auto X = Ctx.atom(); - auto Y = Ctx.atom(); - auto Z = Ctx.atom(); - auto XEqY = Ctx.iff(X, Y); - auto YEqZ = Ctx.iff(Y, Z); - auto NotX = Ctx.neg(X); - - // (X <=> Y) ^ (Y <=> Z) ^ Z ^ !X - EXPECT_THAT(solve({XEqY, YEqZ, Z, NotX}), unsat()); + Arena A; + auto Constraints = parseAll(A, R"( + (V0 = V1) + (V1 = V2) + V2 + !V0 + )"); + EXPECT_THAT(solve(Constraints), unsat()); } TEST(SolverTest, DeMorgan) { - ConstraintContext Ctx; - auto X = Ctx.atom(); - auto Y = Ctx.atom(); - auto Z = Ctx.atom(); - auto W = Ctx.atom(); - - // !(X v Y) <=> !X ^ !Y - auto A = Ctx.iff(Ctx.neg(Ctx.disj(X, Y)), Ctx.conj(Ctx.neg(X), Ctx.neg(Y))); - - // !(Z ^ W) <=> !Z v !W - auto B = Ctx.iff(Ctx.neg(Ctx.conj(Z, W)), Ctx.disj(Ctx.neg(Z), Ctx.neg(W))); - - // A ^ B - EXPECT_THAT(solve({A, B}), sat(_)); + Arena A; + auto Constraints = parseAll(A, R"( + (!(V0 | V1) = (!V0 & !V1)) + (!(V2 & V3) = (!V2 | !V3)) + )"); + EXPECT_THAT(solve(Constraints), sat(_)); } TEST(SolverTest, RespectsAdditionalConstraints) { - ConstraintContext Ctx; - auto X = Ctx.atom(); - auto Y = Ctx.atom(); - auto XEqY = Ctx.iff(X, Y); - auto NotY = Ctx.neg(Y); - - // (X <=> Y) ^ X ^ !Y - EXPECT_THAT(solve({XEqY, X, NotY}), unsat()); + Arena A; + auto Constraints = parseAll(A, R"( + (V0 = V1) + V0 + !V1 + )"); + EXPECT_THAT(solve(Constraints), unsat()); } TEST(SolverTest, ImplicationIsEquivalentToDNF) { - ConstraintContext Ctx; - auto X = Ctx.atom(); - auto Y = Ctx.atom(); - auto XImpliesY = Ctx.impl(X, Y); - auto XImpliesYDNF = Ctx.disj(Ctx.neg(X), Y); - auto NotEquivalent = Ctx.neg(Ctx.iff(XImpliesY, XImpliesYDNF)); - - // !((X => Y) <=> (!X v Y)) - EXPECT_THAT(solve({NotEquivalent}), unsat()); + Arena A; + auto Constraints = parseAll(A, R"( + !((V0 => V1) = (!V0 | V1)) + )"); + EXPECT_THAT(solve(Constraints), unsat()); } TEST(SolverTest, ImplicationConflict) { - ConstraintContext Ctx; - auto X = Ctx.atom(); - auto Y = Ctx.atom(); - auto *XImplY = Ctx.impl(X, Y); - auto *XAndNotY = Ctx.conj(X, Ctx.neg(Y)); - - // X => Y ^ X ^ !Y - EXPECT_THAT(solve({XImplY, XAndNotY}), unsat()); -} - -TEST(SolverTest, LowTimeoutResultsInTimedOut) { - WatchedLiteralsSolver solver(10); - ConstraintContext Ctx; - auto X = Ctx.atom(); - auto Y = Ctx.atom(); - auto Z = Ctx.atom(); - auto W = Ctx.atom(); - - // !(X v Y) <=> !X ^ !Y - auto A = Ctx.iff(Ctx.neg(Ctx.disj(X, Y)), Ctx.conj(Ctx.neg(X), Ctx.neg(Y))); - - // !(Z ^ W) <=> !Z v !W - auto B = Ctx.iff(Ctx.neg(Ctx.conj(Z, W)), Ctx.disj(Ctx.neg(Z), Ctx.neg(W))); - - // A ^ B - EXPECT_EQ(solver.solve({A, B}).getStatus(), Solver::Result::Status::TimedOut); + Arena A; + auto Constraints = parseAll(A, R"( + (V0 => V1) + (V0 & !V1) martinboehme wrote: ```suggestion (V0 => V1) V0 !V1 ``` Nit: This is the way you notated this kind of thing above. https://github.com/llvm/llvm-project/pull/66424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Parse formulas from text (PR #66424)
@@ -87,6 +87,9 @@ class alignas(const Formula *) Formula { ArrayRef Operands, unsigned Value = 0); + // Parse Formulas using Arena rather than caling this function directly. + static Formula *parse(llvm::BumpPtrAllocator , llvm::StringRef &); martinboehme wrote: I can't find a definition for this function. Was this later replaced by `parse()` in Arena.cpp? https://github.com/llvm/llvm-project/pull/66424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Parse formulas from text (PR #66424)
@@ -13,6 +13,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/ErrorHandling.h" #include +#include martinboehme wrote: Inadvertent change? (There are no other changes in this file.) https://github.com/llvm/llvm-project/pull/66424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Parse formulas from text (PR #66424)
@@ -87,6 +87,9 @@ class alignas(const Formula *) Formula { ArrayRef Operands, unsigned Value = 0); + // Parse Formulas using Arena rather than caling this function directly. martinboehme wrote: ```suggestion // Don't call this function directly. Use `Arena::parseFormula()` instead. ``` Nit: When I began reading the comment, "Parse Formulas using Arena" initially sounded like a description of what the function is doing. "Don't call directly" seems like the most helpful thing to put at the beginning. https://github.com/llvm/llvm-project/pull/66424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Parse formulas from text (PR #66424)
@@ -137,5 +140,46 @@ TEST_F(ArenaTest, Interning) { EXPECT_EQ((), ); } +TEST_F(ArenaTest, Parse) { martinboehme wrote: ```suggestion TEST_F(ArenaTest, ParseFormula) { ``` Matches name of the function, and we might conceivably add other parsing functions to `Arena` in the future. https://github.com/llvm/llvm-project/pull/66424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Parse formulas from text (PR #66424)
@@ -95,4 +98,94 @@ BoolValue ::makeBoolValue(const Formula ) { return *It->second; } +namespace { +const Formula *parse(Arena , llvm::StringRef ) { + auto EatWhitespace = [&] { In = In.ltrim(' '); }; martinboehme wrote: ```suggestion auto EatWhitespace = [&] { In = In.ltrim(); }; ``` I think you initially thought you shouldn't eat newlines here, but AFAICT, this isn't an issue because `parseAll()` below splits lines before it ever calls this. Alternatively, if you really do want to eat only spaces here, I'd suggest renaming this `EatSpaces`. https://github.com/llvm/llvm-project/pull/66424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Parse formulas from text (PR #66424)
@@ -95,4 +98,94 @@ BoolValue ::makeBoolValue(const Formula ) { return *It->second; } +namespace { +const Formula *parse(Arena , llvm::StringRef ) { + auto EatWhitespace = [&] { In = In.ltrim(' '); }; + EatWhitespace(); + + if (In.consume_front("!")) { +if (auto *Arg = parse(A, In)) + return (*Arg); +return nullptr; + } + + if (In.consume_front("(")) { +auto *Arg1 = parse(A, In); +if (!Arg1) + return nullptr; + +EatWhitespace(); +decltype(::makeOr) Op; +if (In.consume_front("|")) + Op = ::makeOr; +else if (In.consume_front("&")) + Op = ::makeAnd; +else if (In.consume_front("=>")) + Op = ::makeImplies; +else if (In.consume_front("=")) + Op = ::makeEquals; +else + return nullptr; + +auto *Arg2 = parse(A, In); +if (!Arg2) + return nullptr; + +EatWhitespace(); +if (!In.consume_front(")")) + return nullptr; + +return &(A.*Op)(*Arg1, *Arg2); + } + + if (In.consume_front("V")) { +std::underlying_type_t At; +if (In.consumeInteger(10, At)) + return nullptr; +return (static_cast(At)); + } + + if (In.consume_front("true")) +return (true); + if (In.consume_front("false")) +return (false); + + return nullptr; +} + +class FormulaParseError : public llvm::ErrorInfo { + unsigned Offset; + std::string Formula; martinboehme wrote: Nit: Reorder to match order of constructor parameters? https://github.com/llvm/llvm-project/pull/66424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Parse formulas from text (PR #66424)
https://github.com/martinboehme approved this pull request. https://github.com/llvm/llvm-project/pull/66424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Parse formulas from text (PR #66424)
https://github.com/martinboehme edited https://github.com/llvm/llvm-project/pull/66424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Fix StackAddrEscapeChecker crash on temporary object fields (PR #66493)
@@ -398,7 +400,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS, }(Referrer->getMemorySpace()); // This cast supposed to succeed. DonatNagyE wrote: I think the best would be either a comment that explains _why_ we expect a `VarRegion` here (e.g. it's already checked in function `fooBar()` etc.) or if possible, then a crash-less logic (converting an earlier `isa`-like check + this `cast` into a single `getAs`). I don't think that we should add defensive/paranoid checks; if this logic is broken by some change in the distant future, then a fixable crash is better than silent degradation. https://github.com/llvm/llvm-project/pull/66493 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][ObjC] Add optionality to property attribute strings. (PR #66507)
https://github.com/al45tair created https://github.com/llvm/llvm-project/pull/66507 Add a new attribute, "?", to the property attribute string for properties of protocols that are declared @optional. (Previously https://reviews.llvm.org/D135273) rdar://100463524 >From 3514013089dcf9fa798e9ba5812b34df497a493b Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 15 Sep 2023 13:46:19 +0100 Subject: [PATCH] [Clang][ObjC] Add optionality to property attribute strings. Add a new attribute, "?", to the property attribute string for properties of protocols that are declared @optional. (Previously https://reviews.llvm.org/D135273) rdar://100463524 --- clang/lib/AST/ASTContext.cpp | 4 clang/test/CodeGenObjC/objc-asm-attribute-test.m | 10 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4b1d9e86797b778..57aaa05b1d81ddb 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7890,6 +7890,7 @@ ASTContext::getObjCPropertyImplDeclForPropertyDecl( /// kPropertyWeak = 'W' // 'weak' property /// kPropertyStrong = 'P'// property GC'able /// kPropertyNonAtomic = 'N' // property non-atomic +/// kPropertyOptional = '?' // property optional /// }; /// @endcode std::string @@ -7915,6 +7916,9 @@ ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, // closely resembles encoding of ivars. getObjCEncodingForPropertyType(PD->getType(), S); + if (PD->isOptional()) +S += ",?"; + if (PD->isReadOnly()) { S += ",R"; if (PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) diff --git a/clang/test/CodeGenObjC/objc-asm-attribute-test.m b/clang/test/CodeGenObjC/objc-asm-attribute-test.m index 876370115bfc424..e57e42535f67274 100644 --- a/clang/test/CodeGenObjC/objc-asm-attribute-test.m +++ b/clang/test/CodeGenObjC/objc-asm-attribute-test.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -Wno-objc-root-class -emit-llvm -triple x86_64-apple-darwin %s -o - | FileCheck %s __attribute__((objc_runtime_name("MySecretNamespace.Protocol"))) @protocol Protocol @@ -10,6 +10,10 @@ + (void) ClsMethodP; @protocol Protocol2 - (void) MethodP2; + (void) ClsMethodP2; + +@optional +@property(retain) id optionalProp; + @end __attribute__((objc_runtime_name("MySecretNamespace.Protocol3"))) @@ -57,6 +61,10 @@ id Test16877359(void) { // CHECK: @"OBJC_CLASS_$_MySecretNamespace.Message" ={{.*}} global %struct._class_t // CHECK: @"OBJC_METACLASS_$_MySecretNamespace.Message" ={{.*}} global %struct._class_t +// CHECK: @OBJC_PROP_NAME_ATTR_ = private unnamed_addr constant [13 x i8] c"optionalProp\00" +// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.11 = private unnamed_addr constant [7 x i8] c"T@,?,&\00" +// CHECK: @"_OBJC_$_PROP_LIST_MySecretNamespace.Protocol2" ={{.*}} [%struct._prop_t { ptr @OBJC_PROP_NAME_ATTR_, ptr @OBJC_PROP_NAME_ATTR_.11 }] + // CHECK: private unnamed_addr constant [42 x i8] c"T@\22MySecretNamespace.Message\22,&,V_msgProp\00" // CHECK: private unnamed_addr constant [76 x i8] c"T@\22MySecretNamespace.Message\22,&,V_msgProtoProp\00" // CHECK: private unnamed_addr constant [50 x i8] c"T@\22\22,&,V_idProtoProp\00" ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Add std::variant checker (PR #66481)
https://github.com/Szelethus edited https://github.com/llvm/llvm-project/pull/66481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-transformer] Allow stencils to read from system headers. (PR #66480)
https://github.com/legrosbuffle updated https://github.com/llvm/llvm-project/pull/66480 >From b23472e55093ea1d48d11386cc4ced43f913c170 Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Fri, 15 Sep 2023 10:42:16 +0200 Subject: [PATCH] [clang-transformer] Allow stencils to read from system headers. We were previously checking that stencil input ranges were writable. It suffices for them to be readable. --- clang/include/clang/Tooling/Transformer/SourceCode.h | 6 ++ clang/lib/Tooling/Transformer/SourceCode.cpp | 6 +++--- clang/lib/Tooling/Transformer/Stencil.cpp| 9 + 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Tooling/Transformer/SourceCode.h b/clang/include/clang/Tooling/Transformer/SourceCode.h index 44a4749db74c96c..004c614b0b9d93c 100644 --- a/clang/include/clang/Tooling/Transformer/SourceCode.h +++ b/clang/include/clang/Tooling/Transformer/SourceCode.h @@ -91,6 +91,12 @@ StringRef getExtendedText(const T , tok::TokenKind Next, llvm::Error validateEditRange(const CharSourceRange , const SourceManager ); +/// Determines whether \p Range is one that can be read from. If +/// `AllowSystemHeaders` is false, a range that falls within a system header +/// fails validation. +llvm::Error validateRange(const CharSourceRange , const SourceManager , + bool AllowSystemHeaders); + /// Attempts to resolve the given range to one that can be edited by a rewrite; /// generally, one that starts and ends within a particular file. If a value is /// returned, it satisfies \c validateEditRange. diff --git a/clang/lib/Tooling/Transformer/SourceCode.cpp b/clang/lib/Tooling/Transformer/SourceCode.cpp index 35edc261ef09670..30009537b5923ce 100644 --- a/clang/lib/Tooling/Transformer/SourceCode.cpp +++ b/clang/lib/Tooling/Transformer/SourceCode.cpp @@ -50,9 +50,9 @@ CharSourceRange clang::tooling::maybeExtendRange(CharSourceRange Range, return CharSourceRange::getTokenRange(Range.getBegin(), Tok.getLocation()); } -static llvm::Error validateRange(const CharSourceRange , - const SourceManager , - bool AllowSystemHeaders) { +llvm::Error clang::tooling::validateRange(const CharSourceRange , + const SourceManager , + bool AllowSystemHeaders) { if (Range.isInvalid()) return llvm::make_error(errc::invalid_argument, "Invalid range"); diff --git a/clang/lib/Tooling/Transformer/Stencil.cpp b/clang/lib/Tooling/Transformer/Stencil.cpp index f2c1b6f8520a8cb..d91c9e0a20cc1b0 100644 --- a/clang/lib/Tooling/Transformer/Stencil.cpp +++ b/clang/lib/Tooling/Transformer/Stencil.cpp @@ -229,8 +229,8 @@ class SelectorStencil : public StencilInterface { // Validate the original range to attempt to get a meaningful error // message. If it's valid, then something else is the cause and we just // return the generic failure message. - if (auto Err = - tooling::validateEditRange(*RawRange, *Match.SourceManager)) + if (auto Err = tooling::validateRange(*RawRange, *Match.SourceManager, +/*AllowSystemHeaders=*/true)) return handleErrors(std::move(Err), [](std::unique_ptr E) { assert(E->convertToErrorCode() == llvm::make_error_code(errc::invalid_argument) && @@ -245,8 +245,9 @@ class SelectorStencil : public StencilInterface { "selected range could not be resolved to a valid source range"); } // Validate `Range`, because `makeFileCharRange` accepts some ranges that -// `validateEditRange` rejects. -if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager)) +// `validateRange` rejects. +if (auto Err = tooling::validateRange(Range, *Match.SourceManager, + /*AllowSystemHeaders=*/true)) return joinErrors( llvm::createStringError(errc::invalid_argument, "selected range is not valid for editing"), ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-transformer] Allow stencils to read from system headers. (PR #66480)
@@ -91,6 +91,10 @@ StringRef getExtendedText(const T , tok::TokenKind Next, llvm::Error validateEditRange(const CharSourceRange , const SourceManager ); +/// Determines whether \p Range is one that can be read from. +llvm::Error validateRange(const CharSourceRange , const SourceManager , + bool AllowSystemHeaders); legrosbuffle wrote: done https://github.com/llvm/llvm-project/pull/66480 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-transformer] Allow stencils to read from system headers. (PR #66480)
@@ -230,7 +230,7 @@ class SelectorStencil : public StencilInterface { // message. If it's valid, then something else is the cause and we just // return the generic failure message. if (auto Err = - tooling::validateEditRange(*RawRange, *Match.SourceManager)) + tooling::validateRange(*RawRange, *Match.SourceManager, true)) legrosbuffle wrote: done https://github.com/llvm/llvm-project/pull/66480 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-transformer] Allow stencils to read from system headers. (PR #66480)
https://github.com/legrosbuffle updated https://github.com/llvm/llvm-project/pull/66480 >From 312eeef4c301e1049f50436fa3aa8d070b5cb4e9 Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Fri, 15 Sep 2023 10:42:16 +0200 Subject: [PATCH] [clang-transformer] Allow stencils to read from system headers. We were previously checking that stencil input ranges were writable. It suffices for them to be readable. --- clang/include/clang/Tooling/Transformer/SourceCode.h | 6 ++ clang/lib/Tooling/Transformer/SourceCode.cpp | 6 +++--- clang/lib/Tooling/Transformer/Stencil.cpp| 9 + 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Tooling/Transformer/SourceCode.h b/clang/include/clang/Tooling/Transformer/SourceCode.h index 44a4749db74c96c..cbb92b30a100290 100644 --- a/clang/include/clang/Tooling/Transformer/SourceCode.h +++ b/clang/include/clang/Tooling/Transformer/SourceCode.h @@ -91,6 +91,12 @@ StringRef getExtendedText(const T , tok::TokenKind Next, llvm::Error validateEditRange(const CharSourceRange , const SourceManager ); +/// Determines whether \p Range is one that can be read from. If +// `AllowSystemHeaders` is false, a range that falls within a system header +// fails validation. +llvm::Error validateRange(const CharSourceRange , const SourceManager , + bool AllowSystemHeaders); + /// Attempts to resolve the given range to one that can be edited by a rewrite; /// generally, one that starts and ends within a particular file. If a value is /// returned, it satisfies \c validateEditRange. diff --git a/clang/lib/Tooling/Transformer/SourceCode.cpp b/clang/lib/Tooling/Transformer/SourceCode.cpp index 35edc261ef09670..30009537b5923ce 100644 --- a/clang/lib/Tooling/Transformer/SourceCode.cpp +++ b/clang/lib/Tooling/Transformer/SourceCode.cpp @@ -50,9 +50,9 @@ CharSourceRange clang::tooling::maybeExtendRange(CharSourceRange Range, return CharSourceRange::getTokenRange(Range.getBegin(), Tok.getLocation()); } -static llvm::Error validateRange(const CharSourceRange , - const SourceManager , - bool AllowSystemHeaders) { +llvm::Error clang::tooling::validateRange(const CharSourceRange , + const SourceManager , + bool AllowSystemHeaders) { if (Range.isInvalid()) return llvm::make_error(errc::invalid_argument, "Invalid range"); diff --git a/clang/lib/Tooling/Transformer/Stencil.cpp b/clang/lib/Tooling/Transformer/Stencil.cpp index f2c1b6f8520a8cb..d91c9e0a20cc1b0 100644 --- a/clang/lib/Tooling/Transformer/Stencil.cpp +++ b/clang/lib/Tooling/Transformer/Stencil.cpp @@ -229,8 +229,8 @@ class SelectorStencil : public StencilInterface { // Validate the original range to attempt to get a meaningful error // message. If it's valid, then something else is the cause and we just // return the generic failure message. - if (auto Err = - tooling::validateEditRange(*RawRange, *Match.SourceManager)) + if (auto Err = tooling::validateRange(*RawRange, *Match.SourceManager, +/*AllowSystemHeaders=*/true)) return handleErrors(std::move(Err), [](std::unique_ptr E) { assert(E->convertToErrorCode() == llvm::make_error_code(errc::invalid_argument) && @@ -245,8 +245,9 @@ class SelectorStencil : public StencilInterface { "selected range could not be resolved to a valid source range"); } // Validate `Range`, because `makeFileCharRange` accepts some ranges that -// `validateEditRange` rejects. -if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager)) +// `validateRange` rejects. +if (auto Err = tooling::validateRange(Range, *Match.SourceManager, + /*AllowSystemHeaders=*/true)) return joinErrors( llvm::createStringError(errc::invalid_argument, "selected range is not valid for editing"), ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] a20f485 - [clang-format] Generate the style options
Author: sstwcw Date: 2023-09-15T12:37:21Z New Revision: a20f485bb0c9af3c7a7179bd71ae910c58278341 URL: https://github.com/llvm/llvm-project/commit/a20f485bb0c9af3c7a7179bd71ae910c58278341 DIFF: https://github.com/llvm/llvm-project/commit/a20f485bb0c9af3c7a7179bd71ae910c58278341.diff LOG: [clang-format] Generate the style options I was in a hurry and I forgot to do it for the last commit. Added: Modified: clang/docs/ClangFormatStyleOptions.rst Removed: diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 4ab0b3a207270dc..fea52679585a6cb 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2796,7 +2796,7 @@ the configuration (without a prefix: ``Auto``). string x = "veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString"; - C# and JavaScript interpolated strings are not broken. + C# interpolated strings are not broken. In Verilog: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Fix StackAddrEscapeChecker crash on temporary object fields (PR #66493)
@@ -398,7 +400,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS, }(Referrer->getMemorySpace()); // This cast supposed to succeed. steakhal wrote: I was thinking about it once you raised this comment. To me, to have a proper diagnostic we need something that we can name here; and they are usually variables. Now, if we check and bail out if it's not a VarRegion, we would not get notified if we suddenly have some other value that we could cover but we don't. It took a long time to even hit this crash, so I don't think they are too frequent. So the question is which we prefer: - Crash (possible in the long future) to get notified or - Silently ignore these unthought, interesting cases for which we didn't account for If this would be a mission-critical software I'd vote for (2), but now I'm a bit hesitant in between the two options. Maybe, given that this is a core checker, we should lean towards gracefully handling this. WDYT? https://github.com/llvm/llvm-project/pull/66493 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Bugfix for chosing the correct deduction guide (PR #66487)
HoBoIs wrote: @zygoloid @yuanfang-chen @faisalv @OleStrohm Could you review my commit and/or suggest more appropriate reviewers? Thanks in advance! https://github.com/llvm/llvm-project/pull/66487 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Bugfix for chosing the correct deduction guide (PR #66487)
https://github.com/HoBoIs ready_for_review https://github.com/llvm/llvm-project/pull/66487 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Handle AttributedStmts (PR #66495)
@@ -628,6 +630,12 @@ bool ByteCodeStmtGen::visitAsmStmt(const AsmStmt *S) { return this->emitInvalid(S); } +template +bool ByteCodeStmtGen::visitAttributedStmt(const AttributedStmt *S) { + // Ignore all attributes. tbaederr wrote: > Is this what we want to do for [[assume]]? We can do it this way: > https://eel.is/c++draft/expr.const#5.8 but we can also do it better: > https://eel.is/c++draft/expr.const#5.33 The second case would essentially work like an assertion? If this fails, the statement isn't a constant expression? https://github.com/llvm/llvm-project/pull/66495 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Update llvmlibc-implementation-in-namespace to new rules (PR #66504)
llvmbot wrote: @llvm/pr-subscribers-clang-tidy Changes This is the implementation of step 3 of https://discourse.llvm.org/t/rfc-customizable-namespace-to-allow-testing-the-libc-when-the-system-libc-is-also-llvms-libc/73079. -- Full diff: https://github.com/llvm/llvm-project/pull/66504.diff 3 Files Affected: - (modified) clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp (+13-8) - (modified) clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst (+16-7) - (modified) clang-tools-extra/test/clang-tidy/checkers/llvmlibc/implementation-in-namespace.cpp (+21-10) diff --git a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp index d05310f09ef773a..69a385f5be9807f 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp @@ -14,7 +14,9 @@ using namespace clang::ast_matchers; namespace clang::tidy::llvm_libc { -const static StringRef RequiredNamespace = quot;__llvm_libcquot;; +const static StringRef RequiredNamespaceStart = quot;__llvm_libcquot;; +const static StringRef RequiredNamespaceMacroName = quot;LIBC_NAMESPACEquot;; + void ImplementationInNamespaceCheck::registerMatchers(MatchFinder *Finder) { Finder-gt;addMatcher( decl(hasParent(translationUnitDecl()), unless(linkageSpecDecl())) @@ -29,16 +31,19 @@ void ImplementationInNamespaceCheck::check( if (!Result.SourceManager-gt;isInMainFile(MatchedDecl-gt;getLocation())) return; - if (const auto *NS = dyn_castlt;NamespaceDeclgt;(MatchedDecl)) { -if (NS-gt;getName() != RequiredNamespace) { - diag(NS-gt;getLocation(), quot;#x27;%0#x27; needs to be the outermost namespacequot;) - lt;lt; RequiredNamespace; -} + if (auto *NS = dyn_castlt;NamespaceDeclgt;(MatchedDecl)) { +if (!Result.SourceManager-gt;isMacroBodyExpansion(NS-gt;getLocation())) + diag(NS-gt;getLocation(), + quot;the outermost namespace should be the #x27;%0#x27; macroquot;) + lt;lt; RequiredNamespaceMacroName; +else if (!NS-gt;getName().starts_with(RequiredNamespaceStart)) + diag(NS-gt;getLocation(), quot;the outermost namespace should start with #x27;%0#x27;quot;) + lt;lt; RequiredNamespaceStart; return; } diag(MatchedDecl-gt;getLocation(), - quot;declaration must be declared within the #x27;%0#x27; namespacequot;) - lt;lt; RequiredNamespace; + quot;declaration must be declared within a namespace starting with #x27;%0#x27;quot;) + lt;lt; RequiredNamespaceStart; } } // namespace clang::tidy::llvm_libc diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst index 33d6dc8ff125c84..47ea2b866a93404 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst @@ -8,21 +8,30 @@ correct namespace. .. code-block:: c++ -// Correct: implementation inside the correct namespace. -namespace __llvm_libc { +// Implementation inside the LIBC_NAMESPACE namespace. +// Correct if: +// - LIBC_NAMESPACE is a macro +// - LIBC_NAMESPACE expansion starts with `__llvm_libc` +namespace LIBC_NAMESPACE { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} -// Namespaces within __llvm_libc namespace are allowed. -namespace inner{ +// Namespaces within LIBC_NAMESPACE namespace are allowed. +namespace inner { int localVar = 0; } // Functions with C linkage are allowed. -extern quot;Cquot; void str_fuzz(){} +extern quot;Cquot; void str_fuzz() {} } -// Incorrect: implementation not in a namespace. +// Incorrect: implementation not in the LIBC_NAMESPACE namespace. void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} -// Incorrect: outer most namespace is not correct. +// Incorrect: outer most namespace is not the LIBC_NAMESPACE macro. namespace something_else { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} } + +// Incorrect: outer most namespace expansion does not start with `__llvm_libc`. +#define LIBC_NAMESPACE custom_namespace +namespace LIBC_NAMESPACE { +void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/implementation-in-namespace.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/implementation-in-namespace.cpp index e75556a623b655c..16c5f9ca1067ec5 100644 ---
[clang] Bugfix for chosing the correct deduction guide (PR #66487)
https://github.com/HoBoIs edited https://github.com/llvm/llvm-project/pull/66487 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Bugfix for chosing the correct deduction guide (PR #66487)
https://github.com/HoBoIs edited https://github.com/llvm/llvm-project/pull/66487 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Update llvmlibc-implementation-in-namespace to new rules (PR #66504)
https://github.com/gchatelet created https://github.com/llvm/llvm-project/pull/66504 This is the implementation of step 3 of https://discourse.llvm.org/t/rfc-customizable-namespace-to-allow-testing-the-libc-when-the-system-libc-is-also-llvms-libc/73079. >From f1427a81c4a3425c1a574316fc26d2c74297b34b Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Fri, 15 Sep 2023 12:34:17 + Subject: [PATCH] [clang-tidy] Update llvmlibc-implementation-in-namespace to new rules This is the implementation of step 3 of https://discourse.llvm.org/t/rfc-customizable-namespace-to-allow-testing-the-libc-when-the-system-libc-is-also-llvms-libc/73079. --- .../ImplementationInNamespaceCheck.cpp| 21 - .../llvmlibc/implementation-in-namespace.rst | 23 +- .../llvmlibc/implementation-in-namespace.cpp | 31 +-- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp index d05310f09ef773a..69a385f5be9807f 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp @@ -14,7 +14,9 @@ using namespace clang::ast_matchers; namespace clang::tidy::llvm_libc { -const static StringRef RequiredNamespace = "__llvm_libc"; +const static StringRef RequiredNamespaceStart = "__llvm_libc"; +const static StringRef RequiredNamespaceMacroName = "LIBC_NAMESPACE"; + void ImplementationInNamespaceCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( decl(hasParent(translationUnitDecl()), unless(linkageSpecDecl())) @@ -29,16 +31,19 @@ void ImplementationInNamespaceCheck::check( if (!Result.SourceManager->isInMainFile(MatchedDecl->getLocation())) return; - if (const auto *NS = dyn_cast(MatchedDecl)) { -if (NS->getName() != RequiredNamespace) { - diag(NS->getLocation(), "'%0' needs to be the outermost namespace") - << RequiredNamespace; -} + if (auto *NS = dyn_cast(MatchedDecl)) { +if (!Result.SourceManager->isMacroBodyExpansion(NS->getLocation())) + diag(NS->getLocation(), + "the outermost namespace should be the '%0' macro") + << RequiredNamespaceMacroName; +else if (!NS->getName().starts_with(RequiredNamespaceStart)) + diag(NS->getLocation(), "the outermost namespace should start with '%0'") + << RequiredNamespaceStart; return; } diag(MatchedDecl->getLocation(), - "declaration must be declared within the '%0' namespace") - << RequiredNamespace; + "declaration must be declared within a namespace starting with '%0'") + << RequiredNamespaceStart; } } // namespace clang::tidy::llvm_libc diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst index 33d6dc8ff125c84..47ea2b866a93404 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst @@ -8,21 +8,30 @@ correct namespace. .. code-block:: c++ -// Correct: implementation inside the correct namespace. -namespace __llvm_libc { +// Implementation inside the LIBC_NAMESPACE namespace. +// Correct if: +// - LIBC_NAMESPACE is a macro +// - LIBC_NAMESPACE expansion starts with `__llvm_libc` +namespace LIBC_NAMESPACE { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} -// Namespaces within __llvm_libc namespace are allowed. -namespace inner{ +// Namespaces within LIBC_NAMESPACE namespace are allowed. +namespace inner { int localVar = 0; } // Functions with C linkage are allowed. -extern "C" void str_fuzz(){} +extern "C" void str_fuzz() {} } -// Incorrect: implementation not in a namespace. +// Incorrect: implementation not in the LIBC_NAMESPACE namespace. void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} -// Incorrect: outer most namespace is not correct. +// Incorrect: outer most namespace is not the LIBC_NAMESPACE macro. namespace something_else { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} } + +// Incorrect: outer most namespace expansion does not start with `__llvm_libc`. +#define LIBC_NAMESPACE custom_namespace +namespace LIBC_NAMESPACE { +void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/implementation-in-namespace.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/implementation-in-namespace.cpp index e75556a623b655c..16c5f9ca1067ec5 100644 ---