Skip to content

Commit 3a1b568

Browse files
authored
Merge branch 'main' into issue_169295
2 parents b50b68a + e7f6038 commit 3a1b568

File tree

55 files changed

+3052
-1538
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+3052
-1538
lines changed

.github/workflows/premerge.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ jobs:
191191
with:
192192
name: workflow-args-windows
193193
path: |
194-
comments-Windows-x86_64
194+
comments-Windows-AMD64
195195
196196
premerge-check-macos:
197197
name: MacOS Premerge Checks

clang/include/clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "clang/ASTMatchers/ASTMatchers.h"
1414
#include "clang/Analysis/CFG.h"
1515
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
16+
#include "clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h"
1617
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
1718
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
1819
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
@@ -69,7 +70,8 @@ struct UncheckedStatusOrAccessModelOptions {};
6970

7071
// Dataflow analysis that discovers unsafe uses of StatusOr values.
7172
class UncheckedStatusOrAccessModel
72-
: public DataflowAnalysis<UncheckedStatusOrAccessModel, NoopLattice> {
73+
: public DataflowAnalysis<UncheckedStatusOrAccessModel,
74+
CachedConstAccessorsLattice<NoopLattice>> {
7375
public:
7476
explicit UncheckedStatusOrAccessModel(ASTContext &Ctx, Environment &Env);
7577

clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
2626
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
2727
#include "clang/Analysis/FlowSensitive/RecordOps.h"
28+
#include "clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h"
2829
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
2930
#include "clang/Analysis/FlowSensitive/Value.h"
3031
#include "clang/Basic/LLVM.h"
@@ -237,6 +238,49 @@ static auto isAsStatusCallWithStatusOr() {
237238
hasArgument(0, hasType(statusOrType())));
238239
}
239240

241+
static auto possiblyReferencedStatusOrType() {
242+
using namespace ::clang::ast_matchers; // NOLINT: Too many names
243+
return anyOf(statusOrType(), referenceType(pointee(statusOrType())));
244+
}
245+
246+
static auto isConstStatusOrAccessorMemberCall() {
247+
using namespace ::clang::ast_matchers; // NOLINT: Too many names
248+
return cxxMemberCallExpr(callee(
249+
cxxMethodDecl(parameterCountIs(0), isConst(),
250+
returns(qualType(possiblyReferencedStatusOrType())))));
251+
}
252+
253+
static auto isConstStatusOrAccessorMemberOperatorCall() {
254+
using namespace ::clang::ast_matchers; // NOLINT: Too many names
255+
return cxxOperatorCallExpr(
256+
callee(cxxMethodDecl(parameterCountIs(0), isConst(),
257+
returns(possiblyReferencedStatusOrType()))));
258+
}
259+
260+
static auto isConstStatusOrPointerAccessorMemberCall() {
261+
using namespace ::clang::ast_matchers; // NOLINT: Too many names
262+
return cxxMemberCallExpr(callee(cxxMethodDecl(
263+
parameterCountIs(0), isConst(),
264+
returns(pointerType(pointee(possiblyReferencedStatusOrType()))))));
265+
}
266+
267+
static auto isConstStatusOrPointerAccessorMemberOperatorCall() {
268+
using namespace ::clang::ast_matchers; // NOLINT: Too many names
269+
return cxxOperatorCallExpr(callee(cxxMethodDecl(
270+
parameterCountIs(0), isConst(),
271+
returns(pointerType(pointee(possiblyReferencedStatusOrType()))))));
272+
}
273+
274+
static auto isNonConstMemberCall() {
275+
using namespace ::clang::ast_matchers; // NOLINT: Too many names
276+
return cxxMemberCallExpr(callee(cxxMethodDecl(unless(isConst()))));
277+
}
278+
279+
static auto isNonConstMemberOperatorCall() {
280+
using namespace ::clang::ast_matchers; // NOLINT: Too many names
281+
return cxxOperatorCallExpr(callee(cxxMethodDecl(unless(isConst()))));
282+
}
283+
240284
static auto
241285
buildDiagnoseMatchSwitch(const UncheckedStatusOrAccessModelOptions &Options) {
242286
return CFGMatchSwitchBuilder<const Environment,
@@ -698,6 +742,124 @@ static void transferPointerToBoolean(const ImplicitCastExpr *Expr,
698742
State.Env.setValue(*Expr, *SubExprVal);
699743
}
700744

745+
static void transferStatusOrReturningCall(const CallExpr *Expr,
746+
LatticeTransferState &State) {
747+
RecordStorageLocation *StatusOrLoc =
748+
Expr->isPRValue() ? &State.Env.getResultObjectLocation(*Expr)
749+
: State.Env.get<RecordStorageLocation>(*Expr);
750+
if (StatusOrLoc != nullptr &&
751+
State.Env.getValue(locForOk(locForStatus(*StatusOrLoc))) == nullptr)
752+
initializeStatusOr(*StatusOrLoc, State.Env);
753+
}
754+
755+
static bool doHandleConstStatusOrAccessorMemberCall(
756+
const CallExpr *Expr, RecordStorageLocation *RecordLoc,
757+
const MatchFinder::MatchResult &Result, LatticeTransferState &State) {
758+
assert(isStatusOrType(Expr->getType()));
759+
if (RecordLoc == nullptr)
760+
return false;
761+
const FunctionDecl *DirectCallee = Expr->getDirectCallee();
762+
if (DirectCallee == nullptr)
763+
return false;
764+
StorageLocation &Loc =
765+
State.Lattice.getOrCreateConstMethodReturnStorageLocation(
766+
*RecordLoc, DirectCallee, State.Env, [&](StorageLocation &Loc) {
767+
initializeStatusOr(cast<RecordStorageLocation>(Loc), State.Env);
768+
});
769+
if (Expr->isPRValue()) {
770+
auto &ResultLoc = State.Env.getResultObjectLocation(*Expr);
771+
copyRecord(cast<RecordStorageLocation>(Loc), ResultLoc, State.Env);
772+
} else {
773+
State.Env.setStorageLocation(*Expr, Loc);
774+
}
775+
return true;
776+
}
777+
778+
static void handleConstStatusOrAccessorMemberCall(
779+
const CallExpr *Expr, RecordStorageLocation *RecordLoc,
780+
const MatchFinder::MatchResult &Result, LatticeTransferState &State) {
781+
if (!doHandleConstStatusOrAccessorMemberCall(Expr, RecordLoc, Result, State))
782+
transferStatusOrReturningCall(Expr, State);
783+
}
784+
static void handleConstStatusOrPointerAccessorMemberCall(
785+
const CallExpr *Expr, RecordStorageLocation *RecordLoc,
786+
const MatchFinder::MatchResult &Result, LatticeTransferState &State) {
787+
if (RecordLoc == nullptr)
788+
return;
789+
auto *Val = State.Lattice.getOrCreateConstMethodReturnValue(*RecordLoc, Expr,
790+
State.Env);
791+
State.Env.setValue(*Expr, *Val);
792+
}
793+
794+
static void
795+
transferConstStatusOrAccessorMemberCall(const CXXMemberCallExpr *Expr,
796+
const MatchFinder::MatchResult &Result,
797+
LatticeTransferState &State) {
798+
handleConstStatusOrAccessorMemberCall(
799+
Expr, getImplicitObjectLocation(*Expr, State.Env), Result, State);
800+
}
801+
802+
static void transferConstStatusOrAccessorMemberOperatorCall(
803+
const CXXOperatorCallExpr *Expr, const MatchFinder::MatchResult &Result,
804+
LatticeTransferState &State) {
805+
auto *RecordLoc = cast_or_null<RecordStorageLocation>(
806+
State.Env.getStorageLocation(*Expr->getArg(0)));
807+
handleConstStatusOrAccessorMemberCall(Expr, RecordLoc, Result, State);
808+
}
809+
810+
static void transferConstStatusOrPointerAccessorMemberCall(
811+
const CXXMemberCallExpr *Expr, const MatchFinder::MatchResult &Result,
812+
LatticeTransferState &State) {
813+
handleConstStatusOrPointerAccessorMemberCall(
814+
Expr, getImplicitObjectLocation(*Expr, State.Env), Result, State);
815+
}
816+
817+
static void transferConstStatusOrPointerAccessorMemberOperatorCall(
818+
const CXXOperatorCallExpr *Expr, const MatchFinder::MatchResult &Result,
819+
LatticeTransferState &State) {
820+
auto *RecordLoc = cast_or_null<RecordStorageLocation>(
821+
State.Env.getStorageLocation(*Expr->getArg(0)));
822+
handleConstStatusOrPointerAccessorMemberCall(Expr, RecordLoc, Result, State);
823+
}
824+
825+
static void handleNonConstMemberCall(const CallExpr *Expr,
826+
RecordStorageLocation *RecordLoc,
827+
const MatchFinder::MatchResult &Result,
828+
LatticeTransferState &State) {
829+
if (RecordLoc) {
830+
State.Lattice.clearConstMethodReturnValues(*RecordLoc);
831+
State.Lattice.clearConstMethodReturnStorageLocations(*RecordLoc);
832+
}
833+
if (isStatusOrType(Expr->getType()))
834+
transferStatusOrReturningCall(Expr, State);
835+
}
836+
837+
static void transferNonConstMemberCall(const CXXMemberCallExpr *Expr,
838+
const MatchFinder::MatchResult &Result,
839+
LatticeTransferState &State) {
840+
handleNonConstMemberCall(Expr, getImplicitObjectLocation(*Expr, State.Env),
841+
Result, State);
842+
}
843+
844+
static void
845+
transferNonConstMemberOperatorCall(const CXXOperatorCallExpr *Expr,
846+
const MatchFinder::MatchResult &Result,
847+
LatticeTransferState &State) {
848+
auto *RecordLoc = cast_or_null<RecordStorageLocation>(
849+
State.Env.getStorageLocation(*Expr->getArg(0)));
850+
handleNonConstMemberCall(Expr, RecordLoc, Result, State);
851+
}
852+
853+
static RecordStorageLocation *
854+
getSmartPtrLikeStorageLocation(const Expr &E, const Environment &Env) {
855+
if (!E.isPRValue())
856+
return dyn_cast_or_null<RecordStorageLocation>(Env.getStorageLocation(E));
857+
if (auto *PointerVal = dyn_cast_or_null<PointerValue>(Env.getValue(E)))
858+
return dyn_cast_or_null<RecordStorageLocation>(
859+
&PointerVal->getPointeeLoc());
860+
return nullptr;
861+
}
862+
701863
CFGMatchSwitch<LatticeTransferState>
702864
buildTransferMatchSwitch(ASTContext &Ctx,
703865
CFGMatchSwitchBuilder<LatticeTransferState> Builder) {
@@ -755,6 +917,60 @@ buildTransferMatchSwitch(ASTContext &Ctx,
755917
transferLoggingGetReferenceableValueCall)
756918
.CaseOfCFGStmt<CallExpr>(isLoggingCheckEqImpl(),
757919
transferLoggingCheckEqImpl)
920+
// This needs to go before the const accessor call matcher, because these
921+
// look like them, but we model `operator`* and `get` to return the same
922+
// object. Also, we model them for non-const cases.
923+
.CaseOfCFGStmt<CXXOperatorCallExpr>(
924+
isPointerLikeOperatorStar(),
925+
[](const CXXOperatorCallExpr *E,
926+
const MatchFinder::MatchResult &Result,
927+
LatticeTransferState &State) {
928+
transferSmartPointerLikeCachedDeref(
929+
E, getSmartPtrLikeStorageLocation(*E->getArg(0), State.Env),
930+
State, [](StorageLocation &Loc) {});
931+
})
932+
.CaseOfCFGStmt<CXXOperatorCallExpr>(
933+
isPointerLikeOperatorArrow(),
934+
[](const CXXOperatorCallExpr *E,
935+
const MatchFinder::MatchResult &Result,
936+
LatticeTransferState &State) {
937+
transferSmartPointerLikeCachedGet(
938+
E, getSmartPtrLikeStorageLocation(*E->getArg(0), State.Env),
939+
State, [](StorageLocation &Loc) {});
940+
})
941+
.CaseOfCFGStmt<CXXMemberCallExpr>(
942+
isSmartPointerLikeValueMethodCall(),
943+
[](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &Result,
944+
LatticeTransferState &State) {
945+
transferSmartPointerLikeCachedDeref(
946+
E, getImplicitObjectLocation(*E, State.Env), State,
947+
[](StorageLocation &Loc) {});
948+
})
949+
.CaseOfCFGStmt<CXXMemberCallExpr>(
950+
isSmartPointerLikeGetMethodCall(),
951+
[](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &Result,
952+
LatticeTransferState &State) {
953+
transferSmartPointerLikeCachedGet(
954+
E, getImplicitObjectLocation(*E, State.Env), State,
955+
[](StorageLocation &Loc) {});
956+
})
957+
// const accessor calls
958+
.CaseOfCFGStmt<CXXMemberCallExpr>(isConstStatusOrAccessorMemberCall(),
959+
transferConstStatusOrAccessorMemberCall)
960+
.CaseOfCFGStmt<CXXOperatorCallExpr>(
961+
isConstStatusOrAccessorMemberOperatorCall(),
962+
transferConstStatusOrAccessorMemberOperatorCall)
963+
.CaseOfCFGStmt<CXXMemberCallExpr>(
964+
isConstStatusOrPointerAccessorMemberCall(),
965+
transferConstStatusOrPointerAccessorMemberCall)
966+
.CaseOfCFGStmt<CXXOperatorCallExpr>(
967+
isConstStatusOrPointerAccessorMemberOperatorCall(),
968+
transferConstStatusOrPointerAccessorMemberOperatorCall)
969+
// non-const member calls that may modify the state of an object.
970+
.CaseOfCFGStmt<CXXMemberCallExpr>(isNonConstMemberCall(),
971+
transferNonConstMemberCall)
972+
.CaseOfCFGStmt<CXXOperatorCallExpr>(isNonConstMemberOperatorCall(),
973+
transferNonConstMemberOperatorCall)
758974
// N.B. These need to come after all other CXXConstructExpr.
759975
// These are there to make sure that every Status and StatusOr object
760976
// have their ok boolean initialized when constructed. If we were to

clang/lib/Headers/__clang_hip_math.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ __DEVICE__
498498
float log2f(float __x) { return __FAST_OR_SLOW(__log2f, __builtin_log2f)(__x); }
499499

500500
__DEVICE__
501-
float logbf(float __x) { return __ocml_logb_f32(__x); }
501+
float logbf(float __x) { return __builtin_logbf(__x); }
502502

503503
__DEVICE__
504504
float logf(float __x) { return __FAST_OR_SLOW(__logf, __builtin_logf)(__x); }
@@ -901,7 +901,7 @@ __DEVICE__
901901
double log2(double __x) { return __ocml_log2_f64(__x); }
902902

903903
__DEVICE__
904-
double logb(double __x) { return __ocml_logb_f64(__x); }
904+
double logb(double __x) { return __builtin_logb(__x); }
905905

906906
__DEVICE__
907907
long int lrint(double __x) { return __builtin_rint(__x); }

0 commit comments

Comments
 (0)