Skip to content

Commit f8ddede

Browse files
Merge branch 'main' into main
2 parents 2ad206f + 9d48705 commit f8ddede

File tree

36 files changed

+1300
-233
lines changed

36 files changed

+1300
-233
lines changed

clang/lib/Sema/CheckExprLifetime.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,11 +1239,12 @@ static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path,
12391239
}
12401240
// Check the return type, e.g.
12411241
// const GSLOwner& func(const Foo& foo [[clang::lifetimebound]])
1242+
// GSLOwner* func(cosnt Foo& foo [[clang::lifetimebound]])
12421243
// GSLPointer func(const Foo& foo [[clang::lifetimebound]])
12431244
if (FD &&
1244-
((FD->getReturnType()->isReferenceType() &&
1245+
((FD->getReturnType()->isPointerOrReferenceType() &&
12451246
isRecordWithAttr<OwnerAttr>(FD->getReturnType()->getPointeeType())) ||
1246-
isPointerLikeType(FD->getReturnType())))
1247+
isGLSPointerType(FD->getReturnType())))
12471248
return Report;
12481249

12491250
return Abandon;

clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,57 @@ using MutexDescriptor =
145145
std::variant<FirstArgMutexDescriptor, MemberMutexDescriptor,
146146
RAIIMutexDescriptor>;
147147

148+
class SuppressNonBlockingStreams : public BugReporterVisitor {
149+
private:
150+
const CallDescription OpenFunction{CDM::CLibrary, {"open"}, 2};
151+
SymbolRef StreamSym;
152+
const int NonBlockMacroVal;
153+
bool Satisfied = false;
154+
155+
public:
156+
SuppressNonBlockingStreams(SymbolRef StreamSym, int NonBlockMacroVal)
157+
: StreamSym(StreamSym), NonBlockMacroVal(NonBlockMacroVal) {}
158+
159+
static void *getTag() {
160+
static bool Tag;
161+
return &Tag;
162+
}
163+
164+
void Profile(llvm::FoldingSetNodeID &ID) const override {
165+
ID.AddPointer(getTag());
166+
}
167+
168+
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
169+
BugReporterContext &BRC,
170+
PathSensitiveBugReport &BR) override {
171+
if (Satisfied)
172+
return nullptr;
173+
174+
std::optional<StmtPoint> Point = N->getLocationAs<StmtPoint>();
175+
if (!Point)
176+
return nullptr;
177+
178+
const auto *CE = Point->getStmtAs<CallExpr>();
179+
if (!CE || !OpenFunction.matchesAsWritten(*CE))
180+
return nullptr;
181+
182+
if (N->getSVal(CE).getAsSymbol() != StreamSym)
183+
return nullptr;
184+
185+
Satisfied = true;
186+
187+
// Check if open's second argument contains O_NONBLOCK
188+
const llvm::APSInt *FlagVal = N->getSVal(CE->getArg(1)).getAsInteger();
189+
if (!FlagVal)
190+
return nullptr;
191+
192+
if ((*FlagVal & NonBlockMacroVal) != 0)
193+
BR.markInvalid(getTag(), nullptr);
194+
195+
return nullptr;
196+
}
197+
};
198+
148199
class BlockInCriticalSectionChecker : public Checker<check::PostCall> {
149200
private:
150201
const std::array<MutexDescriptor, 8> MutexDescriptors{
@@ -182,6 +233,9 @@ class BlockInCriticalSectionChecker : public Checker<check::PostCall> {
182233
const BugType BlockInCritSectionBugType{
183234
this, "Call to blocking function in critical section", "Blocking Error"};
184235

236+
using O_NONBLOCKValueTy = std::optional<int>;
237+
mutable std::optional<O_NONBLOCKValueTy> O_NONBLOCKValue;
238+
185239
void reportBlockInCritSection(const CallEvent &call, CheckerContext &C) const;
186240

187241
[[nodiscard]] const NoteTag *createCritSectionNote(CritSectionMarker M,
@@ -337,6 +391,28 @@ void BlockInCriticalSectionChecker::reportBlockInCritSection(
337391
<< "' inside of critical section";
338392
auto R = std::make_unique<PathSensitiveBugReport>(BlockInCritSectionBugType,
339393
os.str(), ErrNode);
394+
// for 'read' and 'recv' call, check whether it's file descriptor(first
395+
// argument) is
396+
// created by 'open' API with O_NONBLOCK flag or is equal to -1, they will
397+
// not cause block in these situations, don't report
398+
StringRef FuncName = Call.getCalleeIdentifier()->getName();
399+
if (FuncName == "read" || FuncName == "recv") {
400+
SVal SV = Call.getArgSVal(0);
401+
SValBuilder &SVB = C.getSValBuilder();
402+
ProgramStateRef state = C.getState();
403+
ConditionTruthVal CTV =
404+
state->areEqual(SV, SVB.makeIntVal(-1, C.getASTContext().IntTy));
405+
if (CTV.isConstrainedTrue())
406+
return;
407+
408+
if (SymbolRef SR = SV.getAsSymbol()) {
409+
if (!O_NONBLOCKValue)
410+
O_NONBLOCKValue = tryExpandAsInteger(
411+
"O_NONBLOCK", C.getBugReporter().getPreprocessor());
412+
if (*O_NONBLOCKValue)
413+
R->addVisitor<SuppressNonBlockingStreams>(SR, **O_NONBLOCKValue);
414+
}
415+
}
340416
R->addRange(Call.getSourceRange());
341417
R->markInteresting(Call.getReturnValue());
342418
C.emitReport(std::move(R));
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma clang system_header
2+
3+
namespace std {
4+
struct mutex {
5+
void lock();
6+
void unlock();
7+
};
8+
9+
template <typename T> struct lock_guard {
10+
lock_guard(std::mutex &);
11+
~lock_guard();
12+
};
13+
} // namespace std
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %clang_analyze_cc1 \
2+
// RUN: -analyzer-checker=core,unix.BlockInCriticalSection \
3+
// RUN: -analyzer-output text -verify %s
4+
5+
// expected-no-diagnostics
6+
7+
#include "Inputs/system-header-simulator-cxx-std-locks.h"
8+
9+
std::mutex mtx;
10+
using ssize_t = long long;
11+
using size_t = unsigned long long;
12+
int open(const char *__file, int __oflag, ...);
13+
ssize_t read(int fd, void *buf, size_t count);
14+
void close(int fd);
15+
#define O_RDONLY 00
16+
#define O_NONBLOCK 04000
17+
18+
void foo() {
19+
std::lock_guard<std::mutex> lock(mtx);
20+
21+
const char *filename = "example.txt";
22+
int fd = open(filename, O_RDONLY | O_NONBLOCK);
23+
24+
char buffer[200] = {};
25+
read(fd, buffer, 199); // no-warning: fd is a non-block file descriptor or equals to -1
26+
close(fd);
27+
}
28+
29+
void foo1(int fd) {
30+
std::lock_guard<std::mutex> lock(mtx);
31+
32+
const char *filename = "example.txt";
33+
char buffer[200] = {};
34+
if (fd == -1)
35+
read(fd, buffer, 199); // no-warning: consider file descriptor is a symbol equals to -1
36+
close(fd);
37+
}

clang/test/Sema/Inputs/lifetime-analysis.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct basic_string_view {
6161
basic_string_view();
6262
basic_string_view(const T *);
6363
const T *begin() const;
64+
const T *data() const;
6465
};
6566
using string_view = basic_string_view<char>;
6667

@@ -80,6 +81,7 @@ struct basic_string {
8081
const T *c_str() const;
8182
operator basic_string_view<T> () const;
8283
using const_iterator = iter<T>;
84+
const T *data() const;
8385
};
8486
using string = basic_string<char>;
8587

clang/test/Sema/warn-lifetime-analysis-nocfg.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,3 +852,27 @@ struct Test {
852852
};
853853

854854
} // namespace GH120543
855+
856+
namespace GH127195 {
857+
template <typename T>
858+
struct StatusOr {
859+
T* operator->() [[clang::lifetimebound]];
860+
T* value() [[clang::lifetimebound]];
861+
};
862+
863+
const char* foo() {
864+
StatusOr<std::string> s;
865+
return s->data(); // expected-warning {{address of stack memory associated with local variable}}
866+
867+
StatusOr<std::string_view> s2;
868+
return s2->data();
869+
870+
StatusOr<StatusOr<std::string_view>> s3;
871+
return s3.value()->value()->data();
872+
873+
// FIXME: nested cases are not supported now.
874+
StatusOr<StatusOr<std::string>> s4;
875+
return s4.value()->value()->data();
876+
}
877+
878+
} // namespace GH127195

compiler-rt/lib/builtins/arm/negdf2vfp.S

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ DEFINE_COMPILERRT_FUNCTION(__negdf2vfp)
2020
#if defined(COMPILER_RT_ARMHF_TARGET)
2121
vneg.f64 d0, d0
2222
#else
23-
eor r1, r1, #-2147483648 // flip sign bit on double in r0/r1 pair
23+
#if _YUGA_BIG_ENDIAN
24+
eor r0, r0, #0x80000000 // flip sign bit on double in r0/r1 pair
25+
#else
26+
eor r1, r1, #0x80000000 // flip sign bit on double in r0/r1 pair
27+
#endif
2428
#endif
2529
bx lr
2630
END_COMPILERRT_FUNCTION(__negdf2vfp)

flang-rt/CMakeLists.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@ endif ()
115115
extend_path(FLANG_RT_INSTALL_RESOURCE_LIB_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}")
116116
cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_DIR)
117117
cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_PATH)
118+
# FIXME: For the libflang_rt.so, the toolchain resource lib dir is not a good
119+
# destination because it is not a ld.so default search path.
120+
# The machine where the executable is eventually executed may not be the
121+
# machine where the Flang compiler and its resource dir is installed, so
122+
# setting RPath by the driver is not an solution. It should belong into
123+
# /usr/lib/<triple>/libflang_rt.so, like e.g. libgcc_s.so.
124+
# But the linker as invoked by the Flang driver also requires
125+
# libflang_rt.so to be found when linking and the resource lib dir is
126+
# the only reliable location.
118127
cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_LIB_DIR)
119128
cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
120129

@@ -129,6 +138,27 @@ cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
129138
option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
130139

131140

141+
option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." ON)
142+
if (WIN32)
143+
# Windows DLL currently not implemented.
144+
set(FLANG_RT_ENABLE_SHARED OFF)
145+
else ()
146+
# TODO: Enable by default to increase test coverage, and which version of the
147+
# library should be the user's choice anyway.
148+
# Currently, the Flang driver adds `-L"libdir" -lflang_rt` as linker
149+
# argument, which leaves the choice which library to use to the linker.
150+
# Since most linkers prefer the shared library, this would constitute a
151+
# breaking change unless the driver is changed.
152+
option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." OFF)
153+
endif ()
154+
if (NOT FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED)
155+
message(FATAL_ERROR "
156+
Must build at least one type of library
157+
(FLANG_RT_ENABLE_STATIC=ON, FLANG_RT_ENABLE_SHARED=ON, or both)
158+
")
159+
endif ()
160+
161+
132162
set(FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT "" CACHE STRING "Compile Flang-RT with GPU support (CUDA or OpenMP)")
133163
set_property(CACHE FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT PROPERTY STRINGS
134164
""

0 commit comments

Comments
 (0)