81#include "llvm/ADT/APFloat.h"
82#include "llvm/ADT/APInt.h"
83#include "llvm/ADT/APSInt.h"
84#include "llvm/ADT/ArrayRef.h"
85#include "llvm/ADT/DenseMap.h"
86#include "llvm/ADT/FoldingSet.h"
87#include "llvm/ADT/STLExtras.h"
88#include "llvm/ADT/STLForwardCompat.h"
89#include "llvm/ADT/SmallBitVector.h"
90#include "llvm/ADT/SmallPtrSet.h"
91#include "llvm/ADT/SmallString.h"
92#include "llvm/ADT/SmallVector.h"
93#include "llvm/ADT/StringExtras.h"
94#include "llvm/ADT/StringRef.h"
95#include "llvm/ADT/StringSet.h"
96#include "llvm/ADT/StringSwitch.h"
97#include "llvm/Support/AtomicOrdering.h"
98#include "llvm/Support/Compiler.h"
99#include "llvm/Support/ConvertUTF.h"
100#include "llvm/Support/ErrorHandling.h"
101#include "llvm/Support/Format.h"
102#include "llvm/Support/Locale.h"
103#include "llvm/Support/MathExtras.h"
104#include "llvm/Support/SaveAndRestore.h"
105#include "llvm/Support/raw_ostream.h"
106#include "llvm/TargetParser/RISCVTargetParser.h"
107#include "llvm/TargetParser/Triple.h"
120using namespace clang;
124 unsigned ByteNo)
const {
135 unsigned ArgCount =
Call->getNumArgs();
136 if (ArgCount >= MinArgCount)
139 return Diag(
Call->getEndLoc(), diag::err_typecheck_call_too_few_args)
140 << 0 << MinArgCount << ArgCount
141 << 0 <<
Call->getSourceRange();
145 unsigned ArgCount =
Call->getNumArgs();
146 if (ArgCount <= MaxArgCount)
148 return Diag(
Call->getEndLoc(), diag::err_typecheck_call_too_many_args_at_most)
149 << 0 << MaxArgCount << ArgCount
150 << 0 <<
Call->getSourceRange();
154 unsigned MaxArgCount) {
160 unsigned ArgCount =
Call->getNumArgs();
161 if (ArgCount == DesiredArgCount)
166 assert(ArgCount > DesiredArgCount &&
"should have diagnosed this");
170 Call->getArg(ArgCount - 1)->getEndLoc());
172 return Diag(Range.getBegin(), diag::err_typecheck_call_too_many_args)
173 << 0 << DesiredArgCount << ArgCount
178 bool HasError =
false;
180 for (
const Expr *Arg :
Call->arguments()) {
181 if (Arg->isValueDependent())
184 std::optional<std::string> ArgString = Arg->tryEvaluateString(S.
Context);
185 int DiagMsgKind = -1;
187 if (!ArgString.has_value())
189 else if (ArgString->find(
'$') != std::string::npos)
192 if (DiagMsgKind >= 0) {
193 S.
Diag(Arg->getBeginLoc(), diag::err_builtin_verbose_trap_arg)
194 << DiagMsgKind << Arg->getSourceRange();
203 if (
Value->isTypeDependent())
210 if (Result.isInvalid())
212 Value = Result.get();
234 if (!Literal || !Literal->isOrdinary()) {
247 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
255 auto *Literal = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts());
256 if (!Literal || !Literal->isWide()) {
257 S.
Diag(Arg->getBeginLoc(), diag::err_msvc_annotation_wide_str)
258 << Arg->getSourceRange();
295 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(
326 bool IsBooleanAlignBuiltin = ID == Builtin::BI__builtin_is_aligned;
328 auto IsValidIntegerType = [](
QualType Ty) {
329 return Ty->isIntegerType() && !Ty->isEnumeralType() && !Ty->isBooleanType();
336 if ((!SrcTy->
isPointerType() && !IsValidIntegerType(SrcTy)) ||
340 S.
Diag(Source->getExprLoc(), diag::err_typecheck_expect_scalar_operand)
346 if (!IsValidIntegerType(AlignOp->
getType())) {
357 llvm::APSInt AlignValue = AlignResult.
Val.
getInt();
358 llvm::APSInt MaxValue(
359 llvm::APInt::getOneBitSet(MaxAlignmentBits + 1, MaxAlignmentBits));
360 if (AlignValue < 1) {
361 S.
Diag(AlignOp->
getExprLoc(), diag::err_alignment_too_small) << 1;
364 if (llvm::APSInt::compareValues(AlignValue, MaxValue) > 0) {
369 if (!AlignValue.isPowerOf2()) {
370 S.
Diag(AlignOp->
getExprLoc(), diag::err_alignment_not_power_of_two);
373 if (AlignValue == 1) {
374 S.
Diag(AlignOp->
getExprLoc(), diag::warn_alignment_builtin_useless)
375 << IsBooleanAlignBuiltin;
403 std::pair<unsigned, const char *> Builtins[] = {
404 { Builtin::BI__builtin_add_overflow,
"ckd_add" },
405 { Builtin::BI__builtin_sub_overflow,
"ckd_sub" },
406 { Builtin::BI__builtin_mul_overflow,
"ckd_mul" },
409 bool CkdOperation = llvm::any_of(Builtins, [&](
const std::pair<
unsigned,
416 auto ValidCkdIntType = [](
QualType QT) {
419 if (
const auto *BT = QT.getCanonicalType()->getAs<
BuiltinType>())
420 return (BT->getKind() >= BuiltinType::Short &&
421 BT->getKind() <= BuiltinType::Int128) || (
422 BT->getKind() >= BuiltinType::UShort &&
423 BT->getKind() <= BuiltinType::UInt128) ||
424 BT->getKind() == BuiltinType::UChar ||
425 BT->getKind() == BuiltinType::SChar;
430 for (
unsigned I = 0; I < 2; ++I) {
436 bool IsValid = CkdOperation ? ValidCkdIntType(Ty) : Ty->
isIntegerType();
455 !PtrTy->getPointeeType()->isIntegerType() ||
456 (!ValidCkdIntType(PtrTy->getPointeeType()) && CkdOperation) ||
457 PtrTy->getPointeeType().isConstQualified()) {
459 diag::err_overflow_builtin_must_be_ptr_int)
467 if (BuiltinID == Builtin::BI__builtin_mul_overflow) {
468 for (
unsigned I = 0; I < 3; ++I) {
469 const auto Arg = TheCall->
getArg(I);
472 if (Ty->isBitIntType() && Ty->isSignedIntegerType() &&
474 return S.
Diag(Arg->getBeginLoc(),
475 diag::err_overflow_builtin_bit_int_max_size)
484struct BuiltinDumpStructGenerator {
488 SmallVector<Expr *, 32> Actions;
489 DiagnosticErrorTrap ErrorTracker;
490 PrintingPolicy Policy;
492 BuiltinDumpStructGenerator(Sema &S, CallExpr *TheCall)
493 : S(S), TheCall(TheCall), ErrorTracker(S.getDiagnostics()),
494 Policy(S.Context.getPrintingPolicy()) {
498 Expr *makeOpaqueValueExpr(Expr *Inner) {
502 Actions.push_back(OVE);
506 Expr *getStringLiteral(llvm::StringRef Str) {
509 return new (S.
Context) ParenExpr(Loc, Loc, Lit);
512 bool callPrintFunction(llvm::StringRef Format,
513 llvm::ArrayRef<Expr *> Exprs = {}) {
514 SmallVector<Expr *, 8> Args;
516 Args.reserve((TheCall->
getNumArgs() - 2) + 1 + Exprs.size());
518 Args.push_back(getStringLiteral(Format));
519 llvm::append_range(Args, Exprs);
522 Sema::CodeSynthesisContext Ctx;
535 Actions.push_back(RealCall.
get());
541 Expr *getIndentString(
unsigned Depth) {
545 llvm::SmallString<32>
Indent;
547 return getStringLiteral(
Indent);
551 return getStringLiteral(
T.getAsString(Policy));
554 bool appendFormatSpecifier(QualType
T, llvm::SmallVectorImpl<char> &Str) {
555 llvm::raw_svector_ostream
OS(Str);
559 if (
auto *BT =
T->
getAs<BuiltinType>()) {
560 switch (BT->getKind()) {
561 case BuiltinType::Bool:
564 case BuiltinType::Char_U:
565 case BuiltinType::UChar:
568 case BuiltinType::Char_S:
569 case BuiltinType::SChar:
577 analyze_printf::PrintfSpecifier
Specifier;
580 if (
Specifier.getConversionSpecifier().getKind() ==
581 analyze_printf::PrintfConversionSpecifier::sArg) {
587 Specifier.setPrecision(analyze_printf::OptionalAmount(32u));
607 bool dumpUnnamedRecord(
const RecordDecl *RD, Expr *E,
unsigned Depth) {
608 Expr *IndentLit = getIndentString(Depth);
610 if (IndentLit ? callPrintFunction(
"%s%s", {IndentLit, TypeLit})
611 : callPrintFunction(
"%s", {TypeLit}))
614 return dumpRecordValue(RD, E, IndentLit, Depth);
618 bool dumpRecordValue(
const RecordDecl *RD, Expr *E, Expr *RecordIndent,
627 Expr *RecordArg = makeOpaqueValueExpr(E);
630 if (callPrintFunction(
" {\n"))
634 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
635 for (
const auto &Base : CXXRD->bases()) {
643 dumpUnnamedRecord(
Base.getType()->getAsRecordDecl(), BasePtr.
get(),
649 Expr *FieldIndentArg = getIndentString(Depth + 1);
652 for (
auto *D : RD->
decls()) {
653 auto *IFD = dyn_cast<IndirectFieldDecl>(D);
654 auto *FD = IFD ? IFD->getAnonField() : dyn_cast<FieldDecl>(D);
655 if (!FD || FD->isUnnamedBitField() || FD->isAnonymousStructOrUnion())
658 llvm::SmallString<20> Format = llvm::StringRef(
"%s%s %s ");
659 llvm::SmallVector<Expr *, 5> Args = {FieldIndentArg,
661 getStringLiteral(FD->getName())};
663 if (FD->isBitField()) {
667 FD->getBitWidthValue());
675 CXXScopeSpec(), Loc, IFD,
678 RecordArg, RecordArgIsPtr, Loc, CXXScopeSpec(), FD,
680 DeclarationNameInfo(FD->getDeclName(), Loc));
681 if (
Field.isInvalid())
684 auto *InnerRD = FD->getType()->getAsRecordDecl();
685 auto *InnerCXXRD = dyn_cast_or_null<CXXRecordDecl>(InnerRD);
686 if (InnerRD && (!InnerCXXRD || InnerCXXRD->isAggregate())) {
688 if (callPrintFunction(Format, Args) ||
689 dumpRecordValue(InnerRD,
Field.get(), FieldIndentArg, Depth + 1))
693 if (appendFormatSpecifier(FD->getType(), Format)) {
695 Args.push_back(
Field.get());
705 Args.push_back(FieldAddr.
get());
708 if (callPrintFunction(Format, Args))
713 return RecordIndent ? callPrintFunction(
"%s}\n", RecordIndent)
714 : callPrintFunction(
"}\n");
717 Expr *buildWrapper() {
720 TheCall->
setType(Wrapper->getType());
741 diag::err_expected_struct_pointer_argument)
750 diag::err_incomplete_type))
759 switch (BT ? BT->getKind() : BuiltinType::Void) {
760 case BuiltinType::Dependent:
761 case BuiltinType::Overload:
762 case BuiltinType::BoundMember:
763 case BuiltinType::PseudoObject:
764 case BuiltinType::UnknownAny:
765 case BuiltinType::BuiltinFn:
771 diag::err_expected_callable_argument)
777 BuiltinDumpStructGenerator Generator(S, TheCall);
783 Expr *PtrArg = PtrArgResult.
get();
787 if (Generator.dumpUnnamedRecord(RD, PtrArg, 0))
790 return Generator.buildWrapper();
802 if (
Call->getStmtClass() != Stmt::CallExprClass) {
803 S.
Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_not_call)
804 <<
Call->getSourceRange();
809 if (CE->getCallee()->getType()->isBlockPointerType()) {
810 S.
Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_block_call)
811 <<
Call->getSourceRange();
815 const Decl *TargetDecl = CE->getCalleeDecl();
816 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
817 if (FD->getBuiltinID()) {
818 S.
Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_builtin_call)
819 <<
Call->getSourceRange();
824 S.
Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_pdtor_call)
825 <<
Call->getSourceRange();
833 S.
Diag(BuiltinLoc, diag::err_second_argument_to_cwsc_not_pointer)
847 BuiltinCall->
setType(CE->getType());
851 BuiltinCall->
setArg(1, ChainResult.
get());
858class ScanfDiagnosticFormatHandler
862 using ComputeSizeFunction =
863 llvm::function_ref<std::optional<llvm::APSInt>(
unsigned)>;
867 using DiagnoseFunction =
868 llvm::function_ref<void(
unsigned,
unsigned,
unsigned)>;
870 ComputeSizeFunction ComputeSizeArgument;
871 DiagnoseFunction Diagnose;
874 ScanfDiagnosticFormatHandler(ComputeSizeFunction ComputeSizeArgument,
875 DiagnoseFunction Diagnose)
876 : ComputeSizeArgument(ComputeSizeArgument), Diagnose(Diagnose) {}
878 bool HandleScanfSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
879 const char *StartSpecifier,
880 unsigned specifierLen)
override {
884 unsigned NulByte = 0;
896 analyze_format_string::OptionalAmount FW = FS.
getFieldWidth();
898 analyze_format_string::OptionalAmount::HowSpecified::Constant)
903 std::optional<llvm::APSInt> DestSizeAPS =
908 unsigned DestSize = DestSizeAPS->getZExtValue();
910 if (DestSize < SourceSize)
917class EstimateSizeFormatHandler
922 bool IsKernelCompatible =
true;
925 EstimateSizeFormatHandler(StringRef Format)
926 :
Size(std::
min(Format.find(0), Format.size()) +
929 bool HandlePrintfSpecifier(
const analyze_printf::PrintfSpecifier &FS,
930 const char *,
unsigned SpecifierLen,
931 const TargetInfo &)
override {
933 const size_t FieldWidth = computeFieldWidth(FS);
934 const size_t Precision = computePrecision(FS);
941 Size += std::max(FieldWidth, (
size_t)1);
953 Size += std::max(FieldWidth, Precision);
969 Size += std::max(FieldWidth, 1 +
970 (Precision ? 1 + Precision
980 (Precision ? 1 + Precision : 0) +
990 (Precision ? 1 + Precision : 0) +
1005 IsKernelCompatible =
false;
1006 Size += std::max(FieldWidth, 2 + Precision);
1053 Size += (Precision ? 0 : 1);
1060 assert(SpecifierLen <= Size &&
"no underflow");
1061 Size -= SpecifierLen;
1065 size_t getSizeLowerBound()
const {
return Size; }
1066 bool isKernelCompatible()
const {
return IsKernelCompatible; }
1069 static size_t computeFieldWidth(
const analyze_printf::PrintfSpecifier &FS) {
1070 const analyze_format_string::OptionalAmount &FW = FS.
getFieldWidth();
1071 size_t FieldWidth = 0;
1077 static size_t computePrecision(
const analyze_printf::PrintfSpecifier &FS) {
1078 const analyze_format_string::OptionalAmount &FW = FS.
getPrecision();
1079 size_t Precision = 0;
1126 StringRef &FormatStrRef,
size_t &StrLen,
1128 if (
const auto *Format = dyn_cast<StringLiteral>(FormatExpr);
1129 Format && (Format->isOrdinary() || Format->isUTF8())) {
1130 FormatStrRef = Format->getString();
1132 Context.getAsConstantArrayType(Format->getType());
1133 assert(
T &&
"String literal not of constant array type!");
1134 size_t TypeSize =
T->getZExtSize();
1136 StrLen = std::min(std::max(TypeSize,
size_t(1)) - 1, FormatStrRef.find(0));
1142void Sema::checkFortifiedBuiltinMemoryFunction(
FunctionDecl *FD,
1148 bool UseDABAttr =
false;
1149 const FunctionDecl *UseDecl = FD;
1151 const auto *DABAttr = FD->
getAttr<DiagnoseAsBuiltinAttr>();
1153 UseDecl = DABAttr->getFunction();
1154 assert(UseDecl &&
"Missing FunctionDecl in DiagnoseAsBuiltin attribute!");
1166 auto TranslateIndex = [&](
unsigned Index) -> std::optional<unsigned> {
1173 unsigned DABIndices = DABAttr->argIndices_size();
1174 unsigned NewIndex = Index < DABIndices
1175 ? DABAttr->argIndices_begin()[Index]
1178 return std::nullopt;
1182 auto ComputeExplicitObjectSizeArgument =
1183 [&](
unsigned Index) -> std::optional<llvm::APSInt> {
1184 std::optional<unsigned> IndexOptional = TranslateIndex(Index);
1186 return std::nullopt;
1187 unsigned NewIndex = *IndexOptional;
1189 Expr *SizeArg = TheCall->
getArg(NewIndex);
1191 return std::nullopt;
1197 auto ComputeSizeArgument =
1198 [&](
unsigned Index) -> std::optional<llvm::APSInt> {
1204 if (Index < FD->getNumParams()) {
1205 if (
const auto *POS =
1207 BOSType = POS->getType();
1210 std::optional<unsigned> IndexOptional = TranslateIndex(Index);
1212 return std::nullopt;
1213 unsigned NewIndex = *IndexOptional;
1216 return std::nullopt;
1218 const Expr *ObjArg = TheCall->
getArg(NewIndex);
1221 return std::nullopt;
1224 return llvm::APSInt::getUnsigned(
Result).extOrTrunc(SizeTypeWidth);
1227 auto ComputeStrLenArgument =
1228 [&](
unsigned Index) -> std::optional<llvm::APSInt> {
1229 std::optional<unsigned> IndexOptional = TranslateIndex(Index);
1231 return std::nullopt;
1232 unsigned NewIndex = *IndexOptional;
1234 const Expr *ObjArg = TheCall->
getArg(NewIndex);
1237 return std::nullopt;
1239 return llvm::APSInt::getUnsigned(
Result + 1).extOrTrunc(SizeTypeWidth);
1242 std::optional<llvm::APSInt> SourceSize;
1243 std::optional<llvm::APSInt> DestinationSize;
1244 unsigned DiagID = 0;
1245 bool IsChkVariant =
false;
1247 auto GetFunctionName = [&]() {
1248 std::string FunctionNameStr =
1250 llvm::StringRef FunctionName = FunctionNameStr;
1255 FunctionName = FunctionName.drop_front(std::strlen(
"__builtin___"));
1256 FunctionName = FunctionName.drop_back(std::strlen(
"_chk"));
1258 FunctionName.consume_front(
"__builtin_");
1260 return FunctionName.str();
1263 switch (BuiltinID) {
1266 case Builtin::BI__builtin_stpcpy:
1267 case Builtin::BIstpcpy:
1268 case Builtin::BI__builtin_strcpy:
1269 case Builtin::BIstrcpy: {
1270 DiagID = diag::warn_fortify_strlen_overflow;
1271 SourceSize = ComputeStrLenArgument(1);
1272 DestinationSize = ComputeSizeArgument(0);
1276 case Builtin::BI__builtin___stpcpy_chk:
1277 case Builtin::BI__builtin___strcpy_chk: {
1278 DiagID = diag::warn_fortify_strlen_overflow;
1279 SourceSize = ComputeStrLenArgument(1);
1280 DestinationSize = ComputeExplicitObjectSizeArgument(2);
1281 IsChkVariant =
true;
1285 case Builtin::BIscanf:
1286 case Builtin::BIfscanf:
1287 case Builtin::BIsscanf: {
1288 unsigned FormatIndex = 1;
1289 unsigned DataIndex = 2;
1290 if (BuiltinID == Builtin::BIscanf) {
1295 const auto *FormatExpr =
1298 StringRef FormatStrRef;
1303 auto Diagnose = [&](
unsigned ArgIndex,
unsigned DestSize,
1304 unsigned SourceSize) {
1305 DiagID = diag::warn_fortify_scanf_overflow;
1306 unsigned Index = ArgIndex + DataIndex;
1307 std::string FunctionName = GetFunctionName();
1309 PDiag(DiagID) << FunctionName << (Index + 1)
1310 << DestSize << SourceSize);
1313 auto ShiftedComputeSizeArgument = [&](
unsigned Index) {
1314 return ComputeSizeArgument(Index + DataIndex);
1316 ScanfDiagnosticFormatHandler H(ShiftedComputeSizeArgument,
Diagnose);
1317 const char *FormatBytes = FormatStrRef.data();
1328 case Builtin::BIsprintf:
1329 case Builtin::BI__builtin___sprintf_chk: {
1330 size_t FormatIndex = BuiltinID == Builtin::BIsprintf ? 1 : 3;
1333 StringRef FormatStrRef;
1336 EstimateSizeFormatHandler H(FormatStrRef);
1337 const char *FormatBytes = FormatStrRef.data();
1339 H, FormatBytes, FormatBytes + StrLen,
getLangOpts(),
1340 Context.getTargetInfo(),
false)) {
1341 DiagID = H.isKernelCompatible()
1342 ? diag::warn_format_overflow
1343 : diag::warn_format_overflow_non_kprintf;
1344 SourceSize = llvm::APSInt::getUnsigned(H.getSizeLowerBound())
1345 .extOrTrunc(SizeTypeWidth);
1346 if (BuiltinID == Builtin::BI__builtin___sprintf_chk) {
1347 DestinationSize = ComputeExplicitObjectSizeArgument(2);
1348 IsChkVariant =
true;
1350 DestinationSize = ComputeSizeArgument(0);
1357 case Builtin::BI__builtin___memcpy_chk:
1358 case Builtin::BI__builtin___memmove_chk:
1359 case Builtin::BI__builtin___memset_chk:
1360 case Builtin::BI__builtin___strlcat_chk:
1361 case Builtin::BI__builtin___strlcpy_chk:
1362 case Builtin::BI__builtin___strncat_chk:
1363 case Builtin::BI__builtin___strncpy_chk:
1364 case Builtin::BI__builtin___stpncpy_chk:
1365 case Builtin::BI__builtin___memccpy_chk:
1366 case Builtin::BI__builtin___mempcpy_chk: {
1367 DiagID = diag::warn_builtin_chk_overflow;
1368 SourceSize = ComputeExplicitObjectSizeArgument(TheCall->
getNumArgs() - 2);
1370 ComputeExplicitObjectSizeArgument(TheCall->
getNumArgs() - 1);
1371 IsChkVariant =
true;
1375 case Builtin::BI__builtin___snprintf_chk:
1376 case Builtin::BI__builtin___vsnprintf_chk: {
1377 DiagID = diag::warn_builtin_chk_overflow;
1378 SourceSize = ComputeExplicitObjectSizeArgument(1);
1379 DestinationSize = ComputeExplicitObjectSizeArgument(3);
1380 IsChkVariant =
true;
1384 case Builtin::BIstrncat:
1385 case Builtin::BI__builtin_strncat:
1386 case Builtin::BIstrncpy:
1387 case Builtin::BI__builtin_strncpy:
1388 case Builtin::BIstpncpy:
1389 case Builtin::BI__builtin_stpncpy: {
1395 DiagID = diag::warn_fortify_source_size_mismatch;
1396 SourceSize = ComputeExplicitObjectSizeArgument(TheCall->
getNumArgs() - 1);
1397 DestinationSize = ComputeSizeArgument(0);
1401 case Builtin::BImemcpy:
1402 case Builtin::BI__builtin_memcpy:
1403 case Builtin::BImemmove:
1404 case Builtin::BI__builtin_memmove:
1405 case Builtin::BImemset:
1406 case Builtin::BI__builtin_memset:
1407 case Builtin::BImempcpy:
1408 case Builtin::BI__builtin_mempcpy: {
1409 DiagID = diag::warn_fortify_source_overflow;
1410 SourceSize = ComputeExplicitObjectSizeArgument(TheCall->
getNumArgs() - 1);
1411 DestinationSize = ComputeSizeArgument(0);
1414 case Builtin::BIsnprintf:
1415 case Builtin::BI__builtin_snprintf:
1416 case Builtin::BIvsnprintf:
1417 case Builtin::BI__builtin_vsnprintf: {
1418 DiagID = diag::warn_fortify_source_size_mismatch;
1419 SourceSize = ComputeExplicitObjectSizeArgument(1);
1421 StringRef FormatStrRef;
1425 EstimateSizeFormatHandler H(FormatStrRef);
1426 const char *FormatBytes = FormatStrRef.data();
1428 H, FormatBytes, FormatBytes + StrLen,
getLangOpts(),
1429 Context.getTargetInfo(),
false)) {
1430 llvm::APSInt FormatSize =
1431 llvm::APSInt::getUnsigned(H.getSizeLowerBound())
1432 .extOrTrunc(SizeTypeWidth);
1433 if (FormatSize > *SourceSize && *SourceSize != 0) {
1434 unsigned TruncationDiagID =
1435 H.isKernelCompatible() ? diag::warn_format_truncation
1436 : diag::warn_format_truncation_non_kprintf;
1437 SmallString<16> SpecifiedSizeStr;
1438 SmallString<16> FormatSizeStr;
1439 SourceSize->toString(SpecifiedSizeStr, 10);
1440 FormatSize.toString(FormatSizeStr, 10);
1442 PDiag(TruncationDiagID)
1443 << GetFunctionName() << SpecifiedSizeStr
1448 DestinationSize = ComputeSizeArgument(0);
1452 if (!SourceSize || !DestinationSize ||
1453 llvm::APSInt::compareValues(*SourceSize, *DestinationSize) <= 0)
1456 std::string FunctionName = GetFunctionName();
1458 SmallString<16> DestinationStr;
1459 SmallString<16> SourceStr;
1460 DestinationSize->toString(DestinationStr, 10);
1461 SourceSize->toString(SourceStr, 10);
1464 << FunctionName << DestinationStr << SourceStr);
1479 if (!S || !(S->
getFlags() & NeededScopeFlags)) {
1482 << DRE->getDecl()->getIdentifier();
1494 "__builtin_alloca has invalid address space");
1502enum PointerAuthOpKind {
1517 Diag(Loc, diag::err_ptrauth_disabled) << Range;
1548 if (!
Context.getTargetInfo().validatePointerAuthKey(*KeyValue)) {
1551 llvm::raw_svector_ostream Str(
Value);
1560 Result = KeyValue->getZExtValue();
1579 bool IsAddrDiscArg =
false;
1584 IsAddrDiscArg =
true;
1593 Diag(Arg->
getExprLoc(), diag::err_ptrauth_address_discrimination_invalid)
1594 <<
Result->getExtValue();
1596 Diag(Arg->
getExprLoc(), diag::err_ptrauth_extra_discriminator_invalid)
1602 IntVal =
Result->getZExtValue();
1606static std::pair<const ValueDecl *, CharUnits>
1613 const auto *BaseDecl =
1618 return {BaseDecl, Result.Val.getLValueOffset()};
1622 bool RequireConstant =
false) {
1630 auto AllowsPointer = [](PointerAuthOpKind OpKind) {
1631 return OpKind != PAO_BlendInteger;
1633 auto AllowsInteger = [](PointerAuthOpKind OpKind) {
1634 return OpKind == PAO_Discriminator || OpKind == PAO_BlendInteger ||
1635 OpKind == PAO_SignGeneric;
1644 }
else if (AllowsInteger(OpKind) &&
1651 <<
unsigned(OpKind == PAO_Discriminator ? 1
1652 : OpKind == PAO_BlendPointer ? 2
1653 : OpKind == PAO_BlendInteger ? 3
1655 <<
unsigned(AllowsInteger(OpKind) ? (AllowsPointer(OpKind) ? 2 : 1) : 0)
1665 if (!RequireConstant) {
1667 if ((OpKind == PAO_Sign || OpKind == PAO_Auth) &&
1670 ? diag::warn_ptrauth_sign_null_pointer
1671 : diag::warn_ptrauth_auth_null_pointer)
1681 if (OpKind == PAO_Sign) {
1699 S.
Diag(Arg->
getExprLoc(), diag::err_ptrauth_bad_constant_pointer);
1704 assert(OpKind == PAO_Discriminator);
1710 if (
Call->getBuiltinCallee() ==
1711 Builtin::BI__builtin_ptrauth_blend_discriminator) {
1726 assert(
Pointer->getType()->isPointerType());
1738 assert(
Integer->getType()->isIntegerType());
1744 S.
Diag(Arg->
getExprLoc(), diag::err_ptrauth_bad_constant_discriminator);
1757 Call->setType(
Call->getArgs()[0]->getType());
1788 PointerAuthOpKind OpKind,
1789 bool RequireConstant) {
1800 Call->setType(
Call->getArgs()[0]->getType());
1816 Call->setType(
Call->getArgs()[0]->getType());
1825 const Expr *Arg =
Call->getArg(0)->IgnoreParenImpCasts();
1828 const auto *Literal = dyn_cast<StringLiteral>(Arg);
1829 if (!Literal || Literal->getCharByteWidth() != 1) {
1845 Call->setArg(0, FirstValue.
get());
1851 if (!FirstArgRecord) {
1852 S.
Diag(FirstArg->
getBeginLoc(), diag::err_get_vtable_pointer_incorrect_type)
1853 << 0 << FirstArgType;
1858 diag::err_get_vtable_pointer_requires_complete_type)) {
1863 S.
Diag(FirstArg->
getBeginLoc(), diag::err_get_vtable_pointer_incorrect_type)
1864 << 1 << FirstArgRecord;
1868 Call->setType(ReturnType);
1893 auto DiagSelect = [&]() -> std::optional<unsigned> {
1900 return std::optional<unsigned>{};
1915 diag::err_incomplete_type))
1919 "Unhandled non-object pointer case");
1947 if (PT->getPointeeType()->isFunctionType()) {
1949 diag::err_builtin_is_within_lifetime_invalid_arg)
1955 if (PT->getPointeeType()->isVariableArrayType()) {
1957 << 1 <<
"__builtin_is_within_lifetime";
1962 diag::err_builtin_is_within_lifetime_invalid_arg)
1976 diag::err_builtin_trivially_relocate_invalid_arg_type)
1983 diag::err_incomplete_type))
1987 T->isIncompleteArrayType()) {
1989 diag::err_builtin_trivially_relocate_invalid_arg_type)
1990 << (
T.isConstQualified() ? 1 : 2);
1999 diag::err_builtin_trivially_relocate_invalid_arg_type)
2006 if (Size.isInvalid())
2010 if (Size.isInvalid())
2012 SizeExpr = Size.get();
2013 TheCall->
setArg(2, SizeExpr);
2023 llvm::Triple::ObjectFormatType CurObjFormat =
2025 if (llvm::is_contained(UnsupportedObjectFormatTypes, CurObjFormat)) {
2038 llvm::Triple::ArchType CurArch =
2040 if (llvm::is_contained(SupportedArchs, CurArch))
2050bool Sema::CheckTSBuiltinFunctionCall(
const TargetInfo &TI,
unsigned BuiltinID,
2057 case llvm::Triple::arm:
2058 case llvm::Triple::armeb:
2059 case llvm::Triple::thumb:
2060 case llvm::Triple::thumbeb:
2062 case llvm::Triple::aarch64:
2063 case llvm::Triple::aarch64_32:
2064 case llvm::Triple::aarch64_be:
2066 case llvm::Triple::bpfeb:
2067 case llvm::Triple::bpfel:
2069 case llvm::Triple::dxil:
2071 case llvm::Triple::hexagon:
2073 case llvm::Triple::mips:
2074 case llvm::Triple::mipsel:
2075 case llvm::Triple::mips64:
2076 case llvm::Triple::mips64el:
2078 case llvm::Triple::spirv:
2079 case llvm::Triple::spirv32:
2080 case llvm::Triple::spirv64:
2081 if (TI.
getTriple().getOS() != llvm::Triple::OSType::AMDHSA)
2084 case llvm::Triple::systemz:
2086 case llvm::Triple::x86:
2087 case llvm::Triple::x86_64:
2089 case llvm::Triple::ppc:
2090 case llvm::Triple::ppcle:
2091 case llvm::Triple::ppc64:
2092 case llvm::Triple::ppc64le:
2094 case llvm::Triple::amdgcn:
2096 case llvm::Triple::riscv32:
2097 case llvm::Triple::riscv64:
2099 case llvm::Triple::loongarch32:
2100 case llvm::Triple::loongarch64:
2103 case llvm::Triple::wasm32:
2104 case llvm::Triple::wasm64:
2106 case llvm::Triple::nvptx:
2107 case llvm::Triple::nvptx64:
2121 EltTy = VecTy->getElementType();
2123 switch (ArgTyRestr) {
2127 return S.
Diag(Loc, diag::err_builtin_invalid_arg_type)
2128 << ArgOrdinal << 2 << 1 << 1
2134 return S.
Diag(Loc, diag::err_builtin_invalid_arg_type)
2135 << ArgOrdinal << 5 << 0
2141 return S.
Diag(Loc, diag::err_builtin_invalid_arg_type)
2142 << ArgOrdinal << 5 << 1
2148 return S.
Diag(Loc, diag::err_builtin_invalid_arg_type)
2162 const TargetInfo *AuxTI,
unsigned BuiltinID) {
2163 assert((BuiltinID == Builtin::BI__builtin_cpu_supports ||
2164 BuiltinID == Builtin::BI__builtin_cpu_is) &&
2165 "Expecting __builtin_cpu_...");
2167 bool IsCPUSupports = BuiltinID == Builtin::BI__builtin_cpu_supports;
2169 auto SupportsBI = [=](
const TargetInfo *TInfo) {
2170 return TInfo && ((IsCPUSupports && TInfo->supportsCpuSupports()) ||
2171 (!IsCPUSupports && TInfo->supportsCpuIs()));
2173 if (!SupportsBI(&TI) && SupportsBI(AuxTI))
2180 ? diag::err_builtin_aix_os_unsupported
2181 : diag::err_builtin_target_unsupported)
2187 return S.
Diag(TheCall->
getBeginLoc(), diag::err_expr_not_string_literal)
2239 TheCall->
setArg(0, Arg0);
2256 TheCall->
setArg(1, Arg1);
2262 << 2 << 1 << 4 << 0 << Arg1Ty;
2271 unsigned Pos,
bool AllowConst,
2275 return S.
Diag(MaskArg->
getBeginLoc(), diag::err_builtin_invalid_arg_type)
2280 if (!PtrTy->isPointerType() || PtrTy->getPointeeType()->isVectorType())
2281 return S.
Diag(PtrArg->
getExprLoc(), diag::err_vec_masked_load_store_ptr)
2282 << Pos <<
"scalar pointer";
2291 diag::err_typecheck_convert_incompatible)
2300 bool TypeDependent =
false;
2301 for (
unsigned Arg = 0, E = TheCall->
getNumArgs(); Arg != E; ++Arg) {
2329 Builtin::BI__builtin_masked_load))
2343 return S.
Diag(PtrArg->
getExprLoc(), diag::err_vec_masked_load_store_ptr)
2366 Builtin::BI__builtin_masked_store))
2374 S.
Diag(ValArg->
getExprLoc(), diag::err_vec_masked_load_store_ptr)
2384 diag::err_vec_builtin_incompatible_vector)
2413 return S.
Diag(MaskArg->
getBeginLoc(), diag::err_builtin_invalid_arg_type)
2426 << MaskTy << IdxTy);
2435 diag::err_vec_masked_load_store_ptr)
2464 return S.
Diag(MaskArg->
getBeginLoc(), diag::err_builtin_invalid_arg_type)
2480 << MaskTy << IdxTy);
2486 << MaskTy << ValTy);
2492 diag::err_vec_builtin_incompatible_vector)
2506 if (Args.size() == 0) {
2508 diag::err_typecheck_call_too_few_args_at_least)
2514 QualType FuncT = Args[0]->getType();
2517 if (Args.size() < 2) {
2519 diag::err_typecheck_call_too_few_args_at_least)
2525 const Type *MemPtrClass = MPT->getQualifier().getAsType();
2526 QualType ObjectT = Args[1]->getType();
2528 if (MPT->isMemberDataPointer() && S.
checkArgCount(TheCall, 2))
2577 tok::periodstar, ObjectArg.
get(), Args[0]);
2581 if (MPT->isMemberDataPointer())
2584 auto *MemCall =
new (S.
Context)
2595Sema::CheckBuiltinFunctionCall(
FunctionDecl *FDecl,
unsigned BuiltinID,
2600 unsigned ICEArguments = 0;
2602 Context.GetBuiltinType(BuiltinID,
Error, &ICEArguments);
2607 for (
unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) {
2609 if ((ICEArguments & (1 << ArgNo)) == 0)
continue;
2614 if (ArgNo < TheCall->getNumArgs() &&
2617 ICEArguments &= ~(1 << ArgNo);
2621 switch (BuiltinID) {
2622 case Builtin::BI__builtin_cpu_supports:
2623 case Builtin::BI__builtin_cpu_is:
2625 Context.getAuxTargetInfo(), BuiltinID))
2628 case Builtin::BI__builtin_cpu_init:
2629 if (!
Context.getTargetInfo().supportsCpuInit()) {
2635 case Builtin::BI__builtin___CFStringMakeConstantString:
2639 *
this, BuiltinID, TheCall,
2640 {llvm::Triple::GOFF, llvm::Triple::XCOFF}))
2643 "Wrong # arguments to builtin CFStringMakeConstantString");
2644 if (
ObjC().CheckObjCString(TheCall->
getArg(0)))
2647 case Builtin::BI__builtin_ms_va_start:
2648 case Builtin::BI__builtin_stdarg_start:
2649 case Builtin::BI__builtin_va_start:
2650 case Builtin::BI__builtin_c23_va_start:
2651 if (BuiltinVAStart(BuiltinID, TheCall))
2654 case Builtin::BI__va_start: {
2655 switch (
Context.getTargetInfo().getTriple().getArch()) {
2656 case llvm::Triple::aarch64:
2657 case llvm::Triple::arm:
2658 case llvm::Triple::thumb:
2659 if (BuiltinVAStartARMMicrosoft(TheCall))
2663 if (BuiltinVAStart(BuiltinID, TheCall))
2671 case Builtin::BI_interlockedbittestandset_acq:
2672 case Builtin::BI_interlockedbittestandset_rel:
2673 case Builtin::BI_interlockedbittestandset_nf:
2674 case Builtin::BI_interlockedbittestandreset_acq:
2675 case Builtin::BI_interlockedbittestandreset_rel:
2676 case Builtin::BI_interlockedbittestandreset_nf:
2679 {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64}))
2684 case Builtin::BI_bittest64:
2685 case Builtin::BI_bittestandcomplement64:
2686 case Builtin::BI_bittestandreset64:
2687 case Builtin::BI_bittestandset64:
2688 case Builtin::BI_interlockedbittestandreset64:
2689 case Builtin::BI_interlockedbittestandset64:
2692 {llvm::Triple::x86_64, llvm::Triple::arm, llvm::Triple::thumb,
2693 llvm::Triple::aarch64, llvm::Triple::amdgcn}))
2698 case Builtin::BI_interlockedbittestandreset64_acq:
2699 case Builtin::BI_interlockedbittestandreset64_rel:
2700 case Builtin::BI_interlockedbittestandreset64_nf:
2701 case Builtin::BI_interlockedbittestandset64_acq:
2702 case Builtin::BI_interlockedbittestandset64_rel:
2703 case Builtin::BI_interlockedbittestandset64_nf:
2708 case Builtin::BI__builtin_set_flt_rounds:
2711 {llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::arm,
2712 llvm::Triple::thumb, llvm::Triple::aarch64, llvm::Triple::amdgcn,
2713 llvm::Triple::ppc, llvm::Triple::ppc64, llvm::Triple::ppcle,
2714 llvm::Triple::ppc64le}))
2718 case Builtin::BI__builtin_isgreater:
2719 case Builtin::BI__builtin_isgreaterequal:
2720 case Builtin::BI__builtin_isless:
2721 case Builtin::BI__builtin_islessequal:
2722 case Builtin::BI__builtin_islessgreater:
2723 case Builtin::BI__builtin_isunordered:
2724 if (BuiltinUnorderedCompare(TheCall, BuiltinID))
2727 case Builtin::BI__builtin_fpclassify:
2728 if (BuiltinFPClassification(TheCall, 6, BuiltinID))
2731 case Builtin::BI__builtin_isfpclass:
2732 if (BuiltinFPClassification(TheCall, 2, BuiltinID))
2735 case Builtin::BI__builtin_isfinite:
2736 case Builtin::BI__builtin_isinf:
2737 case Builtin::BI__builtin_isinf_sign:
2738 case Builtin::BI__builtin_isnan:
2739 case Builtin::BI__builtin_issignaling:
2740 case Builtin::BI__builtin_isnormal:
2741 case Builtin::BI__builtin_issubnormal:
2742 case Builtin::BI__builtin_iszero:
2743 case Builtin::BI__builtin_signbit:
2744 case Builtin::BI__builtin_signbitf:
2745 case Builtin::BI__builtin_signbitl:
2746 if (BuiltinFPClassification(TheCall, 1, BuiltinID))
2749 case Builtin::BI__builtin_shufflevector:
2753 case Builtin::BI__builtin_masked_load:
2754 case Builtin::BI__builtin_masked_expand_load:
2756 case Builtin::BI__builtin_masked_store:
2757 case Builtin::BI__builtin_masked_compress_store:
2759 case Builtin::BI__builtin_masked_gather:
2761 case Builtin::BI__builtin_masked_scatter:
2763 case Builtin::BI__builtin_invoke:
2765 case Builtin::BI__builtin_prefetch:
2766 if (BuiltinPrefetch(TheCall))
2769 case Builtin::BI__builtin_alloca_with_align:
2770 case Builtin::BI__builtin_alloca_with_align_uninitialized:
2771 if (BuiltinAllocaWithAlign(TheCall))
2774 case Builtin::BI__builtin_alloca:
2775 case Builtin::BI__builtin_alloca_uninitialized:
2782 case Builtin::BI__arithmetic_fence:
2783 if (BuiltinArithmeticFence(TheCall))
2786 case Builtin::BI__assume:
2787 case Builtin::BI__builtin_assume:
2788 if (BuiltinAssume(TheCall))
2791 case Builtin::BI__builtin_assume_aligned:
2792 if (BuiltinAssumeAligned(TheCall))
2795 case Builtin::BI__builtin_dynamic_object_size:
2796 case Builtin::BI__builtin_object_size:
2800 case Builtin::BI__builtin_longjmp:
2801 if (BuiltinLongjmp(TheCall))
2804 case Builtin::BI__builtin_setjmp:
2805 if (BuiltinSetjmp(TheCall))
2808 case Builtin::BI__builtin_classify_type:
2813 case Builtin::BI__builtin_complex:
2814 if (BuiltinComplex(TheCall))
2817 case Builtin::BI__builtin_constant_p: {
2826 case Builtin::BI__builtin_launder:
2828 case Builtin::BI__builtin_is_within_lifetime:
2830 case Builtin::BI__builtin_trivially_relocate:
2833 case Builtin::BI__sync_fetch_and_add:
2834 case Builtin::BI__sync_fetch_and_add_1:
2835 case Builtin::BI__sync_fetch_and_add_2:
2836 case Builtin::BI__sync_fetch_and_add_4:
2837 case Builtin::BI__sync_fetch_and_add_8:
2838 case Builtin::BI__sync_fetch_and_add_16:
2839 case Builtin::BI__sync_fetch_and_sub:
2840 case Builtin::BI__sync_fetch_and_sub_1:
2841 case Builtin::BI__sync_fetch_and_sub_2:
2842 case Builtin::BI__sync_fetch_and_sub_4:
2843 case Builtin::BI__sync_fetch_and_sub_8:
2844 case Builtin::BI__sync_fetch_and_sub_16:
2845 case Builtin::BI__sync_fetch_and_or:
2846 case Builtin::BI__sync_fetch_and_or_1:
2847 case Builtin::BI__sync_fetch_and_or_2:
2848 case Builtin::BI__sync_fetch_and_or_4:
2849 case Builtin::BI__sync_fetch_and_or_8:
2850 case Builtin::BI__sync_fetch_and_or_16:
2851 case Builtin::BI__sync_fetch_and_and:
2852 case Builtin::BI__sync_fetch_and_and_1:
2853 case Builtin::BI__sync_fetch_and_and_2:
2854 case Builtin::BI__sync_fetch_and_and_4:
2855 case Builtin::BI__sync_fetch_and_and_8:
2856 case Builtin::BI__sync_fetch_and_and_16:
2857 case Builtin::BI__sync_fetch_and_xor:
2858 case Builtin::BI__sync_fetch_and_xor_1:
2859 case Builtin::BI__sync_fetch_and_xor_2:
2860 case Builtin::BI__sync_fetch_and_xor_4:
2861 case Builtin::BI__sync_fetch_and_xor_8:
2862 case Builtin::BI__sync_fetch_and_xor_16:
2863 case Builtin::BI__sync_fetch_and_nand:
2864 case Builtin::BI__sync_fetch_and_nand_1:
2865 case Builtin::BI__sync_fetch_and_nand_2:
2866 case Builtin::BI__sync_fetch_and_nand_4:
2867 case Builtin::BI__sync_fetch_and_nand_8:
2868 case Builtin::BI__sync_fetch_and_nand_16:
2869 case Builtin::BI__sync_add_and_fetch:
2870 case Builtin::BI__sync_add_and_fetch_1:
2871 case Builtin::BI__sync_add_and_fetch_2:
2872 case Builtin::BI__sync_add_and_fetch_4:
2873 case Builtin::BI__sync_add_and_fetch_8:
2874 case Builtin::BI__sync_add_and_fetch_16:
2875 case Builtin::BI__sync_sub_and_fetch:
2876 case Builtin::BI__sync_sub_and_fetch_1:
2877 case Builtin::BI__sync_sub_and_fetch_2:
2878 case Builtin::BI__sync_sub_and_fetch_4:
2879 case Builtin::BI__sync_sub_and_fetch_8:
2880 case Builtin::BI__sync_sub_and_fetch_16:
2881 case Builtin::BI__sync_and_and_fetch:
2882 case Builtin::BI__sync_and_and_fetch_1:
2883 case Builtin::BI__sync_and_and_fetch_2:
2884 case Builtin::BI__sync_and_and_fetch_4:
2885 case Builtin::BI__sync_and_and_fetch_8:
2886 case Builtin::BI__sync_and_and_fetch_16:
2887 case Builtin::BI__sync_or_and_fetch:
2888 case Builtin::BI__sync_or_and_fetch_1:
2889 case Builtin::BI__sync_or_and_fetch_2:
2890 case Builtin::BI__sync_or_and_fetch_4:
2891 case Builtin::BI__sync_or_and_fetch_8:
2892 case Builtin::BI__sync_or_and_fetch_16:
2893 case Builtin::BI__sync_xor_and_fetch:
2894 case Builtin::BI__sync_xor_and_fetch_1:
2895 case Builtin::BI__sync_xor_and_fetch_2:
2896 case Builtin::BI__sync_xor_and_fetch_4:
2897 case Builtin::BI__sync_xor_and_fetch_8:
2898 case Builtin::BI__sync_xor_and_fetch_16:
2899 case Builtin::BI__sync_nand_and_fetch:
2900 case Builtin::BI__sync_nand_and_fetch_1:
2901 case Builtin::BI__sync_nand_and_fetch_2:
2902 case Builtin::BI__sync_nand_and_fetch_4:
2903 case Builtin::BI__sync_nand_and_fetch_8:
2904 case Builtin::BI__sync_nand_and_fetch_16:
2905 case Builtin::BI__sync_val_compare_and_swap:
2906 case Builtin::BI__sync_val_compare_and_swap_1:
2907 case Builtin::BI__sync_val_compare_and_swap_2:
2908 case Builtin::BI__sync_val_compare_and_swap_4:
2909 case Builtin::BI__sync_val_compare_and_swap_8:
2910 case Builtin::BI__sync_val_compare_and_swap_16:
2911 case Builtin::BI__sync_bool_compare_and_swap:
2912 case Builtin::BI__sync_bool_compare_and_swap_1:
2913 case Builtin::BI__sync_bool_compare_and_swap_2:
2914 case Builtin::BI__sync_bool_compare_and_swap_4:
2915 case Builtin::BI__sync_bool_compare_and_swap_8:
2916 case Builtin::BI__sync_bool_compare_and_swap_16:
2917 case Builtin::BI__sync_lock_test_and_set:
2918 case Builtin::BI__sync_lock_test_and_set_1:
2919 case Builtin::BI__sync_lock_test_and_set_2:
2920 case Builtin::BI__sync_lock_test_and_set_4:
2921 case Builtin::BI__sync_lock_test_and_set_8:
2922 case Builtin::BI__sync_lock_test_and_set_16:
2923 case Builtin::BI__sync_lock_release:
2924 case Builtin::BI__sync_lock_release_1:
2925 case Builtin::BI__sync_lock_release_2:
2926 case Builtin::BI__sync_lock_release_4:
2927 case Builtin::BI__sync_lock_release_8:
2928 case Builtin::BI__sync_lock_release_16:
2929 case Builtin::BI__sync_swap:
2930 case Builtin::BI__sync_swap_1:
2931 case Builtin::BI__sync_swap_2:
2932 case Builtin::BI__sync_swap_4:
2933 case Builtin::BI__sync_swap_8:
2934 case Builtin::BI__sync_swap_16:
2935 return BuiltinAtomicOverloaded(TheCallResult);
2936 case Builtin::BI__sync_synchronize:
2940 case Builtin::BI__builtin_nontemporal_load:
2941 case Builtin::BI__builtin_nontemporal_store:
2942 return BuiltinNontemporalOverloaded(TheCallResult);
2943 case Builtin::BI__builtin_memcpy_inline: {
2944 clang::Expr *SizeOp = TheCall->
getArg(2);
2956 case Builtin::BI__builtin_memset_inline: {
2957 clang::Expr *SizeOp = TheCall->
getArg(2);
2967#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
2968 case Builtin::BI##ID: \
2969 return AtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID);
2970#include "clang/Basic/Builtins.inc"
2971 case Builtin::BI__annotation:
2975 case Builtin::BI__builtin_annotation:
2979 case Builtin::BI__builtin_addressof:
2983 case Builtin::BI__builtin_function_start:
2987 case Builtin::BI__builtin_is_aligned:
2988 case Builtin::BI__builtin_align_up:
2989 case Builtin::BI__builtin_align_down:
2993 case Builtin::BI__builtin_add_overflow:
2994 case Builtin::BI__builtin_sub_overflow:
2995 case Builtin::BI__builtin_mul_overflow:
2999 case Builtin::BI__builtin_operator_new:
3000 case Builtin::BI__builtin_operator_delete: {
3001 bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete;
3003 BuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete);
3006 case Builtin::BI__builtin_dump_struct:
3008 case Builtin::BI__builtin_expect_with_probability: {
3013 const Expr *ProbArg = TheCall->
getArg(2);
3014 SmallVector<PartialDiagnosticAt, 8> Notes;
3015 Expr::EvalResult Eval;
3019 Diag(ProbArg->
getBeginLoc(), diag::err_probability_not_constant_float)
3026 bool LoseInfo =
false;
3027 Probability.convert(llvm::APFloat::IEEEdouble(),
3028 llvm::RoundingMode::Dynamic, &LoseInfo);
3029 if (!(Probability >= llvm::APFloat(0.0) &&
3030 Probability <= llvm::APFloat(1.0))) {
3037 case Builtin::BI__builtin_preserve_access_index:
3041 case Builtin::BI__builtin_call_with_static_chain:
3045 case Builtin::BI__exception_code:
3046 case Builtin::BI_exception_code:
3048 diag::err_seh___except_block))
3051 case Builtin::BI__exception_info:
3052 case Builtin::BI_exception_info:
3054 diag::err_seh___except_filter))
3057 case Builtin::BI__GetExceptionInfo:
3069 case Builtin::BIaddressof:
3070 case Builtin::BI__addressof:
3071 case Builtin::BIforward:
3072 case Builtin::BIforward_like:
3073 case Builtin::BImove:
3074 case Builtin::BImove_if_noexcept:
3075 case Builtin::BIas_const: {
3083 bool ReturnsPointer = BuiltinID == Builtin::BIaddressof ||
3084 BuiltinID == Builtin::BI__addressof;
3086 (ReturnsPointer ?
Result->isAnyPointerType()
3087 :
Result->isReferenceType()) &&
3090 Diag(TheCall->
getBeginLoc(), diag::err_builtin_move_forward_unsupported)
3096 case Builtin::BI__builtin_ptrauth_strip:
3098 case Builtin::BI__builtin_ptrauth_blend_discriminator:
3100 case Builtin::BI__builtin_ptrauth_sign_constant:
3103 case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
3106 case Builtin::BI__builtin_ptrauth_auth:
3109 case Builtin::BI__builtin_ptrauth_sign_generic_data:
3111 case Builtin::BI__builtin_ptrauth_auth_and_resign:
3113 case Builtin::BI__builtin_ptrauth_string_discriminator:
3116 case Builtin::BI__builtin_get_vtable_pointer:
3120 case Builtin::BIread_pipe:
3121 case Builtin::BIwrite_pipe:
3124 if (
OpenCL().checkBuiltinRWPipe(TheCall))
3127 case Builtin::BIreserve_read_pipe:
3128 case Builtin::BIreserve_write_pipe:
3129 case Builtin::BIwork_group_reserve_read_pipe:
3130 case Builtin::BIwork_group_reserve_write_pipe:
3131 if (
OpenCL().checkBuiltinReserveRWPipe(TheCall))
3134 case Builtin::BIsub_group_reserve_read_pipe:
3135 case Builtin::BIsub_group_reserve_write_pipe:
3136 if (
OpenCL().checkSubgroupExt(TheCall) ||
3137 OpenCL().checkBuiltinReserveRWPipe(TheCall))
3140 case Builtin::BIcommit_read_pipe:
3141 case Builtin::BIcommit_write_pipe:
3142 case Builtin::BIwork_group_commit_read_pipe:
3143 case Builtin::BIwork_group_commit_write_pipe:
3144 if (
OpenCL().checkBuiltinCommitRWPipe(TheCall))
3147 case Builtin::BIsub_group_commit_read_pipe:
3148 case Builtin::BIsub_group_commit_write_pipe:
3149 if (
OpenCL().checkSubgroupExt(TheCall) ||
3150 OpenCL().checkBuiltinCommitRWPipe(TheCall))
3153 case Builtin::BIget_pipe_num_packets:
3154 case Builtin::BIget_pipe_max_packets:
3155 if (
OpenCL().checkBuiltinPipePackets(TheCall))
3158 case Builtin::BIto_global:
3159 case Builtin::BIto_local:
3160 case Builtin::BIto_private:
3161 if (
OpenCL().checkBuiltinToAddr(BuiltinID, TheCall))
3165 case Builtin::BIenqueue_kernel:
3166 if (
OpenCL().checkBuiltinEnqueueKernel(TheCall))
3169 case Builtin::BIget_kernel_work_group_size:
3170 case Builtin::BIget_kernel_preferred_work_group_size_multiple:
3171 if (
OpenCL().checkBuiltinKernelWorkGroupSize(TheCall))
3174 case Builtin::BIget_kernel_max_sub_group_size_for_ndrange:
3175 case Builtin::BIget_kernel_sub_group_count_for_ndrange:
3176 if (
OpenCL().checkBuiltinNDRangeAndBlock(TheCall))
3179 case Builtin::BI__builtin_os_log_format:
3180 Cleanup.setExprNeedsCleanups(
true);
3182 case Builtin::BI__builtin_os_log_format_buffer_size:
3183 if (BuiltinOSLogFormat(TheCall))
3186 case Builtin::BI__builtin_frame_address:
3187 case Builtin::BI__builtin_return_address: {
3196 Result.Val.getInt() != 0)
3198 << ((BuiltinID == Builtin::BI__builtin_return_address)
3199 ?
"__builtin_return_address"
3200 :
"__builtin_frame_address")
3205 case Builtin::BI__builtin_nondeterministic_value: {
3206 if (BuiltinNonDeterministicValue(TheCall))
3213 case Builtin::BI__builtin_elementwise_abs:
3221 case Builtin::BI__builtin_elementwise_acos:
3222 case Builtin::BI__builtin_elementwise_asin:
3223 case Builtin::BI__builtin_elementwise_atan:
3224 case Builtin::BI__builtin_elementwise_ceil:
3225 case Builtin::BI__builtin_elementwise_cos:
3226 case Builtin::BI__builtin_elementwise_cosh:
3227 case Builtin::BI__builtin_elementwise_exp:
3228 case Builtin::BI__builtin_elementwise_exp2:
3229 case Builtin::BI__builtin_elementwise_exp10:
3230 case Builtin::BI__builtin_elementwise_floor:
3231 case Builtin::BI__builtin_elementwise_log:
3232 case Builtin::BI__builtin_elementwise_log2:
3233 case Builtin::BI__builtin_elementwise_log10:
3234 case Builtin::BI__builtin_elementwise_roundeven:
3235 case Builtin::BI__builtin_elementwise_round:
3236 case Builtin::BI__builtin_elementwise_rint:
3237 case Builtin::BI__builtin_elementwise_nearbyint:
3238 case Builtin::BI__builtin_elementwise_sin:
3239 case Builtin::BI__builtin_elementwise_sinh:
3240 case Builtin::BI__builtin_elementwise_sqrt:
3241 case Builtin::BI__builtin_elementwise_tan:
3242 case Builtin::BI__builtin_elementwise_tanh:
3243 case Builtin::BI__builtin_elementwise_trunc:
3244 case Builtin::BI__builtin_elementwise_canonicalize:
3249 case Builtin::BI__builtin_elementwise_fma:
3256 case Builtin::BI__builtin_elementwise_minnum:
3257 case Builtin::BI__builtin_elementwise_maxnum:
3258 case Builtin::BI__builtin_elementwise_minimum:
3259 case Builtin::BI__builtin_elementwise_maximum:
3260 case Builtin::BI__builtin_elementwise_minimumnum:
3261 case Builtin::BI__builtin_elementwise_maximumnum:
3262 case Builtin::BI__builtin_elementwise_atan2:
3263 case Builtin::BI__builtin_elementwise_fmod:
3264 case Builtin::BI__builtin_elementwise_pow:
3265 if (BuiltinElementwiseMath(TheCall,
3271 case Builtin::BI__builtin_elementwise_add_sat:
3272 case Builtin::BI__builtin_elementwise_sub_sat:
3273 if (BuiltinElementwiseMath(TheCall,
3277 case Builtin::BI__builtin_elementwise_fshl:
3278 case Builtin::BI__builtin_elementwise_fshr:
3283 case Builtin::BI__builtin_elementwise_min:
3284 case Builtin::BI__builtin_elementwise_max:
3285 if (BuiltinElementwiseMath(TheCall))
3288 case Builtin::BI__builtin_elementwise_popcount:
3289 case Builtin::BI__builtin_elementwise_bitreverse:
3294 case Builtin::BI__builtin_elementwise_copysign: {
3303 QualType MagnitudeTy = Magnitude.
get()->
getType();
3316 diag::err_typecheck_call_different_arg_types)
3317 << MagnitudeTy << SignTy;
3325 case Builtin::BI__builtin_elementwise_clzg:
3326 case Builtin::BI__builtin_elementwise_ctzg:
3334 }
else if (BuiltinElementwiseMath(
3338 case Builtin::BI__builtin_reduce_max:
3339 case Builtin::BI__builtin_reduce_min: {
3340 if (PrepareBuiltinReduceMathOneArgCall(TheCall))
3343 const Expr *Arg = TheCall->
getArg(0);
3348 ElTy = TyA->getElementType();
3352 if (ElTy.isNull()) {
3362 case Builtin::BI__builtin_reduce_maximum:
3363 case Builtin::BI__builtin_reduce_minimum: {
3364 if (PrepareBuiltinReduceMathOneArgCall(TheCall))
3367 const Expr *Arg = TheCall->
getArg(0);
3372 ElTy = TyA->getElementType();
3376 if (ElTy.isNull() || !ElTy->isFloatingType()) {
3389 case Builtin::BI__builtin_reduce_add:
3390 case Builtin::BI__builtin_reduce_mul:
3391 case Builtin::BI__builtin_reduce_xor:
3392 case Builtin::BI__builtin_reduce_or:
3393 case Builtin::BI__builtin_reduce_and: {
3394 if (PrepareBuiltinReduceMathOneArgCall(TheCall))
3397 const Expr *Arg = TheCall->
getArg(0);
3402 ElTy = TyA->getElementType();
3406 if (ElTy.isNull() || !ElTy->isIntegerType()) {
3417 case Builtin::BI__builtin_matrix_transpose:
3418 return BuiltinMatrixTranspose(TheCall, TheCallResult);
3420 case Builtin::BI__builtin_matrix_column_major_load:
3421 return BuiltinMatrixColumnMajorLoad(TheCall, TheCallResult);
3423 case Builtin::BI__builtin_matrix_column_major_store:
3424 return BuiltinMatrixColumnMajorStore(TheCall, TheCallResult);
3426 case Builtin::BI__builtin_verbose_trap:
3431 case Builtin::BI__builtin_get_device_side_mangled_name: {
3432 auto Check = [](CallExpr *TheCall) {
3438 auto *D = DRE->getDecl();
3441 return D->hasAttr<CUDAGlobalAttr>() || D->hasAttr<CUDADeviceAttr>() ||
3442 D->hasAttr<CUDAConstantAttr>() || D->hasAttr<HIPManagedAttr>();
3444 if (!Check(TheCall)) {
3446 diag::err_hip_invalid_args_builtin_mangled_name);
3451 case Builtin::BI__builtin_popcountg:
3455 case Builtin::BI__builtin_clzg:
3456 case Builtin::BI__builtin_ctzg:
3461 case Builtin::BI__builtin_allow_runtime_check: {
3462 Expr *Arg = TheCall->
getArg(0);
3471 case Builtin::BI__builtin_counted_by_ref:
3472 if (BuiltinCountedByRef(TheCall))
3482 if (
Context.BuiltinInfo.isTSBuiltin(BuiltinID)) {
3483 if (
Context.BuiltinInfo.isAuxBuiltinID(BuiltinID)) {
3484 assert(
Context.getAuxTargetInfo() &&
3485 "Aux Target Builtin, but not an aux target?");
3487 if (CheckTSBuiltinFunctionCall(
3489 Context.BuiltinInfo.getAuxBuiltinID(BuiltinID), TheCall))
3492 if (CheckTSBuiltinFunctionCall(
Context.getTargetInfo(), BuiltinID,
3498 return TheCallResult;
3513 if (
Result.isShiftedMask() || (~
Result).isShiftedMask())
3517 diag::err_argument_not_contiguous_bit_field)
3523 bool IsCXXMember =
false;
3524 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D))
3525 IsCXXMember = MD->isInstance();
3526 bool IsVariadic =
false;
3529 else if (
const auto *BD = dyn_cast<BlockDecl>(D))
3530 IsVariadic = BD->isVariadic();
3531 else if (
const auto *OMD = dyn_cast<ObjCMethodDecl>(D))
3532 IsVariadic = OMD->isVariadic();
3538 bool IsCXXMember,
bool IsVariadic,
3542 else if (IsVariadic)
3583 UT && UT->getOriginalDecl()
3584 ->getMostRecentDecl()
3585 ->hasAttr<TransparentUnionAttr>()) {
3586 if (
const auto *CLE = dyn_cast<CompoundLiteralExpr>(
Expr))
3587 if (
const auto *ILE = dyn_cast<InitListExpr>(CLE->getInitializer()))
3588 Expr = ILE->getInit(0);
3598 const Expr *ArgExpr,
3602 S.
PDiag(diag::warn_null_arg)
3608 if (
auto nullability =
type->getNullability())
3619 assert((FDecl || Proto) &&
"Need a function declaration or prototype");
3625 llvm::SmallBitVector NonNullArgs;
3631 for (
const auto *Arg : Args)
3638 unsigned IdxAST = Idx.getASTIndex();
3639 if (IdxAST >= Args.size())
3641 if (NonNullArgs.empty())
3642 NonNullArgs.resize(Args.size());
3643 NonNullArgs.set(IdxAST);
3652 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl))
3657 unsigned ParamIndex = 0;
3659 I != E; ++I, ++ParamIndex) {
3662 if (NonNullArgs.empty())
3663 NonNullArgs.resize(Args.size());
3665 NonNullArgs.set(ParamIndex);
3672 if (
const ValueDecl *VD = dyn_cast<ValueDecl>(FDecl)) {
3677 type = blockType->getPointeeType();
3691 if (NonNullArgs.empty())
3692 NonNullArgs.resize(Args.size());
3694 NonNullArgs.set(Index);
3703 for (
unsigned ArgIndex = 0, ArgIndexEnd = NonNullArgs.size();
3704 ArgIndex != ArgIndexEnd; ++ArgIndex) {
3705 if (NonNullArgs[ArgIndex])
3711 StringRef ParamName,
QualType ArgTy,
3734 CharUnits ParamAlign =
Context.getTypeAlignInChars(ParamTy);
3735 CharUnits ArgAlign =
Context.getTypeAlignInChars(ArgTy);
3739 if (ArgAlign < ParamAlign)
3740 Diag(Loc, diag::warn_param_mismatched_alignment)
3742 << ParamName << (FDecl !=
nullptr) << FDecl;
3746 const Expr *ThisArg,
3748 if (!FD || Args.empty())
3750 auto GetArgAt = [&](
int Idx) ->
const Expr * {
3751 if (Idx == LifetimeCaptureByAttr::Global ||
3752 Idx == LifetimeCaptureByAttr::Unknown)
3754 if (IsMemberFunction && Idx == 0)
3756 return Args[Idx - IsMemberFunction];
3758 auto HandleCaptureByAttr = [&](
const LifetimeCaptureByAttr *
Attr,
3763 Expr *Captured =
const_cast<Expr *
>(GetArgAt(ArgIdx));
3764 for (
int CapturingParamIdx :
Attr->params()) {
3767 if (CapturingParamIdx == LifetimeCaptureByAttr::This &&
3770 Expr *Capturing =
const_cast<Expr *
>(GetArgAt(CapturingParamIdx));
3778 I + IsMemberFunction);
3780 if (IsMemberFunction) {
3788 HandleCaptureByAttr(ATL.
getAttrAs<LifetimeCaptureByAttr>(), 0);
3801 llvm::SmallBitVector CheckedVarArgs;
3803 for (
const auto *I : FDecl->
specific_attrs<FormatMatchesAttr>()) {
3805 CheckedVarArgs.resize(Args.size());
3806 CheckFormatString(I, Args, IsMemberFunction, CallType, Loc, Range,
3811 CheckedVarArgs.resize(Args.size());
3812 CheckFormatArguments(I, Args, IsMemberFunction, CallType, Loc, Range,
3819 auto *FD = dyn_cast_or_null<FunctionDecl>(FDecl);
3823 : isa_and_nonnull<FunctionDecl>(FDecl)
3825 : isa_and_nonnull<ObjCMethodDecl>(FDecl)
3829 for (
unsigned ArgIdx = NumParams; ArgIdx < Args.size(); ++ArgIdx) {
3831 if (
const Expr *Arg = Args[ArgIdx]) {
3832 if (CheckedVarArgs.empty() || !CheckedVarArgs[ArgIdx])
3839 if (FDecl || Proto) {
3844 for (
const auto *I : FDecl->
specific_attrs<ArgumentWithTypeTagAttr>())
3845 CheckArgumentWithTypeTag(I, Args, Loc);
3851 if (!Proto && FDecl) {
3853 if (isa_and_nonnull<FunctionProtoType>(FT))
3859 const auto N = std::min<unsigned>(Proto->
getNumParams(), Args.size());
3861 bool IsScalableArg =
false;
3862 for (
unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
3864 if (
const Expr *Arg = Args[ArgIdx]) {
3868 if (
Context.getTargetInfo().getTriple().isOSAIX() && FDecl && Arg &&
3876 IsScalableArg =
true;
3878 CheckArgAlignment(Arg->
getExprLoc(), FDecl, std::to_string(ArgIdx + 1),
3887 if (
auto *CallerFD = dyn_cast<FunctionDecl>(
CurContext)) {
3888 llvm::StringMap<bool> CallerFeatureMap;
3889 Context.getFunctionFeatureMap(CallerFeatureMap, CallerFD);
3890 if (!CallerFeatureMap.contains(
"sme"))
3891 Diag(Loc, diag::err_sme_call_in_non_sme_target);
3892 }
else if (!
Context.getTargetInfo().hasFeature(
"sme")) {
3893 Diag(Loc, diag::err_sme_call_in_non_sme_target);
3902 const auto *CallerFD = dyn_cast<FunctionDecl>(
CurContext);
3904 (IsScalableArg || IsScalableRet)) {
3905 bool IsCalleeStreaming =
3907 bool IsCalleeStreamingCompatible =
3911 if (!IsCalleeStreamingCompatible &&
3915 unsigned VL = LO.VScaleMin * 128;
3916 unsigned SVL = LO.VScaleStreamingMin * 128;
3917 bool IsVLMismatch = VL && SVL && VL != SVL;
3919 auto EmitDiag = [&](
bool IsArg) {
3923 Diag(Loc, diag::warn_sme_streaming_compatible_vl_mismatch)
3924 << IsArg << IsCalleeStreaming << SVL << VL;
3927 Diag(Loc, diag::err_sme_streaming_transition_vl_mismatch)
3928 << IsArg << SVL << VL;
3930 Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
3947 bool CallerHasZAState =
false;
3948 bool CallerHasZT0State =
false;
3950 auto *
Attr = CallerFD->getAttr<ArmNewAttr>();
3952 CallerHasZAState =
true;
3954 CallerHasZT0State =
true;
3958 FPT->getExtProtoInfo().AArch64SMEAttributes) !=
3960 CallerHasZT0State |=
3962 FPT->getExtProtoInfo().AArch64SMEAttributes) !=
3968 Diag(Loc, diag::err_sme_za_call_no_za_state);
3971 Diag(Loc, diag::err_sme_zt0_call_no_zt0_state);
3975 Diag(Loc, diag::err_sme_unimplemented_za_save_restore);
3976 Diag(Loc, diag::note_sme_use_preserves_za);
3981 if (FDecl && FDecl->
hasAttr<AllocAlignAttr>()) {
3982 auto *AA = FDecl->
getAttr<AllocAlignAttr>();
3983 const Expr *Arg = Args[AA->getParamIndex().getASTIndex()];
3984 if (!Arg->isValueDependent()) {
3986 if (Arg->EvaluateAsInt(Align,
Context)) {
3987 const llvm::APSInt &I = Align.
Val.
getInt();
3988 if (!I.isPowerOf2())
3989 Diag(Arg->getExprLoc(), diag::warn_alignment_not_power_of_two)
3990 << Arg->getSourceRange();
3993 Diag(Arg->getExprLoc(), diag::warn_assume_aligned_too_great)
4019 Loc, FDecl,
"'this'", Context.getPointerType(ThisType),
4020 Context.getPointerType(Ctor->getFunctionObjectParameterType()));
4022 checkCall(FDecl, Proto,
nullptr, Args,
true,
4031 IsMemberOperatorCall;
4037 Expr *ImplicitThis =
nullptr;
4042 ImplicitThis = Args[0];
4045 }
else if (IsMemberFunction && !FDecl->
isStatic() &&
4056 ThisType =
Context.getPointerType(ThisType);
4062 CheckArgAlignment(TheCall->
getRParenLoc(), FDecl,
"'this'", ThisType,
4080 CheckAbsoluteValueFunction(TheCall, FDecl);
4081 CheckMaxUnsignedZero(TheCall, FDecl);
4082 CheckInfNaNFunction(TheCall, FDecl);
4093 case Builtin::BIstrlcpy:
4094 case Builtin::BIstrlcat:
4095 CheckStrlcpycatArguments(TheCall, FnInfo);
4097 case Builtin::BIstrncat:
4098 CheckStrncatArguments(TheCall, FnInfo);
4100 case Builtin::BIfree:
4101 CheckFreeArguments(TheCall);
4104 CheckMemaccessArguments(TheCall, CMId, FnInfo);
4113 if (
const auto *
V = dyn_cast<VarDecl>(NDecl))
4114 Ty =
V->getType().getNonReferenceType();
4115 else if (
const auto *F = dyn_cast<FieldDecl>(NDecl))
4116 Ty = F->getType().getNonReferenceType();
4153 if (!llvm::isValidAtomicOrderingCABI(Ordering))
4156 auto OrderingCABI = (llvm::AtomicOrderingCABI)Ordering;
4158 case AtomicExpr::AO__c11_atomic_init:
4159 case AtomicExpr::AO__opencl_atomic_init:
4160 llvm_unreachable(
"There is no ordering argument for an init");
4162 case AtomicExpr::AO__c11_atomic_load:
4163 case AtomicExpr::AO__opencl_atomic_load:
4164 case AtomicExpr::AO__hip_atomic_load:
4165 case AtomicExpr::AO__atomic_load_n:
4166 case AtomicExpr::AO__atomic_load:
4167 case AtomicExpr::AO__scoped_atomic_load_n:
4168 case AtomicExpr::AO__scoped_atomic_load:
4169 return OrderingCABI != llvm::AtomicOrderingCABI::release &&
4170 OrderingCABI != llvm::AtomicOrderingCABI::acq_rel;
4172 case AtomicExpr::AO__c11_atomic_store:
4173 case AtomicExpr::AO__opencl_atomic_store:
4174 case AtomicExpr::AO__hip_atomic_store:
4175 case AtomicExpr::AO__atomic_store:
4176 case AtomicExpr::AO__atomic_store_n:
4177 case AtomicExpr::AO__scoped_atomic_store:
4178 case AtomicExpr::AO__scoped_atomic_store_n:
4179 case AtomicExpr::AO__atomic_clear:
4180 return OrderingCABI != llvm::AtomicOrderingCABI::consume &&
4181 OrderingCABI != llvm::AtomicOrderingCABI::acquire &&
4182 OrderingCABI != llvm::AtomicOrderingCABI::acq_rel;
4241 const unsigned NumForm = ClearByte + 1;
4242 const unsigned NumArgs[] = {2, 2, 3, 3, 3, 3, 4, 5, 6, 2, 2};
4243 const unsigned NumVals[] = {1, 0, 1, 1, 1, 1, 2, 2, 3, 0, 0};
4251 static_assert(
sizeof(NumArgs)/
sizeof(NumArgs[0]) == NumForm
4252 &&
sizeof(NumVals)/
sizeof(NumVals[0]) == NumForm,
4253 "need to update code for modified forms");
4254 static_assert(AtomicExpr::AO__atomic_add_fetch == 0 &&
4255 AtomicExpr::AO__atomic_xor_fetch + 1 ==
4256 AtomicExpr::AO__c11_atomic_compare_exchange_strong,
4257 "need to update code for modified C11 atomics");
4258 bool IsOpenCL = Op >= AtomicExpr::AO__opencl_atomic_compare_exchange_strong &&
4259 Op <= AtomicExpr::AO__opencl_atomic_store;
4260 bool IsHIP = Op >= AtomicExpr::AO__hip_atomic_compare_exchange_strong &&
4261 Op <= AtomicExpr::AO__hip_atomic_store;
4262 bool IsScoped = Op >= AtomicExpr::AO__scoped_atomic_add_fetch &&
4263 Op <= AtomicExpr::AO__scoped_atomic_xor_fetch;
4264 bool IsC11 = (Op >= AtomicExpr::AO__c11_atomic_compare_exchange_strong &&
4265 Op <= AtomicExpr::AO__c11_atomic_store) ||
4267 bool IsN = Op == AtomicExpr::AO__atomic_load_n ||
4268 Op == AtomicExpr::AO__atomic_store_n ||
4269 Op == AtomicExpr::AO__atomic_exchange_n ||
4270 Op == AtomicExpr::AO__atomic_compare_exchange_n ||
4271 Op == AtomicExpr::AO__scoped_atomic_load_n ||
4272 Op == AtomicExpr::AO__scoped_atomic_store_n ||
4273 Op == AtomicExpr::AO__scoped_atomic_exchange_n ||
4274 Op == AtomicExpr::AO__scoped_atomic_compare_exchange_n;
4278 enum ArithOpExtraValueType {
4283 unsigned ArithAllows = AOEVT_None;
4286 case AtomicExpr::AO__c11_atomic_init:
4287 case AtomicExpr::AO__opencl_atomic_init:
4291 case AtomicExpr::AO__c11_atomic_load:
4292 case AtomicExpr::AO__opencl_atomic_load:
4293 case AtomicExpr::AO__hip_atomic_load:
4294 case AtomicExpr::AO__atomic_load_n:
4295 case AtomicExpr::AO__scoped_atomic_load_n:
4299 case AtomicExpr::AO__atomic_load:
4300 case AtomicExpr::AO__scoped_atomic_load:
4304 case AtomicExpr::AO__c11_atomic_store:
4305 case AtomicExpr::AO__opencl_atomic_store:
4306 case AtomicExpr::AO__hip_atomic_store:
4307 case AtomicExpr::AO__atomic_store:
4308 case AtomicExpr::AO__atomic_store_n:
4309 case AtomicExpr::AO__scoped_atomic_store:
4310 case AtomicExpr::AO__scoped_atomic_store_n:
4313 case AtomicExpr::AO__atomic_fetch_add:
4314 case AtomicExpr::AO__atomic_fetch_sub:
4315 case AtomicExpr::AO__atomic_add_fetch:
4316 case AtomicExpr::AO__atomic_sub_fetch:
4317 case AtomicExpr::AO__scoped_atomic_fetch_add:
4318 case AtomicExpr::AO__scoped_atomic_fetch_sub:
4319 case AtomicExpr::AO__scoped_atomic_add_fetch:
4320 case AtomicExpr::AO__scoped_atomic_sub_fetch:
4321 case AtomicExpr::AO__c11_atomic_fetch_add:
4322 case AtomicExpr::AO__c11_atomic_fetch_sub:
4323 case AtomicExpr::AO__opencl_atomic_fetch_add:
4324 case AtomicExpr::AO__opencl_atomic_fetch_sub:
4325 case AtomicExpr::AO__hip_atomic_fetch_add:
4326 case AtomicExpr::AO__hip_atomic_fetch_sub:
4327 ArithAllows = AOEVT_Pointer | AOEVT_FP;
4330 case AtomicExpr::AO__atomic_fetch_max:
4331 case AtomicExpr::AO__atomic_fetch_min:
4332 case AtomicExpr::AO__atomic_max_fetch:
4333 case AtomicExpr::AO__atomic_min_fetch:
4334 case AtomicExpr::AO__scoped_atomic_fetch_max:
4335 case AtomicExpr::AO__scoped_atomic_fetch_min:
4336 case AtomicExpr::AO__scoped_atomic_max_fetch:
4337 case AtomicExpr::AO__scoped_atomic_min_fetch:
4338 case AtomicExpr::AO__c11_atomic_fetch_max:
4339 case AtomicExpr::AO__c11_atomic_fetch_min:
4340 case AtomicExpr::AO__opencl_atomic_fetch_max:
4341 case AtomicExpr::AO__opencl_atomic_fetch_min:
4342 case AtomicExpr::AO__hip_atomic_fetch_max:
4343 case AtomicExpr::AO__hip_atomic_fetch_min:
4344 ArithAllows = AOEVT_FP;
4347 case AtomicExpr::AO__c11_atomic_fetch_and:
4348 case AtomicExpr::AO__c11_atomic_fetch_or:
4349 case AtomicExpr::AO__c11_atomic_fetch_xor:
4350 case AtomicExpr::AO__hip_atomic_fetch_and:
4351 case AtomicExpr::AO__hip_atomic_fetch_or:
4352 case AtomicExpr::AO__hip_atomic_fetch_xor:
4353 case AtomicExpr::AO__c11_atomic_fetch_nand:
4354 case AtomicExpr::AO__opencl_atomic_fetch_and:
4355 case AtomicExpr::AO__opencl_atomic_fetch_or:
4356 case AtomicExpr::AO__opencl_atomic_fetch_xor:
4357 case AtomicExpr::AO__atomic_fetch_and:
4358 case AtomicExpr::AO__atomic_fetch_or:
4359 case AtomicExpr::AO__atomic_fetch_xor:
4360 case AtomicExpr::AO__atomic_fetch_nand:
4361 case AtomicExpr::AO__atomic_and_fetch:
4362 case AtomicExpr::AO__atomic_or_fetch:
4363 case AtomicExpr::AO__atomic_xor_fetch:
4364 case AtomicExpr::AO__atomic_nand_fetch:
4365 case AtomicExpr::AO__scoped_atomic_fetch_and:
4366 case AtomicExpr::AO__scoped_atomic_fetch_or:
4367 case AtomicExpr::AO__scoped_atomic_fetch_xor:
4368 case AtomicExpr::AO__scoped_atomic_fetch_nand:
4369 case AtomicExpr::AO__scoped_atomic_and_fetch:
4370 case AtomicExpr::AO__scoped_atomic_or_fetch:
4371 case AtomicExpr::AO__scoped_atomic_xor_fetch:
4372 case AtomicExpr::AO__scoped_atomic_nand_fetch:
4376 case AtomicExpr::AO__c11_atomic_exchange:
4377 case AtomicExpr::AO__hip_atomic_exchange:
4378 case AtomicExpr::AO__opencl_atomic_exchange:
4379 case AtomicExpr::AO__atomic_exchange_n:
4380 case AtomicExpr::AO__scoped_atomic_exchange_n:
4384 case AtomicExpr::AO__atomic_exchange:
4385 case AtomicExpr::AO__scoped_atomic_exchange:
4389 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
4390 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
4391 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
4392 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
4393 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
4394 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
4398 case AtomicExpr::AO__atomic_compare_exchange:
4399 case AtomicExpr::AO__atomic_compare_exchange_n:
4400 case AtomicExpr::AO__scoped_atomic_compare_exchange:
4401 case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
4405 case AtomicExpr::AO__atomic_test_and_set:
4406 Form = TestAndSetByte;
4409 case AtomicExpr::AO__atomic_clear:
4414 unsigned AdjustedNumArgs = NumArgs[Form];
4415 if ((IsOpenCL || IsHIP || IsScoped) &&
4416 Op != AtomicExpr::AO__opencl_atomic_init)
4419 if (Args.size() < AdjustedNumArgs) {
4420 Diag(CallRange.
getEnd(), diag::err_typecheck_call_too_few_args)
4421 << 0 << AdjustedNumArgs << static_cast<unsigned>(Args.size())
4424 }
else if (Args.size() > AdjustedNumArgs) {
4425 Diag(Args[AdjustedNumArgs]->getBeginLoc(),
4426 diag::err_typecheck_call_too_many_args)
4427 << 0 << AdjustedNumArgs << static_cast<unsigned>(Args.size())
4433 Expr *Ptr = Args[0];
4438 Ptr = ConvertedPtr.
get();
4441 Diag(ExprRange.
getBegin(), diag::err_atomic_builtin_must_be_pointer)
4451 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_atomic)
4457 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_non_const_atomic)
4463 }
else if (Form != Load && Form != LoadCopy) {
4465 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_non_const_pointer)
4471 if (Form != TestAndSetByte && Form != ClearByte) {
4474 diag::err_incomplete_type))
4477 if (
Context.getTypeInfoInChars(AtomTy).Width.isZero()) {
4478 Diag(ExprRange.
getBegin(), diag::err_atomic_builtin_must_be_pointer)
4488 pointerType->getPointeeType().getCVRQualifiers());
4498 diag::err_atomic_op_needs_non_address_discriminated_pointer)
4507 auto IsAllowedValueType = [&](
QualType ValType,
4508 unsigned AllowedType) ->
bool {
4512 return AllowedType & AOEVT_Pointer;
4517 &
Context.getTargetInfo().getLongDoubleFormat() ==
4518 &llvm::APFloat::x87DoubleExtended())
4522 if (!IsAllowedValueType(ValType, ArithAllows)) {
4523 auto DID = ArithAllows & AOEVT_FP
4524 ? (ArithAllows & AOEVT_Pointer
4525 ? diag::err_atomic_op_needs_atomic_int_ptr_or_fp
4526 : diag::err_atomic_op_needs_atomic_int_or_fp)
4527 : diag::err_atomic_op_needs_atomic_int;
4534 diag::err_incomplete_type)) {
4540 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_atomic_int_or_ptr)
4551 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_trivial_copy)
4567 Diag(ExprRange.
getBegin(), diag::err_arc_atomic_ownership)
4579 if (Form ==
Copy || Form == LoadCopy || Form == GNUXchg || Form ==
Init ||
4582 else if (Form == C11CmpXchg || Form == GNUCmpXchg || Form == TestAndSetByte)
4588 bool IsPassedByAddress =
false;
4589 if (!IsC11 && !IsHIP && !IsN) {
4591 IsPassedByAddress =
true;
4596 APIOrderedArgs.push_back(Args[0]);
4600 APIOrderedArgs.push_back(Args[1]);
4606 APIOrderedArgs.push_back(Args[2]);
4607 APIOrderedArgs.push_back(Args[1]);
4610 APIOrderedArgs.push_back(Args[2]);
4611 APIOrderedArgs.push_back(Args[3]);
4612 APIOrderedArgs.push_back(Args[1]);
4615 APIOrderedArgs.push_back(Args[2]);
4616 APIOrderedArgs.push_back(Args[4]);
4617 APIOrderedArgs.push_back(Args[1]);
4618 APIOrderedArgs.push_back(Args[3]);
4621 APIOrderedArgs.push_back(Args[2]);
4622 APIOrderedArgs.push_back(Args[4]);
4623 APIOrderedArgs.push_back(Args[5]);
4624 APIOrderedArgs.push_back(Args[1]);
4625 APIOrderedArgs.push_back(Args[3]);
4627 case TestAndSetByte:
4629 APIOrderedArgs.push_back(Args[1]);
4633 APIOrderedArgs.append(Args.begin(), Args.end());
4640 for (
unsigned i = 0; i != APIOrderedArgs.size(); ++i) {
4642 if (i < NumVals[Form] + 1) {
4655 assert(Form != Load);
4657 Ty =
Context.getPointerDiffType();
4660 else if (Form ==
Copy || Form == Xchg) {
4661 if (IsPassedByAddress) {
4668 Expr *ValArg = APIOrderedArgs[i];
4675 AS = PtrTy->getPointeeType().getAddressSpace();
4684 if (IsPassedByAddress)
4704 APIOrderedArgs[i] = Arg.
get();
4709 SubExprs.push_back(Ptr);
4713 SubExprs.push_back(APIOrderedArgs[1]);
4716 case TestAndSetByte:
4718 SubExprs.push_back(APIOrderedArgs[1]);
4724 SubExprs.push_back(APIOrderedArgs[2]);
4725 SubExprs.push_back(APIOrderedArgs[1]);
4729 SubExprs.push_back(APIOrderedArgs[3]);
4730 SubExprs.push_back(APIOrderedArgs[1]);
4731 SubExprs.push_back(APIOrderedArgs[2]);
4734 SubExprs.push_back(APIOrderedArgs[3]);
4735 SubExprs.push_back(APIOrderedArgs[1]);
4736 SubExprs.push_back(APIOrderedArgs[4]);
4737 SubExprs.push_back(APIOrderedArgs[2]);
4740 SubExprs.push_back(APIOrderedArgs[4]);
4741 SubExprs.push_back(APIOrderedArgs[1]);
4742 SubExprs.push_back(APIOrderedArgs[5]);
4743 SubExprs.push_back(APIOrderedArgs[2]);
4744 SubExprs.push_back(APIOrderedArgs[3]);
4749 if (SubExprs.size() >= 2 && Form !=
Init) {
4750 std::optional<llvm::APSInt>
Success =
4751 SubExprs[1]->getIntegerConstantExpr(
Context);
4753 Diag(SubExprs[1]->getBeginLoc(),
4754 diag::warn_atomic_op_has_invalid_memory_order)
4755 << (Form == C11CmpXchg || Form == GNUCmpXchg)
4756 << SubExprs[1]->getSourceRange();
4758 if (SubExprs.size() >= 5) {
4759 if (std::optional<llvm::APSInt> Failure =
4760 SubExprs[3]->getIntegerConstantExpr(
Context)) {
4761 if (!llvm::is_contained(
4762 {llvm::AtomicOrderingCABI::relaxed,
4763 llvm::AtomicOrderingCABI::consume,
4764 llvm::AtomicOrderingCABI::acquire,
4765 llvm::AtomicOrderingCABI::seq_cst},
4766 (llvm::AtomicOrderingCABI)Failure->getSExtValue())) {
4767 Diag(SubExprs[3]->getBeginLoc(),
4768 diag::warn_atomic_op_has_invalid_memory_order)
4769 << 2 << SubExprs[3]->getSourceRange();
4776 auto *
Scope = Args[Args.size() - 1];
4777 if (std::optional<llvm::APSInt>
Result =
4779 if (!ScopeModel->isValid(
Result->getZExtValue()))
4780 Diag(
Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_sync_scope)
4781 <<
Scope->getSourceRange();
4783 SubExprs.push_back(
Scope);
4789 if ((Op == AtomicExpr::AO__c11_atomic_load ||
4790 Op == AtomicExpr::AO__c11_atomic_store ||
4791 Op == AtomicExpr::AO__opencl_atomic_load ||
4792 Op == AtomicExpr::AO__hip_atomic_load ||
4793 Op == AtomicExpr::AO__opencl_atomic_store ||
4794 Op == AtomicExpr::AO__hip_atomic_store) &&
4795 Context.AtomicUsesUnsupportedLibcall(AE))
4797 << ((Op == AtomicExpr::AO__c11_atomic_load ||
4798 Op == AtomicExpr::AO__opencl_atomic_load ||
4799 Op == AtomicExpr::AO__hip_atomic_load)
4804 Diag(Ptr->
getExprLoc(), diag::err_atomic_builtin_bit_int_prohibit);
4820 assert(Fn &&
"builtin call without direct callee!");
4836 CallExpr *TheCall =
static_cast<CallExpr *
>(TheCallResult.
get());
4843 Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4845 <<
Callee->getSourceRange();
4854 Expr *FirstArg = TheCall->
getArg(0);
4858 FirstArg = FirstArgResult.
get();
4859 TheCall->
setArg(0, FirstArg);
4871 Diag(DRE->
getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intptr)
4878 diag::err_atomic_op_needs_non_address_discriminated_pointer)
4908 QualType ResultType = ValType;
4913#define BUILTIN_ROW(x) \
4914 { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \
4915 Builtin::BI##x##_8, Builtin::BI##x##_16 }
4917 static const unsigned BuiltinIndices[][5] = {
4942 switch (
Context.getTypeSizeInChars(ValType).getQuantity()) {
4943 case 1: SizeIndex = 0;
break;
4944 case 2: SizeIndex = 1;
break;
4945 case 4: SizeIndex = 2;
break;
4946 case 8: SizeIndex = 3;
break;
4947 case 16: SizeIndex = 4;
break;
4959 unsigned BuiltinIndex, NumFixed = 1;
4960 bool WarnAboutSemanticsChange =
false;
4961 switch (BuiltinID) {
4962 default: llvm_unreachable(
"Unknown overloaded atomic builtin!");
4963 case Builtin::BI__sync_fetch_and_add:
4964 case Builtin::BI__sync_fetch_and_add_1:
4965 case Builtin::BI__sync_fetch_and_add_2:
4966 case Builtin::BI__sync_fetch_and_add_4:
4967 case Builtin::BI__sync_fetch_and_add_8:
4968 case Builtin::BI__sync_fetch_and_add_16:
4972 case Builtin::BI__sync_fetch_and_sub:
4973 case Builtin::BI__sync_fetch_and_sub_1:
4974 case Builtin::BI__sync_fetch_and_sub_2:
4975 case Builtin::BI__sync_fetch_and_sub_4:
4976 case Builtin::BI__sync_fetch_and_sub_8:
4977 case Builtin::BI__sync_fetch_and_sub_16:
4981 case Builtin::BI__sync_fetch_and_or:
4982 case Builtin::BI__sync_fetch_and_or_1:
4983 case Builtin::BI__sync_fetch_and_or_2:
4984 case Builtin::BI__sync_fetch_and_or_4:
4985 case Builtin::BI__sync_fetch_and_or_8:
4986 case Builtin::BI__sync_fetch_and_or_16:
4990 case Builtin::BI__sync_fetch_and_and:
4991 case Builtin::BI__sync_fetch_and_and_1:
4992 case Builtin::BI__sync_fetch_and_and_2:
4993 case Builtin::BI__sync_fetch_and_and_4:
4994 case Builtin::BI__sync_fetch_and_and_8:
4995 case Builtin::BI__sync_fetch_and_and_16:
4999 case Builtin::BI__sync_fetch_and_xor:
5000 case Builtin::BI__sync_fetch_and_xor_1:
5001 case Builtin::BI__sync_fetch_and_xor_2:
5002 case Builtin::BI__sync_fetch_and_xor_4:
5003 case Builtin::BI__sync_fetch_and_xor_8:
5004 case Builtin::BI__sync_fetch_and_xor_16:
5008 case Builtin::BI__sync_fetch_and_nand:
5009 case Builtin::BI__sync_fetch_and_nand_1:
5010 case Builtin::BI__sync_fetch_and_nand_2:
5011 case Builtin::BI__sync_fetch_and_nand_4:
5012 case Builtin::BI__sync_fetch_and_nand_8:
5013 case Builtin::BI__sync_fetch_and_nand_16:
5015 WarnAboutSemanticsChange =
true;
5018 case Builtin::BI__sync_add_and_fetch:
5019 case Builtin::BI__sync_add_and_fetch_1:
5020 case Builtin::BI__sync_add_and_fetch_2:
5021 case Builtin::BI__sync_add_and_fetch_4:
5022 case Builtin::BI__sync_add_and_fetch_8:
5023 case Builtin::BI__sync_add_and_fetch_16:
5027 case Builtin::BI__sync_sub_and_fetch:
5028 case Builtin::BI__sync_sub_and_fetch_1:
5029 case Builtin::BI__sync_sub_and_fetch_2:
5030 case Builtin::BI__sync_sub_and_fetch_4:
5031 case Builtin::BI__sync_sub_and_fetch_8:
5032 case Builtin::BI__sync_sub_and_fetch_16:
5036 case Builtin::BI__sync_and_and_fetch:
5037 case Builtin::BI__sync_and_and_fetch_1:
5038 case Builtin::BI__sync_and_and_fetch_2:
5039 case Builtin::BI__sync_and_and_fetch_4:
5040 case Builtin::BI__sync_and_and_fetch_8:
5041 case Builtin::BI__sync_and_and_fetch_16:
5045 case Builtin::BI__sync_or_and_fetch:
5046 case Builtin::BI__sync_or_and_fetch_1:
5047 case Builtin::BI__sync_or_and_fetch_2:
5048 case Builtin::BI__sync_or_and_fetch_4:
5049 case Builtin::BI__sync_or_and_fetch_8:
5050 case Builtin::BI__sync_or_and_fetch_16:
5054 case Builtin::BI__sync_xor_and_fetch:
5055 case Builtin::BI__sync_xor_and_fetch_1:
5056 case Builtin::BI__sync_xor_and_fetch_2:
5057 case Builtin::BI__sync_xor_and_fetch_4:
5058 case Builtin::BI__sync_xor_and_fetch_8:
5059 case Builtin::BI__sync_xor_and_fetch_16:
5063 case Builtin::BI__sync_nand_and_fetch:
5064 case Builtin::BI__sync_nand_and_fetch_1:
5065 case Builtin::BI__sync_nand_and_fetch_2:
5066 case Builtin::BI__sync_nand_and_fetch_4:
5067 case Builtin::BI__sync_nand_and_fetch_8:
5068 case Builtin::BI__sync_nand_and_fetch_16:
5070 WarnAboutSemanticsChange =
true;
5073 case Builtin::BI__sync_val_compare_and_swap:
5074 case Builtin::BI__sync_val_compare_and_swap_1:
5075 case Builtin::BI__sync_val_compare_and_swap_2:
5076 case Builtin::BI__sync_val_compare_and_swap_4:
5077 case Builtin::BI__sync_val_compare_and_swap_8:
5078 case Builtin::BI__sync_val_compare_and_swap_16:
5083 case Builtin::BI__sync_bool_compare_and_swap:
5084 case Builtin::BI__sync_bool_compare_and_swap_1:
5085 case Builtin::BI__sync_bool_compare_and_swap_2:
5086 case Builtin::BI__sync_bool_compare_and_swap_4:
5087 case Builtin::BI__sync_bool_compare_and_swap_8:
5088 case Builtin::BI__sync_bool_compare_and_swap_16:
5094 case Builtin::BI__sync_lock_test_and_set:
5095 case Builtin::BI__sync_lock_test_and_set_1:
5096 case Builtin::BI__sync_lock_test_and_set_2:
5097 case Builtin::BI__sync_lock_test_and_set_4:
5098 case Builtin::BI__sync_lock_test_and_set_8:
5099 case Builtin::BI__sync_lock_test_and_set_16:
5103 case Builtin::BI__sync_lock_release:
5104 case Builtin::BI__sync_lock_release_1:
5105 case Builtin::BI__sync_lock_release_2:
5106 case Builtin::BI__sync_lock_release_4:
5107 case Builtin::BI__sync_lock_release_8:
5108 case Builtin::BI__sync_lock_release_16:
5114 case Builtin::BI__sync_swap:
5115 case Builtin::BI__sync_swap_1:
5116 case Builtin::BI__sync_swap_2:
5117 case Builtin::BI__sync_swap_4:
5118 case Builtin::BI__sync_swap_8:
5119 case Builtin::BI__sync_swap_16:
5127 Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
5128 << 0 << 1 + NumFixed << TheCall->
getNumArgs() << 0
5129 <<
Callee->getSourceRange();
5133 Diag(TheCall->
getEndLoc(), diag::warn_atomic_implicit_seq_cst)
5134 <<
Callee->getSourceRange();
5136 if (WarnAboutSemanticsChange) {
5137 Diag(TheCall->
getEndLoc(), diag::warn_sync_fetch_and_nand_semantics_change)
5138 <<
Callee->getSourceRange();
5143 unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
5144 std::string NewBuiltinName =
Context.BuiltinInfo.getName(NewBuiltinID);
5145 FunctionDecl *NewBuiltinDecl;
5146 if (NewBuiltinID == BuiltinID)
5147 NewBuiltinDecl = FDecl;
5150 DeclarationName DN(&
Context.Idents.get(NewBuiltinName));
5153 assert(Res.getFoundDecl());
5154 NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl());
5155 if (!NewBuiltinDecl)
5162 for (
unsigned i = 0; i != NumFixed; ++i) {
5191 QualType CalleePtrTy =
Context.getPointerType(NewBuiltinDecl->
getType());
5193 CK_BuiltinFnToFnPtr);
5204 const auto *BitIntValType = ValType->
getAs<BitIntType>();
5205 if (BitIntValType && !llvm::isPowerOf2_64(BitIntValType->getNumBits())) {
5206 Diag(FirstArg->
getExprLoc(), diag::err_atomic_builtin_ext_int_size);
5210 return TheCallResult;
5214 CallExpr *TheCall = (CallExpr *)TheCallResult.
get();
5219 assert((BuiltinID == Builtin::BI__builtin_nontemporal_store ||
5220 BuiltinID == Builtin::BI__builtin_nontemporal_load) &&
5221 "Unexpected nontemporal load/store builtin!");
5222 bool isStore = BuiltinID == Builtin::BI__builtin_nontemporal_store;
5223 unsigned numArgs = isStore ? 2 : 1;
5233 Expr *PointerArg = TheCall->
getArg(numArgs - 1);
5239 PointerArg = PointerArgResult.
get();
5240 TheCall->
setArg(numArgs - 1, PointerArg);
5244 Diag(DRE->
getBeginLoc(), diag::err_nontemporal_builtin_must_be_pointer)
5257 diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector)
5264 return TheCallResult;
5276 return TheCallResult;
5283 auto *
Literal = dyn_cast<StringLiteral>(Arg);
5285 if (
auto *ObjcLiteral = dyn_cast<ObjCStringLiteral>(Arg)) {
5286 Literal = ObjcLiteral->getString();
5290 if (!Literal || (!
Literal->isOrdinary() && !
Literal->isUTF8())) {
5297 QualType ResultTy =
Context.getPointerType(
Context.CharTy.withConst());
5298 InitializedEntity Entity =
5308 bool IsX64 = TT.getArch() == llvm::Triple::x86_64;
5309 bool IsAArch64 = (TT.getArch() == llvm::Triple::aarch64 ||
5310 TT.getArch() == llvm::Triple::aarch64_32);
5311 bool IsWindowsOrUEFI = TT.isOSWindows() || TT.isUEFI();
5312 bool IsMSVAStart = BuiltinID == Builtin::BI__builtin_ms_va_start;
5313 if (IsX64 || IsAArch64) {
5320 return S.
Diag(Fn->getBeginLoc(),
5321 diag::err_ms_va_start_used_in_sysv_function);
5328 (!IsWindowsOrUEFI && CC ==
CC_Win64))
5329 return S.
Diag(Fn->getBeginLoc(),
5330 diag::err_va_start_used_in_wrong_abi_function)
5331 << !IsWindowsOrUEFI;
5337 return S.
Diag(Fn->getBeginLoc(), diag::err_builtin_x64_aarch64_only);
5345 bool IsVariadic =
false;
5348 if (
auto *
Block = dyn_cast<BlockDecl>(Caller)) {
5349 IsVariadic =
Block->isVariadic();
5350 Params =
Block->parameters();
5351 }
else if (
auto *FD = dyn_cast<FunctionDecl>(Caller)) {
5354 }
else if (
auto *MD = dyn_cast<ObjCMethodDecl>(Caller)) {
5355 IsVariadic = MD->isVariadic();
5357 Params = MD->parameters();
5360 S.
Diag(Fn->getBeginLoc(), diag::err_va_start_captured_stmt);
5364 S.
Diag(Fn->getBeginLoc(), diag::err_va_start_outside_function);
5369 S.
Diag(Fn->getBeginLoc(), diag::err_va_start_fixed_function);
5374 *LastParam = Params.empty() ?
nullptr : Params.back();
5379bool Sema::BuiltinVAStart(
unsigned BuiltinID,
CallExpr *TheCall) {
5384 if (BuiltinID == Builtin::BI__builtin_c23_va_start) {
5408 ParmVarDecl *LastParam;
5419 if (BuiltinID == Builtin::BI__builtin_c23_va_start &&
5421 Diag(TheCall->
getExprLoc(), diag::warn_c17_compat_va_start_one_arg);
5426 if (std::optional<llvm::APSInt> Val =
5428 Val &&
LangOpts.C23 && *Val == 0 &&
5429 BuiltinID != Builtin::BI__builtin_c23_va_start) {
5430 Diag(TheCall->
getExprLoc(), diag::warn_c17_compat_va_start_one_arg);
5437 SourceLocation ParamLoc;
5438 bool IsCRegister =
false;
5439 bool SecondArgIsLastNonVariadicArgument =
false;
5440 if (
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
5441 if (
const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
5442 SecondArgIsLastNonVariadicArgument = PV == LastParam;
5445 ParamLoc = PV->getLocation();
5451 if (!SecondArgIsLastNonVariadicArgument)
5453 diag::warn_second_arg_of_va_start_not_last_non_variadic_param);
5454 else if (IsCRegister ||
Type->isReferenceType() ||
5455 Type->isSpecificBuiltinType(BuiltinType::Float) || [=] {
5458 if (!Context.isPromotableIntegerType(Type))
5460 const auto *ED = Type->getAsEnumDecl();
5463 return !Context.typesAreCompatible(ED->getPromotionType(), Type);
5465 unsigned Reason = 0;
5466 if (
Type->isReferenceType()) Reason = 1;
5467 else if (IsCRegister) Reason = 2;
5468 Diag(Arg->
getBeginLoc(), diag::warn_va_start_type_is_undefined) << Reason;
5469 Diag(ParamLoc, diag::note_parameter_type) <<
Type;
5476 auto IsSuitablyTypedFormatArgument = [
this](
const Expr *Arg) ->
bool {
5496 if (
Call->getNumArgs() < 3)
5498 diag::err_typecheck_call_too_few_args_at_least)
5499 << 0 << 3 <<
Call->getNumArgs()
5512 const Expr *Arg1 =
Call->getArg(1)->IgnoreParens();
5515 const Expr *Arg2 =
Call->getArg(2)->IgnoreParens();
5518 const QualType &ConstCharPtrTy =
5520 if (!Arg1Ty->
isPointerType() || !IsSuitablyTypedFormatArgument(Arg1))
5522 << Arg1->
getType() << ConstCharPtrTy << 1
5525 << 2 << Arg1->
getType() << ConstCharPtrTy;
5527 const QualType SizeTy =
Context.getSizeType();
5532 << Arg2->
getType() << SizeTy << 1
5535 << 3 << Arg2->
getType() << SizeTy;
5540bool Sema::BuiltinUnorderedCompare(
CallExpr *TheCall,
unsigned BuiltinID) {
5544 if (BuiltinID == Builtin::BI__builtin_isunordered &&
5572 diag::err_typecheck_call_invalid_ordered_compare)
5580bool Sema::BuiltinFPClassification(
CallExpr *TheCall,
unsigned NumArgs,
5581 unsigned BuiltinID) {
5586 if (FPO.getNoHonorInfs() && (BuiltinID == Builtin::BI__builtin_isfinite ||
5587 BuiltinID == Builtin::BI__builtin_isinf ||
5588 BuiltinID == Builtin::BI__builtin_isinf_sign))
5592 if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
5593 BuiltinID == Builtin::BI__builtin_isunordered))
5597 bool IsFPClass = NumArgs == 2;
5600 unsigned FPArgNo = IsFPClass ? 0 : NumArgs - 1;
5604 for (
unsigned i = 0; i < FPArgNo; ++i) {
5605 Expr *Arg = TheCall->
getArg(i);
5618 Expr *OrigArg = TheCall->
getArg(FPArgNo);
5626 if (
Context.getTargetInfo().useFP16ConversionIntrinsics()) {
5631 OrigArg = Res.
get();
5637 OrigArg = Res.
get();
5639 TheCall->
setArg(FPArgNo, OrigArg);
5641 QualType VectorResultTy;
5642 QualType ElementTy = OrigArg->
getType();
5647 ElementTy = ElementTy->
castAs<VectorType>()->getElementType();
5653 diag::err_typecheck_call_invalid_unary_fp)
5665 if (!VectorResultTy.
isNull())
5666 ResultTy = VectorResultTy;
5675bool Sema::BuiltinComplex(
CallExpr *TheCall) {
5680 for (
unsigned I = 0; I != 2; ++I) {
5681 Expr *Arg = TheCall->
getArg(I);
5691 return Diag(Arg->
getBeginLoc(), diag::err_typecheck_call_requires_real_fp)
5706 Expr *Real = TheCall->
getArg(0);
5707 Expr *Imag = TheCall->
getArg(1);
5710 diag::err_typecheck_call_different_arg_types)
5725 diag::err_typecheck_call_too_few_args_at_least)
5726 << 0 << 2 << NumArgs
5733 unsigned NumElements = 0;
5748 unsigned NumResElements = NumArgs - 2;
5757 diag::err_vec_builtin_incompatible_vector)
5762 }
else if (!
Context.hasSameUnqualifiedType(LHSType, RHSType)) {
5764 diag::err_vec_builtin_incompatible_vector)
5769 }
else if (NumElements != NumResElements) {
5772 ?
Context.getExtVectorType(EltType, NumResElements)
5773 :
Context.getVectorType(EltType, NumResElements,
5778 for (
unsigned I = 2; I != NumArgs; ++I) {
5786 diag::err_shufflevector_nonconstant_argument)
5792 else if (
Result->getActiveBits() > 64 ||
5793 Result->getZExtValue() >= NumElements * 2)
5795 diag::err_shufflevector_argument_too_large)
5820 diag::err_convertvector_non_vector)
5823 return ExprError(
Diag(BuiltinLoc, diag::err_builtin_non_vector_type)
5825 <<
"__builtin_convertvector");
5830 if (SrcElts != DstElts)
5832 diag::err_convertvector_incompatible_vector)
5840bool Sema::BuiltinPrefetch(
CallExpr *TheCall) {
5845 diag::err_typecheck_call_too_many_args_at_most)
5846 << 0 << 3 << NumArgs << 0
5851 for (
unsigned i = 1; i != NumArgs; ++i)
5858bool Sema::BuiltinArithmeticFence(
CallExpr *TheCall) {
5859 if (!Context.getTargetInfo().checkArithmeticFenceSupported())
5860 return Diag(TheCall->
getBeginLoc(), diag::err_builtin_target_unsupported)
5870 return Diag(TheCall->
getEndLoc(), diag::err_typecheck_expect_flt_or_vector)
5880bool Sema::BuiltinAssume(
CallExpr *TheCall) {
5881 Expr *Arg = TheCall->
getArg(0);
5892bool Sema::BuiltinAllocaWithAlign(
CallExpr *TheCall) {
5894 Expr *Arg = TheCall->
getArg(1);
5898 if (
const auto *UE =
5900 if (UE->getKind() == UETT_AlignOf ||
5901 UE->getKind() == UETT_PreferredAlignOf)
5907 if (!
Result.isPowerOf2())
5908 return Diag(TheCall->
getBeginLoc(), diag::err_alignment_not_power_of_two)
5915 if (
Result > std::numeric_limits<int32_t>::max())
5923bool Sema::BuiltinAssumeAligned(
CallExpr *TheCall) {
5928 Expr *FirstArg = TheCall->
getArg(0);
5934 Diag(TheCall->
getBeginLoc(), diag::err_builtin_assume_aligned_invalid_arg)
5938 TheCall->
setArg(0, FirstArgResult.
get());
5942 Expr *SecondArg = TheCall->
getArg(1);
5950 if (!
Result.isPowerOf2())
5951 return Diag(TheCall->
getBeginLoc(), diag::err_alignment_not_power_of_two)
5963 Expr *ThirdArg = TheCall->
getArg(2);
5966 TheCall->
setArg(2, ThirdArg);
5972bool Sema::BuiltinOSLogFormat(
CallExpr *TheCall) {
5973 unsigned BuiltinID =
5975 bool IsSizeCall = BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size;
5978 unsigned NumRequiredArgs = IsSizeCall ? 1 : 2;
5979 if (NumArgs < NumRequiredArgs) {
5980 return Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args)
5981 << 0 << NumRequiredArgs << NumArgs
5984 if (NumArgs >= NumRequiredArgs + 0x100) {
5986 diag::err_typecheck_call_too_many_args_at_most)
5987 << 0 << (NumRequiredArgs + 0xff) << NumArgs
5998 if (Arg.isInvalid())
6000 TheCall->
setArg(i, Arg.get());
6005 unsigned FormatIdx = i;
6015 unsigned FirstDataArg = i;
6016 while (i < NumArgs) {
6034 llvm::SmallBitVector CheckedVarArgs(NumArgs,
false);
6036 bool Success = CheckFormatArguments(
6039 TheCall->
getBeginLoc(), SourceRange(), CheckedVarArgs);
6063 return Diag(TheCall->
getBeginLoc(), diag::err_constant_integer_arg_type)
6072 int High,
bool RangeIsError) {
6086 if (
Result.getSExtValue() < Low ||
Result.getSExtValue() > High) {
6094 PDiag(diag::warn_argument_invalid_range)
6137 return Diag(TheCall->
getBeginLoc(), diag::err_argument_not_power_of_2)
6142 if (
Value.isNegative())
6153 if ((
Value & 0xFF) != 0)
6178 Result.setIsUnsigned(
true);
6183 return Diag(TheCall->
getBeginLoc(), diag::err_argument_not_shifted_byte)
6203 Result.setIsUnsigned(
true);
6211 diag::err_argument_not_shifted_byte_or_xxff)
6215bool Sema::BuiltinLongjmp(
CallExpr *TheCall) {
6216 if (!Context.getTargetInfo().hasSjLjLowering())
6217 return Diag(TheCall->
getBeginLoc(), diag::err_builtin_longjmp_unsupported)
6228 return Diag(TheCall->
getBeginLoc(), diag::err_builtin_longjmp_invalid_val)
6234bool Sema::BuiltinSetjmp(
CallExpr *TheCall) {
6235 if (!Context.getTargetInfo().hasSjLjLowering())
6236 return Diag(TheCall->
getBeginLoc(), diag::err_builtin_setjmp_unsupported)
6241bool Sema::BuiltinCountedByRef(
CallExpr *TheCall) {
6256 diag::err_builtin_counted_by_ref_must_be_flex_array_member)
6261 diag::err_builtin_counted_by_ref_has_side_effects)
6264 if (
const auto *ME = dyn_cast<MemberExpr>(Arg)) {
6265 if (!ME->isFlexibleArrayMemberLike(
6268 diag::err_builtin_counted_by_ref_must_be_flex_array_member)
6272 ME->getMemberDecl()->getType()->getAs<CountAttributedType>();
6275 if (
const FieldDecl *CountFD = FAMDecl->findCountedByField()) {
6282 diag::err_builtin_counted_by_ref_must_be_flex_array_member)
6292bool Sema::CheckInvalidBuiltinCountedByRef(
const Expr *E,
6294 const CallExpr *CE =
6303 diag::err_builtin_counted_by_ref_cannot_leak_reference)
6308 diag::err_builtin_counted_by_ref_cannot_leak_reference)
6313 diag::err_builtin_counted_by_ref_cannot_leak_reference)
6317 Diag(E->
getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
6321 Diag(E->
getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
6331class UncoveredArgHandler {
6332 enum {
Unknown = -1, AllCovered = -2 };
6334 signed FirstUncoveredArg =
Unknown;
6335 SmallVector<const Expr *, 4> DiagnosticExprs;
6338 UncoveredArgHandler() =
default;
6340 bool hasUncoveredArg()
const {
6341 return (FirstUncoveredArg >= 0);
6344 unsigned getUncoveredArg()
const {
6345 assert(hasUncoveredArg() &&
"no uncovered argument");
6346 return FirstUncoveredArg;
6349 void setAllCovered() {
6352 DiagnosticExprs.clear();
6353 FirstUncoveredArg = AllCovered;
6356 void Update(
signed NewFirstUncoveredArg,
const Expr *StrExpr) {
6357 assert(NewFirstUncoveredArg >= 0 &&
"Outside range");
6360 if (FirstUncoveredArg == AllCovered)
6365 if (NewFirstUncoveredArg == FirstUncoveredArg)
6366 DiagnosticExprs.push_back(StrExpr);
6367 else if (NewFirstUncoveredArg > FirstUncoveredArg) {
6368 DiagnosticExprs.clear();
6369 DiagnosticExprs.push_back(StrExpr);
6370 FirstUncoveredArg = NewFirstUncoveredArg;
6374 void Diagnose(Sema &S,
bool IsFunctionCall,
const Expr *ArgExpr);
6377enum StringLiteralCheckType {
6379 SLCT_UncheckedLiteral,
6387 bool AddendIsRight) {
6388 unsigned BitWidth = Offset.getBitWidth();
6389 unsigned AddendBitWidth = Addend.getBitWidth();
6391 if (Addend.isUnsigned()) {
6392 Addend = Addend.zext(++AddendBitWidth);
6393 Addend.setIsSigned(
true);
6396 if (AddendBitWidth > BitWidth) {
6397 Offset = Offset.sext(AddendBitWidth);
6398 BitWidth = AddendBitWidth;
6399 }
else if (BitWidth > AddendBitWidth) {
6400 Addend = Addend.sext(BitWidth);
6404 llvm::APSInt ResOffset = Offset;
6405 if (BinOpKind == BO_Add)
6406 ResOffset = Offset.sadd_ov(Addend, Ov);
6408 assert(AddendIsRight && BinOpKind == BO_Sub &&
6409 "operator must be add or sub with addend on the right");
6410 ResOffset = Offset.ssub_ov(Addend, Ov);
6416 assert(BitWidth <= std::numeric_limits<unsigned>::max() / 2 &&
6417 "index (intermediate) result too big");
6418 Offset = Offset.sext(2 * BitWidth);
6419 sumOffsets(Offset, Addend, BinOpKind, AddendIsRight);
6431class FormatStringLiteral {
6432 const StringLiteral *FExpr;
6436 FormatStringLiteral(
const StringLiteral *fexpr, int64_t Offset = 0)
6437 : FExpr(fexpr), Offset(Offset) {}
6439 const StringLiteral *getFormatString()
const {
return FExpr; }
6441 StringRef getString()
const {
return FExpr->
getString().drop_front(Offset); }
6443 unsigned getByteLength()
const {
6444 return FExpr->
getByteLength() - getCharByteWidth() * Offset;
6447 unsigned getLength()
const {
return FExpr->
getLength() - Offset; }
6454 bool isAscii()
const {
return FExpr->
isOrdinary(); }
6455 bool isWide()
const {
return FExpr->
isWide(); }
6456 bool isUTF8()
const {
return FExpr->
isUTF8(); }
6457 bool isUTF16()
const {
return FExpr->
isUTF16(); }
6458 bool isUTF32()
const {
return FExpr->
isUTF32(); }
6459 bool isPascal()
const {
return FExpr->
isPascal(); }
6461 SourceLocation getLocationOfByte(
6462 unsigned ByteNo,
const SourceManager &
SM,
const LangOptions &Features,
6463 const TargetInfo &
Target,
unsigned *StartToken =
nullptr,
6464 unsigned *StartTokenByteOffset =
nullptr)
const {
6466 StartToken, StartTokenByteOffset);
6469 SourceLocation getBeginLoc() const LLVM_READONLY {
6473 SourceLocation getEndLoc() const LLVM_READONLY {
return FExpr->
getEndLoc(); }
6479 Sema &S,
const FormatStringLiteral *FExpr,
6484 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
6485 bool IgnoreStringsWithoutSpecifiers);
6499 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
6500 llvm::APSInt Offset,
bool IgnoreStringsWithoutSpecifiers =
false) {
6502 return SLCT_NotALiteral;
6504 assert(Offset.isSigned() &&
"invalid offset");
6507 return SLCT_NotALiteral;
6516 return SLCT_UncheckedLiteral;
6519 case Stmt::InitListExprClass:
6523 S, ReferenceFormatString, SLE, Args, APK, format_idx, firstDataArg,
6524 Type, CallType,
false, CheckedVarArgs,
6525 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6527 return SLCT_NotALiteral;
6528 case Stmt::BinaryConditionalOperatorClass:
6529 case Stmt::ConditionalOperatorClass: {
6538 bool CheckLeft =
true, CheckRight =
true;
6541 if (
C->getCond()->EvaluateAsBooleanCondition(
6553 StringLiteralCheckType Left;
6555 Left = SLCT_UncheckedLiteral;
6558 S, ReferenceFormatString,
C->getTrueExpr(), Args, APK, format_idx,
6559 firstDataArg,
Type, CallType, InFunctionCall, CheckedVarArgs,
6560 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6561 if (Left == SLCT_NotALiteral || !CheckRight) {
6567 S, ReferenceFormatString,
C->getFalseExpr(), Args, APK, format_idx,
6568 firstDataArg,
Type, CallType, InFunctionCall, CheckedVarArgs,
6569 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6571 return (CheckLeft && Left < Right) ? Left : Right;
6574 case Stmt::ImplicitCastExprClass:
6578 case Stmt::OpaqueValueExprClass:
6583 return SLCT_NotALiteral;
6585 case Stmt::PredefinedExprClass:
6589 return SLCT_UncheckedLiteral;
6591 case Stmt::DeclRefExprClass: {
6597 bool isConstant =
false;
6601 isConstant = AT->getElementType().isConstant(S.
Context);
6603 isConstant =
T.isConstant(S.
Context) &&
6604 PT->getPointeeType().isConstant(S.
Context);
6605 }
else if (
T->isObjCObjectPointerType()) {
6608 isConstant =
T.isConstant(S.
Context);
6612 if (
const Expr *
Init = VD->getAnyInitializer()) {
6615 if (InitList->isStringLiteralInit())
6616 Init = InitList->getInit(0)->IgnoreParenImpCasts();
6619 S, ReferenceFormatString,
Init, Args, APK, format_idx,
6620 firstDataArg,
Type, CallType,
6621 false, CheckedVarArgs, UncoveredArg, Offset);
6672 if (
const auto *PV = dyn_cast<ParmVarDecl>(VD)) {
6673 if (
const auto *D = dyn_cast<Decl>(PV->getDeclContext())) {
6674 for (
const auto *PVFormatMatches :
6675 D->specific_attrs<FormatMatchesAttr>()) {
6680 if (PV->getFunctionScopeIndex() == CalleeFSI.
FormatIdx) {
6684 S.
Diag(Args[format_idx]->getBeginLoc(),
6685 diag::warn_format_string_type_incompatible)
6686 << PVFormatMatches->getType()->getName()
6688 if (!InFunctionCall) {
6689 S.
Diag(PVFormatMatches->getFormatString()->getBeginLoc(),
6690 diag::note_format_string_defined);
6692 return SLCT_UncheckedLiteral;
6695 S, ReferenceFormatString, PVFormatMatches->getFormatString(),
6696 Args, APK, format_idx, firstDataArg,
Type, CallType,
6697 false, CheckedVarArgs, UncoveredArg,
6698 Offset, IgnoreStringsWithoutSpecifiers);
6702 for (
const auto *PVFormat : D->specific_attrs<FormatAttr>()) {
6705 PVFormat->getFirstArg(), &CallerFSI))
6707 if (PV->getFunctionScopeIndex() == CallerFSI.
FormatIdx) {
6711 S.
Diag(Args[format_idx]->getBeginLoc(),
6712 diag::warn_format_string_type_incompatible)
6713 << PVFormat->getType()->getName()
6715 if (!InFunctionCall) {
6718 return SLCT_UncheckedLiteral;
6731 return SLCT_UncheckedLiteral;
6739 return SLCT_NotALiteral;
6742 case Stmt::CallExprClass:
6743 case Stmt::CXXMemberCallExprClass: {
6747 StringLiteralCheckType CommonResult;
6748 for (
const auto *FA : ND->specific_attrs<FormatArgAttr>()) {
6749 const Expr *Arg = CE->
getArg(FA->getFormatIdx().getASTIndex());
6751 S, ReferenceFormatString, Arg, Args, APK, format_idx, firstDataArg,
6752 Type, CallType, InFunctionCall, CheckedVarArgs, UncoveredArg,
6753 Offset, IgnoreStringsWithoutSpecifiers);
6755 CommonResult = Result;
6760 return CommonResult;
6762 if (
const auto *FD = dyn_cast<FunctionDecl>(ND)) {
6764 if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
6765 BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) {
6768 S, ReferenceFormatString, Arg, Args, APK, format_idx,
6769 firstDataArg,
Type, CallType, InFunctionCall, CheckedVarArgs,
6770 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6776 S, ReferenceFormatString, SLE, Args, APK, format_idx, firstDataArg,
6777 Type, CallType,
false, CheckedVarArgs,
6778 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6779 return SLCT_NotALiteral;
6781 case Stmt::ObjCMessageExprClass: {
6783 if (
const auto *MD = ME->getMethodDecl()) {
6784 if (
const auto *FA = MD->getAttr<FormatArgAttr>()) {
6793 if (MD->isInstanceMethod() && (IFace = MD->getClassInterface()) &&
6795 MD->getSelector().isKeywordSelector(
6796 {
"localizedStringForKey",
"value",
"table"})) {
6797 IgnoreStringsWithoutSpecifiers =
true;
6800 const Expr *Arg = ME->getArg(FA->getFormatIdx().getASTIndex());
6802 S, ReferenceFormatString, Arg, Args, APK, format_idx, firstDataArg,
6803 Type, CallType, InFunctionCall, CheckedVarArgs, UncoveredArg,
6804 Offset, IgnoreStringsWithoutSpecifiers);
6808 return SLCT_NotALiteral;
6810 case Stmt::ObjCStringLiteralClass:
6811 case Stmt::StringLiteralClass: {
6820 if (Offset.isNegative() || Offset > StrE->
getLength()) {
6823 return SLCT_NotALiteral;
6825 FormatStringLiteral FStr(StrE, Offset.sextOrTrunc(64).getSExtValue());
6827 format_idx, firstDataArg,
Type, InFunctionCall,
6828 CallType, CheckedVarArgs, UncoveredArg,
6829 IgnoreStringsWithoutSpecifiers);
6830 return SLCT_CheckedLiteral;
6833 return SLCT_NotALiteral;
6835 case Stmt::BinaryOperatorClass: {
6849 if (LIsInt != RIsInt) {
6853 if (BinOpKind == BO_Add) {
6866 return SLCT_NotALiteral;
6868 case Stmt::UnaryOperatorClass: {
6870 auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->
getSubExpr());
6871 if (UnaOp->
getOpcode() == UO_AddrOf && ASE) {
6873 if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.
Context,
6883 return SLCT_NotALiteral;
6887 return SLCT_NotALiteral;
6898 const auto *LVE = Result.Val.getLValueBase().dyn_cast<
const Expr *>();
6899 if (isa_and_nonnull<StringLiteral>(LVE))
6920 return "freebsd_kprintf";
6929 return llvm::StringSwitch<FormatStringType>(Flavor)
6931 .Cases(
"gnu_printf",
"printf",
"printf0",
"syslog",
6936 .Cases(
"kprintf",
"cmn_err",
"vcmn_err",
"zcmn_err",
6952bool Sema::CheckFormatArguments(
const FormatAttr *Format,
6956 llvm::SmallBitVector &CheckedVarArgs) {
6957 FormatStringInfo FSI;
6961 return CheckFormatArguments(
6962 Args, FSI.ArgPassingKind,
nullptr, FSI.FormatIdx, FSI.FirstDataArg,
6967bool Sema::CheckFormatString(
const FormatMatchesAttr *Format,
6971 llvm::SmallBitVector &CheckedVarArgs) {
6972 FormatStringInfo FSI;
6976 return CheckFormatArguments(Args, FSI.ArgPassingKind,
6977 Format->getFormatString(), FSI.FormatIdx,
6979 CallType, Loc, Range, CheckedVarArgs);
6987 unsigned format_idx,
unsigned firstDataArg,
6991 llvm::SmallBitVector &CheckedVarArgs) {
6993 if (format_idx >= Args.size()) {
6994 Diag(Loc, diag::warn_missing_format_string) <<
Range;
6998 const Expr *OrigFormatExpr = Args[format_idx]->IgnoreParenCasts();
7012 UncoveredArgHandler UncoveredArg;
7014 *
this, ReferenceFormatString, OrigFormatExpr, Args, APK, format_idx,
7015 firstDataArg,
Type, CallType,
7016 true, CheckedVarArgs, UncoveredArg,
7017 llvm::APSInt(64,
false) = 0);
7020 if (UncoveredArg.hasUncoveredArg()) {
7021 unsigned ArgIdx = UncoveredArg.getUncoveredArg() + firstDataArg;
7022 assert(ArgIdx < Args.size() &&
"ArgIdx outside bounds");
7023 UncoveredArg.Diagnose(*
this,
true, Args[ArgIdx]);
7026 if (CT != SLCT_NotALiteral)
7028 return CT == SLCT_CheckedLiteral;
7039 SourceLocation FormatLoc = Args[format_idx]->getBeginLoc();
7046 if (Args.size() == firstDataArg) {
7047 Diag(FormatLoc, diag::warn_format_nonliteral_noargs)
7055 Diag(FormatLoc, diag::note_format_security_fixit)
7059 Diag(FormatLoc, diag::note_format_security_fixit)
7064 Diag(FormatLoc, diag::warn_format_nonliteral)
7075 const FormatStringLiteral *FExpr;
7076 const Expr *OrigFormatExpr;
7078 const unsigned FirstDataArg;
7079 const unsigned NumDataArgs;
7082 ArrayRef<const Expr *> Args;
7084 llvm::SmallBitVector CoveredArgs;
7085 bool usesPositionalArgs =
false;
7086 bool atFirstArg =
true;
7087 bool inFunctionCall;
7089 llvm::SmallBitVector &CheckedVarArgs;
7090 UncoveredArgHandler &UncoveredArg;
7093 CheckFormatHandler(Sema &
s,
const FormatStringLiteral *fexpr,
7095 unsigned firstDataArg,
unsigned numDataArgs,
7097 ArrayRef<const Expr *> Args,
unsigned formatIdx,
7099 llvm::SmallBitVector &CheckedVarArgs,
7100 UncoveredArgHandler &UncoveredArg)
7101 : S(
s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FSType(
type),
7102 FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg),
7103 ArgPassingKind(APK), Args(Args), FormatIdx(formatIdx),
7104 inFunctionCall(inFunctionCall), CallType(callType),
7105 CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) {
7106 CoveredArgs.resize(numDataArgs);
7107 CoveredArgs.reset();
7110 bool HasFormatArguments()
const {
7115 void DoneProcessing();
7117 void HandleIncompleteSpecifier(
const char *startSpecifier,
7118 unsigned specifierLen)
override;
7120 void HandleInvalidLengthModifier(
7121 const analyze_format_string::FormatSpecifier &FS,
7122 const analyze_format_string::ConversionSpecifier &CS,
7123 const char *startSpecifier,
unsigned specifierLen,
7126 void HandleNonStandardLengthModifier(
7127 const analyze_format_string::FormatSpecifier &FS,
7128 const char *startSpecifier,
unsigned specifierLen);
7130 void HandleNonStandardConversionSpecifier(
7131 const analyze_format_string::ConversionSpecifier &CS,
7132 const char *startSpecifier,
unsigned specifierLen);
7134 void HandlePosition(
const char *startPos,
unsigned posLen)
override;
7136 void HandleInvalidPosition(
const char *startSpecifier,
7137 unsigned specifierLen,
7140 void HandleZeroPosition(
const char *startPos,
unsigned posLen)
override;
7142 void HandleNullChar(
const char *nullCharacter)
override;
7144 template <
typename Range>
7146 EmitFormatDiagnostic(Sema &S,
bool inFunctionCall,
const Expr *ArgumentExpr,
7147 const PartialDiagnostic &PDiag, SourceLocation StringLoc,
7148 bool IsStringLocation, Range StringRange,
7149 ArrayRef<FixItHint> Fixit = {});
7152 bool HandleInvalidConversionSpecifier(
unsigned argIndex, SourceLocation Loc,
7153 const char *startSpec,
7154 unsigned specifierLen,
7155 const char *csStart,
unsigned csLen);
7157 void HandlePositionalNonpositionalArgs(SourceLocation Loc,
7158 const char *startSpec,
7159 unsigned specifierLen);
7161 SourceRange getFormatStringRange();
7162 CharSourceRange getSpecifierRange(
const char *startSpecifier,
7163 unsigned specifierLen);
7164 SourceLocation getLocationOfByte(
const char *x);
7166 const Expr *getDataArg(
unsigned i)
const;
7168 bool CheckNumArgs(
const analyze_format_string::FormatSpecifier &FS,
7169 const analyze_format_string::ConversionSpecifier &CS,
7170 const char *startSpecifier,
unsigned specifierLen,
7173 template <
typename Range>
7174 void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
7175 bool IsStringLocation, Range StringRange,
7176 ArrayRef<FixItHint> Fixit = {});
7181SourceRange CheckFormatHandler::getFormatStringRange() {
7186getSpecifierRange(
const char *startSpecifier,
unsigned specifierLen) {
7188 SourceLocation End = getLocationOfByte(startSpecifier + specifierLen - 1);
7196SourceLocation CheckFormatHandler::getLocationOfByte(
const char *x) {
7201void CheckFormatHandler::HandleIncompleteSpecifier(
const char *startSpecifier,
7202 unsigned specifierLen){
7203 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_incomplete_specifier),
7204 getLocationOfByte(startSpecifier),
7206 getSpecifierRange(startSpecifier, specifierLen));
7209void CheckFormatHandler::HandleInvalidLengthModifier(
7212 const char *startSpecifier,
unsigned specifierLen,
unsigned DiagID) {
7224 getSpecifierRange(startSpecifier, specifierLen));
7226 S.
Diag(getLocationOfByte(LM.
getStart()), diag::note_format_fix_specifier)
7227 << FixedLM->toString()
7232 if (DiagID == diag::warn_format_nonsensical_length)
7238 getSpecifierRange(startSpecifier, specifierLen),
7243void CheckFormatHandler::HandleNonStandardLengthModifier(
7245 const char *startSpecifier,
unsigned specifierLen) {
7254 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard)
7258 getSpecifierRange(startSpecifier, specifierLen));
7260 S.
Diag(getLocationOfByte(LM.
getStart()), diag::note_format_fix_specifier)
7261 << FixedLM->toString()
7265 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard)
7269 getSpecifierRange(startSpecifier, specifierLen));
7273void CheckFormatHandler::HandleNonStandardConversionSpecifier(
7275 const char *startSpecifier,
unsigned specifierLen) {
7281 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard)
7285 getSpecifierRange(startSpecifier, specifierLen));
7288 S.
Diag(getLocationOfByte(CS.
getStart()), diag::note_format_fix_specifier)
7289 << FixedCS->toString()
7292 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard)
7296 getSpecifierRange(startSpecifier, specifierLen));
7300void CheckFormatHandler::HandlePosition(
const char *startPos,
7303 diag::warn_format_non_standard_positional_arg,
SourceLocation()))
7304 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard_positional_arg),
7305 getLocationOfByte(startPos),
7307 getSpecifierRange(startPos, posLen));
7310void CheckFormatHandler::HandleInvalidPosition(
7311 const char *startSpecifier,
unsigned specifierLen,
7314 diag::warn_format_invalid_positional_specifier,
SourceLocation()))
7315 EmitFormatDiagnostic(
7316 S.
PDiag(diag::warn_format_invalid_positional_specifier) << (
unsigned)p,
7317 getLocationOfByte(startSpecifier),
true,
7318 getSpecifierRange(startSpecifier, specifierLen));
7321void CheckFormatHandler::HandleZeroPosition(
const char *startPos,
7325 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_zero_positional_specifier),
7326 getLocationOfByte(startPos),
7328 getSpecifierRange(startPos, posLen));
7331void CheckFormatHandler::HandleNullChar(
const char *nullCharacter) {
7334 EmitFormatDiagnostic(
7335 S.
PDiag(diag::warn_printf_format_string_contains_null_char),
7336 getLocationOfByte(nullCharacter),
true,
7337 getFormatStringRange());
7343const Expr *CheckFormatHandler::getDataArg(
unsigned i)
const {
7344 return Args[FirstDataArg + i];
7347void CheckFormatHandler::DoneProcessing() {
7350 if (HasFormatArguments()) {
7353 signed notCoveredArg = CoveredArgs.find_first();
7354 if (notCoveredArg >= 0) {
7355 assert((
unsigned)notCoveredArg < NumDataArgs);
7356 UncoveredArg.Update(notCoveredArg, OrigFormatExpr);
7358 UncoveredArg.setAllCovered();
7363void UncoveredArgHandler::Diagnose(
Sema &S,
bool IsFunctionCall,
7364 const Expr *ArgExpr) {
7365 assert(hasUncoveredArg() && !DiagnosticExprs.empty() &&
7377 for (
auto E : DiagnosticExprs)
7380 CheckFormatHandler::EmitFormatDiagnostic(
7381 S, IsFunctionCall, DiagnosticExprs[0],
7387CheckFormatHandler::HandleInvalidConversionSpecifier(
unsigned argIndex,
7389 const char *startSpec,
7390 unsigned specifierLen,
7391 const char *csStart,
7393 bool keepGoing =
true;
7394 if (argIndex < NumDataArgs) {
7397 CoveredArgs.set(argIndex);
7413 std::string CodePointStr;
7414 if (!llvm::sys::locale::isPrint(*csStart)) {
7415 llvm::UTF32 CodePoint;
7416 const llvm::UTF8 **B =
reinterpret_cast<const llvm::UTF8 **
>(&csStart);
7417 const llvm::UTF8 *E =
7418 reinterpret_cast<const llvm::UTF8 *
>(csStart + csLen);
7419 llvm::ConversionResult
Result =
7420 llvm::convertUTF8Sequence(B, E, &CodePoint, llvm::strictConversion);
7422 if (
Result != llvm::conversionOK) {
7423 unsigned char FirstChar = *csStart;
7424 CodePoint = (llvm::UTF32)FirstChar;
7427 llvm::raw_string_ostream
OS(CodePointStr);
7428 if (CodePoint < 256)
7429 OS <<
"\\x" << llvm::format(
"%02x", CodePoint);
7430 else if (CodePoint <= 0xFFFF)
7431 OS <<
"\\u" << llvm::format(
"%04x", CodePoint);
7433 OS <<
"\\U" << llvm::format(
"%08x", CodePoint);
7437 EmitFormatDiagnostic(
7438 S.
PDiag(diag::warn_format_invalid_conversion) << Specifier, Loc,
7439 true, getSpecifierRange(startSpec, specifierLen));
7445CheckFormatHandler::HandlePositionalNonpositionalArgs(
SourceLocation Loc,
7446 const char *startSpec,
7447 unsigned specifierLen) {
7448 EmitFormatDiagnostic(
7449 S.
PDiag(diag::warn_format_mix_positional_nonpositional_args),
7450 Loc,
true, getSpecifierRange(startSpec, specifierLen));
7454CheckFormatHandler::CheckNumArgs(
7457 const char *startSpecifier,
unsigned specifierLen,
unsigned argIndex) {
7459 if (HasFormatArguments() && argIndex >= NumDataArgs) {
7461 ? (S.
PDiag(diag::warn_printf_positional_arg_exceeds_data_args)
7462 << (argIndex+1) << NumDataArgs)
7463 : S.
PDiag(diag::warn_printf_insufficient_data_args);
7464 EmitFormatDiagnostic(
7465 PDiag, getLocationOfByte(CS.
getStart()),
true,
7466 getSpecifierRange(startSpecifier, specifierLen));
7470 UncoveredArg.setAllCovered();
7476template<
typename Range>
7479 bool IsStringLocation,
7482 EmitFormatDiagnostic(S, inFunctionCall, Args[FormatIdx], PDiag,
7483 Loc, IsStringLocation, StringRange, FixIt);
7513template <
typename Range>
7514void CheckFormatHandler::EmitFormatDiagnostic(
7515 Sema &S,
bool InFunctionCall,
const Expr *ArgumentExpr,
7518 if (InFunctionCall) {
7523 S.
Diag(IsStringLocation ? ArgumentExpr->
getExprLoc() : Loc, PDiag)
7527 S.
Diag(IsStringLocation ? Loc : StringRange.getBegin(),
7528 diag::note_format_string_defined);
7530 Note << StringRange;
7539class CheckPrintfHandler :
public CheckFormatHandler {
7541 CheckPrintfHandler(Sema &
s,
const FormatStringLiteral *fexpr,
7543 unsigned firstDataArg,
unsigned numDataArgs,
bool isObjC,
7545 ArrayRef<const Expr *> Args,
unsigned formatIdx,
7547 llvm::SmallBitVector &CheckedVarArgs,
7548 UncoveredArgHandler &UncoveredArg)
7549 : CheckFormatHandler(
s, fexpr, origFormatExpr,
type, firstDataArg,
7550 numDataArgs, beg, APK, Args, formatIdx,
7551 inFunctionCall, CallType, CheckedVarArgs,
7554 bool isObjCContext()
const {
return FSType == FormatStringType::NSString; }
7557 bool allowsObjCArg()
const {
7558 return FSType == FormatStringType::NSString ||
7559 FSType == FormatStringType::OSLog ||
7560 FSType == FormatStringType::OSTrace;
7563 bool HandleInvalidPrintfConversionSpecifier(
7564 const analyze_printf::PrintfSpecifier &FS,
7565 const char *startSpecifier,
7566 unsigned specifierLen)
override;
7568 void handleInvalidMaskType(StringRef MaskType)
override;
7570 bool HandlePrintfSpecifier(
const analyze_printf::PrintfSpecifier &FS,
7571 const char *startSpecifier,
unsigned specifierLen,
7572 const TargetInfo &
Target)
override;
7573 bool checkFormatExpr(
const analyze_printf::PrintfSpecifier &FS,
7574 const char *StartSpecifier,
7575 unsigned SpecifierLen,
7578 bool HandleAmount(
const analyze_format_string::OptionalAmount &Amt,
unsigned k,
7579 const char *startSpecifier,
unsigned specifierLen);
7580 void HandleInvalidAmount(
const analyze_printf::PrintfSpecifier &FS,
7581 const analyze_printf::OptionalAmount &Amt,
7583 const char *startSpecifier,
unsigned specifierLen);
7584 void HandleFlag(
const analyze_printf::PrintfSpecifier &FS,
7585 const analyze_printf::OptionalFlag &flag,
7586 const char *startSpecifier,
unsigned specifierLen);
7587 void HandleIgnoredFlag(
const analyze_printf::PrintfSpecifier &FS,
7588 const analyze_printf::OptionalFlag &ignoredFlag,
7589 const analyze_printf::OptionalFlag &flag,
7590 const char *startSpecifier,
unsigned specifierLen);
7591 bool checkForCStrMembers(
const analyze_printf::ArgType &AT,
7594 void HandleEmptyObjCModifierFlag(
const char *startFlag,
7595 unsigned flagLen)
override;
7597 void HandleInvalidObjCModifierFlag(
const char *startFlag,
7598 unsigned flagLen)
override;
7601 HandleObjCFlagsWithNonObjCConversion(
const char *flagsStart,
7602 const char *flagsEnd,
7603 const char *conversionPosition)
override;
7608class EquatableFormatArgument {
7610 enum SpecifierSensitivity :
unsigned {
7617 enum FormatArgumentRole :
unsigned {
7625 analyze_format_string::ArgType ArgType;
7627 StringRef SpecifierLetter;
7628 CharSourceRange
Range;
7629 SourceLocation ElementLoc;
7630 FormatArgumentRole
Role : 2;
7631 SpecifierSensitivity Sensitivity : 2;
7632 unsigned Position : 14;
7633 unsigned ModifierFor : 14;
7635 void EmitDiagnostic(Sema &S, PartialDiagnostic PDiag,
const Expr *FmtExpr,
7636 bool InFunctionCall)
const;
7639 EquatableFormatArgument(CharSourceRange Range, SourceLocation ElementLoc,
7641 StringRef SpecifierLetter,
7642 analyze_format_string::ArgType ArgType,
7643 FormatArgumentRole
Role,
7644 SpecifierSensitivity Sensitivity,
unsigned Position,
7645 unsigned ModifierFor)
7646 : ArgType(ArgType), LengthMod(LengthMod),
7647 SpecifierLetter(SpecifierLetter),
Range(
Range), ElementLoc(ElementLoc),
7648 Role(
Role), Sensitivity(Sensitivity), Position(Position),
7649 ModifierFor(ModifierFor) {}
7651 unsigned getPosition()
const {
return Position; }
7652 SourceLocation getSourceLocation()
const {
return ElementLoc; }
7654 analyze_format_string::LengthModifier getLengthModifier()
const {
7655 return analyze_format_string::LengthModifier(
nullptr, LengthMod);
7657 void setModifierFor(
unsigned V) { ModifierFor =
V; }
7659 std::string buildFormatSpecifier()
const {
7661 llvm::raw_string_ostream(result)
7662 << getLengthModifier().toString() << SpecifierLetter;
7666 bool VerifyCompatible(Sema &S,
const EquatableFormatArgument &
Other,
7667 const Expr *FmtExpr,
bool InFunctionCall)
const;
7671class DecomposePrintfHandler :
public CheckPrintfHandler {
7672 llvm::SmallVectorImpl<EquatableFormatArgument> &Specs;
7675 DecomposePrintfHandler(Sema &
s,
const FormatStringLiteral *fexpr,
7676 const Expr *origFormatExpr,
7678 unsigned numDataArgs,
bool isObjC,
const char *beg,
7680 ArrayRef<const Expr *> Args,
unsigned formatIdx,
7682 llvm::SmallBitVector &CheckedVarArgs,
7683 UncoveredArgHandler &UncoveredArg,
7684 llvm::SmallVectorImpl<EquatableFormatArgument> &Specs)
7685 : CheckPrintfHandler(
s, fexpr, origFormatExpr,
type, firstDataArg,
7686 numDataArgs,
isObjC, beg, APK, Args, formatIdx,
7687 inFunctionCall, CallType, CheckedVarArgs,
7689 Specs(Specs), HadError(
false) {}
7693 GetSpecifiers(Sema &S,
const FormatStringLiteral *FSL,
const Expr *FmtExpr,
7695 llvm::SmallVectorImpl<EquatableFormatArgument> &Args);
7697 virtual bool HandlePrintfSpecifier(
const analyze_printf::PrintfSpecifier &FS,
7698 const char *startSpecifier,
7699 unsigned specifierLen,
7700 const TargetInfo &
Target)
override;
7705bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
7707 unsigned specifierLen) {
7711 return HandleInvalidConversionSpecifier(FS.
getArgIndex(),
7713 startSpecifier, specifierLen,
7717void CheckPrintfHandler::handleInvalidMaskType(StringRef MaskType) {
7718 S.
Diag(getLocationOfByte(MaskType.data()), diag::err_invalid_mask_type_size);
7726 return T->isRecordType() ||
T->isComplexType();
7729bool CheckPrintfHandler::HandleAmount(
7731 const char *startSpecifier,
unsigned specifierLen) {
7733 if (HasFormatArguments()) {
7735 if (argIndex >= NumDataArgs) {
7736 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_asterisk_missing_arg)
7740 getSpecifierRange(startSpecifier, specifierLen));
7750 CoveredArgs.set(argIndex);
7751 const Expr *Arg = getDataArg(argIndex);
7762 ? diag::err_printf_asterisk_wrong_type
7763 : diag::warn_printf_asterisk_wrong_type;
7764 EmitFormatDiagnostic(S.
PDiag(DiagID)
7769 getSpecifierRange(startSpecifier, specifierLen));
7779void CheckPrintfHandler::HandleInvalidAmount(
7783 const char *startSpecifier,
7784 unsigned specifierLen) {
7794 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_nonsensical_optional_amount)
7798 getSpecifierRange(startSpecifier, specifierLen),
7804 const char *startSpecifier,
7805 unsigned specifierLen) {
7809 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_nonsensical_flag)
7813 getSpecifierRange(startSpecifier, specifierLen),
7818void CheckPrintfHandler::HandleIgnoredFlag(
7822 const char *startSpecifier,
7823 unsigned specifierLen) {
7825 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_ignored_flag)
7829 getSpecifierRange(startSpecifier, specifierLen),
7831 getSpecifierRange(ignoredFlag.
getPosition(), 1)));
7834void CheckPrintfHandler::HandleEmptyObjCModifierFlag(
const char *startFlag,
7837 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_empty_objc_flag),
7838 getLocationOfByte(startFlag),
7840 getSpecifierRange(startFlag, flagLen));
7843void CheckPrintfHandler::HandleInvalidObjCModifierFlag(
const char *startFlag,
7846 auto Range = getSpecifierRange(startFlag, flagLen);
7847 StringRef flag(startFlag, flagLen);
7848 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_invalid_objc_flag) << flag,
7849 getLocationOfByte(startFlag),
7854void CheckPrintfHandler::HandleObjCFlagsWithNonObjCConversion(
7855 const char *flagsStart,
const char *flagsEnd,
const char *conversionPosition) {
7857 auto Range = getSpecifierRange(flagsStart, flagsEnd - flagsStart + 1);
7858 auto diag = diag::warn_printf_ObjCflags_without_ObjCConversion;
7859 EmitFormatDiagnostic(S.
PDiag(
diag) << StringRef(conversionPosition, 1),
7860 getLocationOfByte(conversionPosition),
7866 const Expr *FmtExpr,
7867 bool InFunctionCall)
const {
7868 CheckFormatHandler::EmitFormatDiagnostic(S, InFunctionCall, FmtExpr, PDiag,
7869 ElementLoc,
true, Range);
7872bool EquatableFormatArgument::VerifyCompatible(
7873 Sema &S,
const EquatableFormatArgument &
Other,
const Expr *FmtExpr,
7874 bool InFunctionCall)
const {
7879 S, S.
PDiag(diag::warn_format_cmp_role_mismatch) <<
Role <<
Other.Role,
7880 FmtExpr, InFunctionCall);
7881 S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with) << 0 <<
Other.Range;
7885 if (
Role != FAR_Data) {
7886 if (ModifierFor !=
Other.ModifierFor) {
7889 S.
PDiag(diag::warn_format_cmp_modifierfor_mismatch)
7890 << (ModifierFor + 1) << (
Other.ModifierFor + 1),
7891 FmtExpr, InFunctionCall);
7892 S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with) << 0 <<
Other.Range;
7898 bool HadError =
false;
7899 if (Sensitivity !=
Other.Sensitivity) {
7902 S.
PDiag(diag::warn_format_cmp_sensitivity_mismatch)
7903 << Sensitivity <<
Other.Sensitivity,
7904 FmtExpr, InFunctionCall);
7905 HadError = S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with)
7906 << 0 <<
Other.Range;
7909 switch (ArgType.matchesArgType(S.
Context,
Other.ArgType)) {
7913 case MK::MatchPromotion:
7917 case MK::NoMatchTypeConfusion:
7918 case MK::NoMatchPromotionTypeConfusion:
7920 S.
PDiag(diag::warn_format_cmp_specifier_mismatch)
7921 << buildFormatSpecifier()
7922 <<
Other.buildFormatSpecifier(),
7923 FmtExpr, InFunctionCall);
7924 HadError = S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with)
7925 << 0 <<
Other.Range;
7928 case MK::NoMatchPedantic:
7930 S.
PDiag(diag::warn_format_cmp_specifier_mismatch_pedantic)
7931 << buildFormatSpecifier()
7932 <<
Other.buildFormatSpecifier(),
7933 FmtExpr, InFunctionCall);
7934 HadError = S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with)
7935 << 0 <<
Other.Range;
7938 case MK::NoMatchSignedness:
7940 S.
PDiag(diag::warn_format_cmp_specifier_sign_mismatch)
7941 << buildFormatSpecifier()
7942 <<
Other.buildFormatSpecifier(),
7943 FmtExpr, InFunctionCall);
7944 HadError = S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with)
7945 << 0 <<
Other.Range;
7951bool DecomposePrintfHandler::GetSpecifiers(
7952 Sema &S,
const FormatStringLiteral *FSL,
const Expr *FmtExpr,
7955 StringRef
Data = FSL->getString();
7956 const char *Str =
Data.data();
7957 llvm::SmallBitVector BV;
7958 UncoveredArgHandler UA;
7959 const Expr *PrintfArgs[] = {FSL->getFormatString()};
7960 DecomposePrintfHandler H(S, FSL, FSL->getFormatString(),
Type, 0, 0, IsObjC,
7972 llvm::stable_sort(Args, [](
const EquatableFormatArgument &A,
7973 const EquatableFormatArgument &B) {
7974 return A.getPosition() < B.getPosition();
7979bool DecomposePrintfHandler::HandlePrintfSpecifier(
7982 if (!CheckPrintfHandler::HandlePrintfSpecifier(FS, startSpecifier,
7997 const unsigned Unset = ~0;
7998 unsigned FieldWidthIndex = Unset;
7999 unsigned PrecisionIndex = Unset;
8003 if (!FieldWidth.isInvalid() && FieldWidth.hasDataArgument()) {
8004 FieldWidthIndex = Specs.size();
8005 Specs.emplace_back(getSpecifierRange(startSpecifier, specifierLen),
8006 getLocationOfByte(FieldWidth.getStart()),
8008 FieldWidth.getArgType(S.
Context),
8009 EquatableFormatArgument::FAR_FieldWidth,
8010 EquatableFormatArgument::SS_None,
8011 FieldWidth.usesPositionalArg()
8012 ? FieldWidth.getPositionalArgIndex() - 1
8018 if (!Precision.isInvalid() && Precision.hasDataArgument()) {
8019 PrecisionIndex = Specs.size();
8021 getSpecifierRange(startSpecifier, specifierLen),
8022 getLocationOfByte(Precision.getStart()),
8024 Precision.getArgType(S.
Context), EquatableFormatArgument::FAR_Precision,
8025 EquatableFormatArgument::SS_None,
8026 Precision.usesPositionalArg() ? Precision.getPositionalArgIndex() - 1
8032 unsigned SpecIndex =
8034 if (FieldWidthIndex != Unset)
8035 Specs[FieldWidthIndex].setModifierFor(SpecIndex);
8036 if (PrecisionIndex != Unset)
8037 Specs[PrecisionIndex].setModifierFor(SpecIndex);
8039 EquatableFormatArgument::SpecifierSensitivity Sensitivity;
8041 Sensitivity = EquatableFormatArgument::SS_Private;
8043 Sensitivity = EquatableFormatArgument::SS_Public;
8045 Sensitivity = EquatableFormatArgument::SS_Sensitive;
8047 Sensitivity = EquatableFormatArgument::SS_None;
8050 getSpecifierRange(startSpecifier, specifierLen),
8053 EquatableFormatArgument::FAR_Data, Sensitivity, SpecIndex, 0);
8058 Specs.emplace_back(getSpecifierRange(startSpecifier, specifierLen),
8063 EquatableFormatArgument::FAR_Auxiliary, Sensitivity,
8064 SpecIndex + 1, SpecIndex);
8072template<
typename MemberKind>
8090 if (MemberKind *FK = dyn_cast<MemberKind>(
decl))
8105 for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
8107 if ((*MI)->getMinRequiredArguments() == 0)
8115bool CheckPrintfHandler::checkForCStrMembers(
8122 for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
8125 if (
Method->getMinRequiredArguments() == 0 &&
8138bool CheckPrintfHandler::HandlePrintfSpecifier(
8152 HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()),
8153 startSpecifier, specifierLen);
8161 startSpecifier, specifierLen)) {
8166 startSpecifier, specifierLen)) {
8170 if (!CS.consumesDataArgument()) {
8178 if (argIndex < NumDataArgs) {
8182 CoveredArgs.set(argIndex);
8189 if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex + 1))
8192 if (HasFormatArguments()) {
8194 CoveredArgs.set(argIndex + 1);
8197 const Expr *Ex = getDataArg(argIndex);
8201 : ArgType::CPointerTy;
8203 EmitFormatDiagnostic(
8204 S.
PDiag(diag::warn_format_conversion_argument_type_mismatch)
8208 getSpecifierRange(startSpecifier, specifierLen));
8211 Ex = getDataArg(argIndex + 1);
8214 EmitFormatDiagnostic(
8215 S.
PDiag(diag::warn_format_conversion_argument_type_mismatch)
8219 getSpecifierRange(startSpecifier, specifierLen));
8226 if (!allowsObjCArg() && CS.isObjCArg()) {
8227 return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
8234 return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
8241 EmitFormatDiagnostic(S.
PDiag(diag::warn_os_log_format_narg),
8242 getLocationOfByte(CS.getStart()),
8244 getSpecifierRange(startSpecifier, specifierLen));
8254 return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
8261 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_invalid_annotation)
8265 getSpecifierRange(startSpecifier, specifierLen));
8268 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_invalid_annotation)
8272 getSpecifierRange(startSpecifier, specifierLen));
8276 const llvm::Triple &Triple =
Target.getTriple();
8278 (Triple.isAndroid() || Triple.isOSFuchsia())) {
8279 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_narg_not_supported),
8280 getLocationOfByte(CS.getStart()),
8282 getSpecifierRange(startSpecifier, specifierLen));
8288 startSpecifier, specifierLen);
8294 startSpecifier, specifierLen);
8300 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_P_no_precision),
8301 getLocationOfByte(startSpecifier),
8303 getSpecifierRange(startSpecifier, specifierLen));
8312 HandleFlag(FS, FS.
hasPlusPrefix(), startSpecifier, specifierLen);
8314 HandleFlag(FS, FS.
hasSpacePrefix(), startSpecifier, specifierLen);
8323 startSpecifier, specifierLen);
8326 startSpecifier, specifierLen);
8331 HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
8332 diag::warn_format_nonsensical_length);
8334 HandleNonStandardLengthModifier(FS, startSpecifier, specifierLen);
8336 HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
8337 diag::warn_format_non_standard_conversion_spec);
8340 HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen);
8343 if (!HasFormatArguments())
8346 if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
8349 const Expr *Arg = getDataArg(argIndex);
8353 return checkFormatExpr(FS, startSpecifier, specifierLen, Arg);
8365 case Stmt::ArraySubscriptExprClass:
8366 case Stmt::CallExprClass:
8367 case Stmt::CharacterLiteralClass:
8368 case Stmt::CXXBoolLiteralExprClass:
8369 case Stmt::DeclRefExprClass:
8370 case Stmt::FloatingLiteralClass:
8371 case Stmt::IntegerLiteralClass:
8372 case Stmt::MemberExprClass:
8373 case Stmt::ObjCArrayLiteralClass:
8374 case Stmt::ObjCBoolLiteralExprClass:
8375 case Stmt::ObjCBoxedExprClass:
8376 case Stmt::ObjCDictionaryLiteralClass:
8377 case Stmt::ObjCEncodeExprClass:
8378 case Stmt::ObjCIvarRefExprClass:
8379 case Stmt::ObjCMessageExprClass:
8380 case Stmt::ObjCPropertyRefExprClass:
8381 case Stmt::ObjCStringLiteralClass:
8382 case Stmt::ObjCSubscriptRefExprClass:
8383 case Stmt::ParenExprClass:
8384 case Stmt::StringLiteralClass:
8385 case Stmt::UnaryOperatorClass:
8392static std::pair<QualType, StringRef>
8399 StringRef Name = UserTy->getDecl()->getName();
8400 QualType CastTy = llvm::StringSwitch<QualType>(Name)
8401 .Case(
"CFIndex", Context.getNSIntegerType())
8402 .Case(
"NSInteger", Context.getNSIntegerType())
8403 .Case(
"NSUInteger", Context.getNSUIntegerType())
8404 .Case(
"SInt32", Context.IntTy)
8405 .Case(
"UInt32", Context.UnsignedIntTy)
8409 return std::make_pair(CastTy, Name);
8411 TyTy = UserTy->desugar();
8415 if (
const ParenExpr *PE = dyn_cast<ParenExpr>(E))
8417 PE->getSubExpr()->getType(),
8426 StringRef TrueName, FalseName;
8428 std::tie(TrueTy, TrueName) =
8430 CO->getTrueExpr()->getType(),
8432 std::tie(FalseTy, FalseName) =
8434 CO->getFalseExpr()->getType(),
8435 CO->getFalseExpr());
8437 if (TrueTy == FalseTy)
8438 return std::make_pair(TrueTy, TrueName);
8439 else if (TrueTy.
isNull())
8440 return std::make_pair(FalseTy, FalseName);
8441 else if (FalseTy.
isNull())
8442 return std::make_pair(TrueTy, TrueName);
8445 return std::make_pair(
QualType(), StringRef());
8464 From = VecTy->getElementType();
8466 To = VecTy->getElementType();
8477 diag::warn_format_conversion_argument_type_mismatch_signedness,
8481 diag::warn_format_conversion_argument_type_mismatch, Loc)) {
8490 const char *StartSpecifier,
8491 unsigned SpecifierLen,
8503 while (
const TypeOfExprType *TET = dyn_cast<TypeOfExprType>(ExprTy)) {
8504 ExprTy = TET->getUnderlyingExpr()->getType();
8519 getSpecifierRange(StartSpecifier, SpecifierLen);
8521 llvm::raw_svector_ostream os(FSString);
8523 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_bool_as_character)
8534 getSpecifierRange(StartSpecifier, SpecifierLen);
8535 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_P_with_objc_pointer),
8545 if (
Match == ArgType::Match)
8549 assert(
Match != ArgType::NoMatchPromotionTypeConfusion);
8558 E = ICE->getSubExpr();
8568 if (OrigMatch == ArgType::NoMatchSignedness &&
8569 ImplicitMatch != ArgType::NoMatchSignedness)
8576 if (ImplicitMatch == ArgType::Match)
8594 if (
Match == ArgType::MatchPromotion)
8598 if (
Match == ArgType::MatchPromotion) {
8602 ImplicitMatch != ArgType::NoMatchPromotionTypeConfusion &&
8603 ImplicitMatch != ArgType::NoMatchTypeConfusion)
8607 if (ImplicitMatch == ArgType::NoMatchPedantic ||
8608 ImplicitMatch == ArgType::NoMatchTypeConfusion)
8609 Match = ImplicitMatch;
8610 assert(
Match != ArgType::MatchPromotion);
8613 bool IsEnum =
false;
8614 bool IsScopedEnum =
false;
8617 IntendedTy = ED->getIntegerType();
8618 if (!ED->isScoped()) {
8619 ExprTy = IntendedTy;
8624 IsScopedEnum =
true;
8631 if (isObjCContext() &&
8642 const llvm::APInt &
V = IL->getValue();
8652 if (TD->getUnderlyingType() == IntendedTy)
8662 bool ShouldNotPrintDirectly =
false; StringRef CastTyName;
8670 if (!IsScopedEnum &&
8671 (CastTyName ==
"NSInteger" || CastTyName ==
"NSUInteger") &&
8675 IntendedTy = CastTy;
8676 ShouldNotPrintDirectly =
true;
8681 PrintfSpecifier fixedFS = FS;
8688 llvm::raw_svector_ostream os(buf);
8691 CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);
8693 if (IntendedTy == ExprTy && !ShouldNotPrintDirectly && !IsScopedEnum) {
8699 llvm_unreachable(
"expected non-matching");
8701 Diag = diag::warn_format_conversion_argument_type_mismatch_signedness;
8704 Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
8707 Diag = diag::warn_format_conversion_argument_type_mismatch_confusion;
8710 Diag = diag::warn_format_conversion_argument_type_mismatch;
8731 llvm::raw_svector_ostream CastFix(CastBuf);
8732 CastFix << (S.
LangOpts.CPlusPlus ?
"static_cast<" :
"(");
8734 CastFix << (S.
LangOpts.CPlusPlus ?
">" :
")");
8740 if ((IntendedMatch != ArgType::Match) || ShouldNotPrintDirectly)
8745 SourceRange CastRange(CCast->getLParenLoc(), CCast->getRParenLoc());
8767 if (ShouldNotPrintDirectly && !IsScopedEnum) {
8773 Name = TypedefTy->getDecl()->getName();
8777 ? diag::warn_format_argument_needs_cast_pedantic
8778 : diag::warn_format_argument_needs_cast;
8779 EmitFormatDiagnostic(S.
PDiag(
Diag) << Name << IntendedTy << IsEnum
8790 ? diag::warn_format_conversion_argument_type_mismatch_pedantic
8791 : diag::warn_format_conversion_argument_type_mismatch;
8793 EmitFormatDiagnostic(
8805 bool EmitTypeMismatch =
false;
8815 llvm_unreachable(
"expected non-matching");
8817 Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
8820 Diag = diag::warn_format_conversion_argument_type_mismatch_confusion;
8824 ? diag::err_format_conversion_argument_type_mismatch
8825 : diag::warn_format_conversion_argument_type_mismatch;
8829 EmitFormatDiagnostic(
8838 EmitTypeMismatch =
true;
8840 EmitFormatDiagnostic(
8841 S.
PDiag(diag::warn_non_pod_vararg_with_format_string)
8842 << S.
getLangOpts().CPlusPlus11 << ExprTy << CallType
8846 checkForCStrMembers(AT, E);
8852 EmitTypeMismatch =
true;
8854 EmitFormatDiagnostic(
8855 S.
PDiag(diag::err_cannot_pass_objc_interface_to_vararg_format)
8856 << S.
getLangOpts().CPlusPlus11 << ExprTy << CallType
8869 if (EmitTypeMismatch) {
8875 EmitFormatDiagnostic(
8876 S.
PDiag(diag::warn_format_conversion_argument_type_mismatch)
8882 assert(FirstDataArg + FS.
getArgIndex() < CheckedVarArgs.size() &&
8883 "format string specifier index out of range");
8884 CheckedVarArgs[FirstDataArg + FS.
getArgIndex()] =
true;
8894class CheckScanfHandler :
public CheckFormatHandler {
8896 CheckScanfHandler(Sema &
s,
const FormatStringLiteral *fexpr,
8898 unsigned firstDataArg,
unsigned numDataArgs,
8900 ArrayRef<const Expr *> Args,
unsigned formatIdx,
8902 llvm::SmallBitVector &CheckedVarArgs,
8903 UncoveredArgHandler &UncoveredArg)
8904 : CheckFormatHandler(
s, fexpr, origFormatExpr,
type, firstDataArg,
8905 numDataArgs, beg, APK, Args, formatIdx,
8906 inFunctionCall, CallType, CheckedVarArgs,
8909 bool HandleScanfSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
8910 const char *startSpecifier,
8911 unsigned specifierLen)
override;
8913 bool HandleInvalidScanfConversionSpecifier(
8914 const analyze_scanf::ScanfSpecifier &FS,
8915 const char *startSpecifier,
8916 unsigned specifierLen)
override;
8918 void HandleIncompleteScanList(
const char *start,
const char *end)
override;
8923void CheckScanfHandler::HandleIncompleteScanList(
const char *start,
8925 EmitFormatDiagnostic(S.
PDiag(diag::warn_scanf_scanlist_incomplete),
8926 getLocationOfByte(end),
true,
8927 getSpecifierRange(start, end - start));
8930bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier(
8932 const char *startSpecifier,
8933 unsigned specifierLen) {
8937 return HandleInvalidConversionSpecifier(FS.
getArgIndex(),
8939 startSpecifier, specifierLen,
8943bool CheckScanfHandler::HandleScanfSpecifier(
8945 const char *startSpecifier,
8946 unsigned specifierLen) {
8960 HandlePositionalNonpositionalArgs(getLocationOfByte(CS.
getStart()),
8961 startSpecifier, specifierLen);
8972 EmitFormatDiagnostic(S.
PDiag(diag::warn_scanf_nonzero_width),
8987 if (argIndex < NumDataArgs) {
8991 CoveredArgs.set(argIndex);
8997 HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
8998 diag::warn_format_nonsensical_length);
9000 HandleNonStandardLengthModifier(FS, startSpecifier, specifierLen);
9002 HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
9003 diag::warn_format_non_standard_conversion_spec);
9006 HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen);
9009 if (!HasFormatArguments())
9012 if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
9016 const Expr *Ex = getDataArg(argIndex);
9034 ScanfSpecifier fixedFS = FS;
9039 Pedantic ? diag::warn_format_conversion_argument_type_mismatch_pedantic
9041 ? diag::warn_format_conversion_argument_type_mismatch_signedness
9042 : diag::warn_format_conversion_argument_type_mismatch;
9047 llvm::raw_svector_ostream os(buf);
9050 EmitFormatDiagnostic(
9055 getSpecifierRange(startSpecifier, specifierLen),
9057 getSpecifierRange(startSpecifier, specifierLen), os.str()));
9064 getSpecifierRange(startSpecifier, specifierLen));
9074 const Expr *FmtExpr,
bool InFunctionCall) {
9075 bool HadError =
false;
9076 auto FmtIter = FmtArgs.begin(), FmtEnd = FmtArgs.end();
9077 auto RefIter = RefArgs.begin(), RefEnd = RefArgs.end();
9078 while (FmtIter < FmtEnd && RefIter < RefEnd) {
9090 for (; FmtIter < FmtEnd; ++FmtIter) {
9094 if (FmtIter->getPosition() < RefIter->getPosition())
9098 if (FmtIter->getPosition() > RefIter->getPosition())
9102 !FmtIter->VerifyCompatible(S, *RefIter, FmtExpr, InFunctionCall);
9106 RefIter = std::find_if(RefIter + 1, RefEnd, [=](
const auto &Arg) {
9107 return Arg.getPosition() != RefIter->getPosition();
9111 if (FmtIter < FmtEnd) {
9112 CheckFormatHandler::EmitFormatDiagnostic(
9113 S, InFunctionCall, FmtExpr,
9114 S.
PDiag(diag::warn_format_cmp_specifier_arity) << 1,
9115 FmtExpr->
getBeginLoc(),
false, FmtIter->getSourceRange());
9116 HadError = S.
Diag(Ref->
getBeginLoc(), diag::note_format_cmp_with) << 1;
9117 }
else if (RefIter < RefEnd) {
9118 CheckFormatHandler::EmitFormatDiagnostic(
9119 S, InFunctionCall, FmtExpr,
9120 S.
PDiag(diag::warn_format_cmp_specifier_arity) << 0,
9123 << 1 << RefIter->getSourceRange();
9129 Sema &S,
const FormatStringLiteral *FExpr,
9134 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
9135 bool IgnoreStringsWithoutSpecifiers) {
9137 if (!FExpr->isAscii() && !FExpr->isUTF8()) {
9138 CheckFormatHandler::EmitFormatDiagnostic(
9139 S, inFunctionCall, Args[format_idx],
9140 S.
PDiag(diag::warn_format_string_is_wide_literal), FExpr->getBeginLoc(),
9146 StringRef StrRef = FExpr->getString();
9147 const char *Str = StrRef.data();
9151 assert(
T &&
"String literal not of constant array type!");
9152 size_t TypeSize =
T->getZExtSize();
9153 size_t StrLen = std::min(std::max(TypeSize,
size_t(1)) - 1, StrRef.size());
9154 const unsigned numDataArgs = Args.size() - firstDataArg;
9156 if (IgnoreStringsWithoutSpecifiers &&
9163 if (TypeSize <= StrRef.size() && !StrRef.substr(0, TypeSize).contains(
'\0')) {
9164 CheckFormatHandler::EmitFormatDiagnostic(
9165 S, inFunctionCall, Args[format_idx],
9166 S.
PDiag(diag::warn_printf_format_string_not_null_terminated),
9167 FExpr->getBeginLoc(),
9173 if (StrLen == 0 && numDataArgs > 0) {
9174 CheckFormatHandler::EmitFormatDiagnostic(
9175 S, inFunctionCall, Args[format_idx],
9176 S.
PDiag(diag::warn_empty_format_string), FExpr->getBeginLoc(),
9187 if (ReferenceFormatString ==
nullptr) {
9188 CheckPrintfHandler H(S, FExpr, OrigFormatExpr,
Type, firstDataArg,
9189 numDataArgs, IsObjC, Str, APK, Args, format_idx,
9190 inFunctionCall, CallType, CheckedVarArgs,
9200 Type, ReferenceFormatString, FExpr->getFormatString(),
9201 inFunctionCall ?
nullptr : Args[format_idx]);
9204 CheckScanfHandler H(S, FExpr, OrigFormatExpr,
Type, firstDataArg,
9205 numDataArgs, Str, APK, Args, format_idx, inFunctionCall,
9206 CallType, CheckedVarArgs, UncoveredArg);
9226 FormatStringLiteral RefLit = AuthoritativeFormatString;
9227 FormatStringLiteral TestLit = TestedFormatString;
9229 bool DiagAtStringLiteral;
9230 if (FunctionCallArg) {
9231 Arg = FunctionCallArg;
9232 DiagAtStringLiteral =
false;
9234 Arg = TestedFormatString;
9235 DiagAtStringLiteral =
true;
9237 if (DecomposePrintfHandler::GetSpecifiers(*
this, &RefLit,
9238 AuthoritativeFormatString,
Type,
9239 IsObjC,
true, RefArgs) &&
9240 DecomposePrintfHandler::GetSpecifiers(*
this, &TestLit, Arg,
Type, IsObjC,
9241 DiagAtStringLiteral, FmtArgs)) {
9243 TestedFormatString, FmtArgs, Arg,
9244 DiagAtStringLiteral);
9257 FormatStringLiteral RefLit = Str;
9261 if (!DecomposePrintfHandler::GetSpecifiers(*
this, &RefLit, Str,
Type, IsObjC,
9270 bool HadError =
false;
9271 auto Iter = Args.begin();
9272 auto End = Args.end();
9273 while (Iter != End) {
9274 const auto &FirstInGroup = *Iter;
9276 Iter != End && Iter->getPosition() == FirstInGroup.getPosition();
9278 HadError |= !Iter->VerifyCompatible(*
this, FirstInGroup, Str,
true);
9287 const char *Str = StrRef.data();
9290 assert(
T &&
"String literal not of constant array type!");
9291 size_t TypeSize =
T->getZExtSize();
9292 size_t StrLen = std::min(std::max(TypeSize,
size_t(1)) - 1, StrRef.size());
9303 switch (AbsFunction) {
9307 case Builtin::BI__builtin_abs:
9308 return Builtin::BI__builtin_labs;
9309 case Builtin::BI__builtin_labs:
9310 return Builtin::BI__builtin_llabs;
9311 case Builtin::BI__builtin_llabs:
9314 case Builtin::BI__builtin_fabsf:
9315 return Builtin::BI__builtin_fabs;
9316 case Builtin::BI__builtin_fabs:
9317 return Builtin::BI__builtin_fabsl;
9318 case Builtin::BI__builtin_fabsl:
9321 case Builtin::BI__builtin_cabsf:
9322 return Builtin::BI__builtin_cabs;
9323 case Builtin::BI__builtin_cabs:
9324 return Builtin::BI__builtin_cabsl;
9325 case Builtin::BI__builtin_cabsl:
9328 case Builtin::BIabs:
9329 return Builtin::BIlabs;
9330 case Builtin::BIlabs:
9331 return Builtin::BIllabs;
9332 case Builtin::BIllabs:
9335 case Builtin::BIfabsf:
9336 return Builtin::BIfabs;
9337 case Builtin::BIfabs:
9338 return Builtin::BIfabsl;
9339 case Builtin::BIfabsl:
9342 case Builtin::BIcabsf:
9343 return Builtin::BIcabs;
9344 case Builtin::BIcabs:
9345 return Builtin::BIcabsl;
9346 case Builtin::BIcabsl:
9375 unsigned AbsFunctionKind) {
9376 unsigned BestKind = 0;
9377 uint64_t ArgSize = Context.getTypeSize(ArgType);
9378 for (
unsigned Kind = AbsFunctionKind; Kind != 0;
9381 if (Context.getTypeSize(ParamType) >= ArgSize) {
9384 else if (Context.hasSameType(ParamType, ArgType)) {
9400 if (
T->isIntegralOrEnumerationType())
9402 if (
T->isRealFloatingType())
9404 if (
T->isAnyComplexType())
9407 llvm_unreachable(
"Type not integer, floating, or complex");
9414 switch (ValueKind) {
9419 case Builtin::BI__builtin_fabsf:
9420 case Builtin::BI__builtin_fabs:
9421 case Builtin::BI__builtin_fabsl:
9422 case Builtin::BI__builtin_cabsf:
9423 case Builtin::BI__builtin_cabs:
9424 case Builtin::BI__builtin_cabsl:
9425 return Builtin::BI__builtin_abs;
9426 case Builtin::BIfabsf:
9427 case Builtin::BIfabs:
9428 case Builtin::BIfabsl:
9429 case Builtin::BIcabsf:
9430 case Builtin::BIcabs:
9431 case Builtin::BIcabsl:
9432 return Builtin::BIabs;
9438 case Builtin::BI__builtin_abs:
9439 case Builtin::BI__builtin_labs:
9440 case Builtin::BI__builtin_llabs:
9441 case Builtin::BI__builtin_cabsf:
9442 case Builtin::BI__builtin_cabs:
9443 case Builtin::BI__builtin_cabsl:
9444 return Builtin::BI__builtin_fabsf;
9445 case Builtin::BIabs:
9446 case Builtin::BIlabs:
9447 case Builtin::BIllabs:
9448 case Builtin::BIcabsf:
9449 case Builtin::BIcabs:
9450 case Builtin::BIcabsl:
9451 return Builtin::BIfabsf;
9457 case Builtin::BI__builtin_abs:
9458 case Builtin::BI__builtin_labs:
9459 case Builtin::BI__builtin_llabs:
9460 case Builtin::BI__builtin_fabsf:
9461 case Builtin::BI__builtin_fabs:
9462 case Builtin::BI__builtin_fabsl:
9463 return Builtin::BI__builtin_cabsf;
9464 case Builtin::BIabs:
9465 case Builtin::BIlabs:
9466 case Builtin::BIllabs:
9467 case Builtin::BIfabsf:
9468 case Builtin::BIfabs:
9469 case Builtin::BIfabsl:
9470 return Builtin::BIcabsf;
9473 llvm_unreachable(
"Unable to convert function");
9484 case Builtin::BI__builtin_abs:
9485 case Builtin::BI__builtin_fabs:
9486 case Builtin::BI__builtin_fabsf:
9487 case Builtin::BI__builtin_fabsl:
9488 case Builtin::BI__builtin_labs:
9489 case Builtin::BI__builtin_llabs:
9490 case Builtin::BI__builtin_cabs:
9491 case Builtin::BI__builtin_cabsf:
9492 case Builtin::BI__builtin_cabsl:
9493 case Builtin::BIabs:
9494 case Builtin::BIlabs:
9495 case Builtin::BIllabs:
9496 case Builtin::BIfabs:
9497 case Builtin::BIfabsf:
9498 case Builtin::BIfabsl:
9499 case Builtin::BIcabs:
9500 case Builtin::BIcabsf:
9501 case Builtin::BIcabsl:
9504 llvm_unreachable(
"Unknown Builtin type");
9510 unsigned AbsKind,
QualType ArgType) {
9511 bool EmitHeaderHint =
true;
9512 const char *HeaderName =
nullptr;
9513 std::string FunctionName;
9514 if (S.
getLangOpts().CPlusPlus && !ArgType->isAnyComplexType()) {
9515 FunctionName =
"std::abs";
9516 if (ArgType->isIntegralOrEnumerationType()) {
9517 HeaderName =
"cstdlib";
9518 }
else if (ArgType->isRealFloatingType()) {
9519 HeaderName =
"cmath";
9521 llvm_unreachable(
"Invalid Type");
9530 for (
const auto *I : R) {
9533 FDecl = dyn_cast<FunctionDecl>(UsingD->getTargetDecl());
9535 FDecl = dyn_cast<FunctionDecl>(I);
9550 EmitHeaderHint =
false;
9568 EmitHeaderHint =
false;
9572 }
else if (!R.
empty()) {
9578 S.
Diag(Loc, diag::note_replace_abs_function)
9584 if (!EmitHeaderHint)
9587 S.
Diag(Loc, diag::note_include_header_or_declare) << HeaderName
9591template <std::
size_t StrLen>
9593 const char (&Str)[StrLen]) {
9606 auto MatchesAny = [&](std::initializer_list<llvm::StringRef> names) {
9607 return llvm::is_contained(names, calleeName);
9612 return MatchesAny({
"__builtin_nan",
"__builtin_nanf",
"__builtin_nanl",
9613 "__builtin_nanf16",
"__builtin_nanf128"});
9615 return MatchesAny({
"__builtin_inf",
"__builtin_inff",
"__builtin_infl",
9616 "__builtin_inff16",
"__builtin_inff128"});
9618 llvm_unreachable(
"unknown MathCheck");
9622 if (FDecl->
getName() !=
"infinity")
9625 if (
const CXXMethodDecl *MDecl = dyn_cast<CXXMethodDecl>(FDecl)) {
9627 if (RDecl->
getName() !=
"numeric_limits")
9644 if (FPO.getNoHonorNaNs() &&
9647 Diag(
Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
9648 << 1 << 0 <<
Call->getSourceRange();
9652 if (FPO.getNoHonorInfs() &&
9656 Diag(
Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
9657 << 0 << 0 <<
Call->getSourceRange();
9661void Sema::CheckAbsoluteValueFunction(
const CallExpr *
Call,
9663 if (
Call->getNumArgs() != 1)
9668 if (AbsKind == 0 && !IsStdAbs)
9671 QualType ArgType =
Call->getArg(0)->IgnoreParenImpCasts()->getType();
9672 QualType ParamType =
Call->getArg(0)->getType();
9677 std::string FunctionName =
9678 IsStdAbs ?
"std::abs" :
Context.BuiltinInfo.getName(AbsKind);
9679 Diag(
Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType;
9680 Diag(
Call->getExprLoc(), diag::note_remove_abs)
9709 if (ArgValueKind == ParamValueKind) {
9710 if (
Context.getTypeSize(ArgType) <=
Context.getTypeSize(ParamType))
9714 Diag(
Call->getExprLoc(), diag::warn_abs_too_small)
9715 << FDecl << ArgType << ParamType;
9717 if (NewAbsKind == 0)
9721 Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
9730 if (NewAbsKind == 0)
9733 Diag(
Call->getExprLoc(), diag::warn_wrong_absolute_value_type)
9734 << FDecl << ParamValueKind << ArgValueKind;
9737 Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
9743 if (!
Call || !FDecl)
return;
9747 if (
Call->getExprLoc().isMacroID())
return;
9750 if (
Call->getNumArgs() != 2)
return;
9753 if (!ArgList)
return;
9754 if (ArgList->size() != 1)
return;
9757 const auto& TA = ArgList->
get(0);
9759 QualType ArgType = TA.getAsType();
9763 auto IsLiteralZeroArg = [](
const Expr* E) ->
bool {
9764 const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);
9765 if (!MTE)
return false;
9766 const auto *
Num = dyn_cast<IntegerLiteral>(MTE->getSubExpr());
9767 if (!
Num)
return false;
9768 if (
Num->getValue() != 0)
return false;
9772 const Expr *FirstArg =
Call->getArg(0);
9773 const Expr *SecondArg =
Call->getArg(1);
9774 const bool IsFirstArgZero = IsLiteralZeroArg(FirstArg);
9775 const bool IsSecondArgZero = IsLiteralZeroArg(SecondArg);
9778 if (IsFirstArgZero == IsSecondArgZero)
return;
9783 SourceRange ZeroRange = IsFirstArgZero ? FirstRange : SecondRange;
9785 Diag(
Call->getExprLoc(), diag::warn_max_unsigned_zero)
9786 << IsFirstArgZero <<
Call->getCallee()->getSourceRange() << ZeroRange;
9789 SourceRange RemovalRange;
9790 if (IsFirstArgZero) {
9791 RemovalRange = SourceRange(FirstRange.
getBegin(),
9798 Diag(
Call->getExprLoc(), diag::note_remove_max_call)
9813 const auto *Size = dyn_cast<BinaryOperator>(E);
9818 if (!Size->isComparisonOp() && !Size->isLogicalOp())
9822 S.
Diag(Size->getOperatorLoc(), diag::warn_memsize_comparison)
9823 << SizeRange << FnName;
9824 S.
Diag(FnLoc, diag::note_memsize_comparison_paren)
9829 S.
Diag(SizeRange.
getBegin(), diag::note_memsize_comparison_cast_silence)
9840 bool &IsContained) {
9842 const Type *Ty =
T->getBaseElementTypeUnsafe();
9843 IsContained =
false;
9856 for (
auto *FD : RD->
fields()) {
9869 if (
const auto *Unary = dyn_cast<UnaryExprOrTypeTraitExpr>(E))
9870 if (Unary->getKind() == UETT_SizeOf)
9879 if (!
SizeOf->isArgumentType())
9880 return SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
9887 return SizeOf->getTypeOfArgument();
9893struct SearchNonTrivialToInitializeField
9896 DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField>;
9898 SearchNonTrivialToInitializeField(
const Expr *E, Sema &S) : E(E), S(S) {}
9901 SourceLocation SL) {
9902 if (
const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
9903 asDerived().visitArray(PDIK, AT, SL);
9907 Super::visitWithKind(PDIK, FT, SL);
9910 void visitARCStrong(QualType FT, SourceLocation SL) {
9913 void visitARCWeak(QualType FT, SourceLocation SL) {
9916 void visitStruct(QualType FT, SourceLocation SL) {
9921 const ArrayType *AT, SourceLocation SL) {
9922 visit(getContext().getBaseElementType(AT), SL);
9924 void visitTrivial(QualType FT, SourceLocation SL) {}
9926 static void diag(QualType RT,
const Expr *E, Sema &S) {
9927 SearchNonTrivialToInitializeField(E, S).visitStruct(RT, SourceLocation());
9936struct SearchNonTrivialToCopyField
9938 using Super = CopiedTypeVisitor<SearchNonTrivialToCopyField, false>;
9940 SearchNonTrivialToCopyField(
const Expr *E, Sema &S) : E(E), S(S) {}
9943 SourceLocation SL) {
9944 if (
const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
9945 asDerived().visitArray(PCK, AT, SL);
9949 Super::visitWithKind(PCK, FT, SL);
9952 void visitARCStrong(QualType FT, SourceLocation SL) {
9955 void visitARCWeak(QualType FT, SourceLocation SL) {
9958 void visitPtrAuth(QualType FT, SourceLocation SL) {
9961 void visitStruct(QualType FT, SourceLocation SL) {
9966 SourceLocation SL) {
9967 visit(getContext().getBaseElementType(AT), SL);
9970 SourceLocation SL) {}
9971 void visitTrivial(QualType FT, SourceLocation SL) {}
9972 void visitVolatileTrivial(QualType FT, SourceLocation SL) {}
9974 static void diag(QualType RT,
const Expr *E, Sema &S) {
9975 SearchNonTrivialToCopyField(E, S).visitStruct(RT, SourceLocation());
9990 if (
const auto *BO = dyn_cast<BinaryOperator>(SizeofExpr)) {
9991 if (BO->getOpcode() != BO_Mul && BO->getOpcode() != BO_Add)
10015 return SM.getFileID(CallLoc) !=
SM.getFileID(ArgLoc);
10017 return SM.getFileID(
SM.getImmediateMacroCallerLoc(CallLoc)) !=
10018 SM.getFileID(
SM.getImmediateMacroCallerLoc(ArgLoc));
10024 if (BId != Builtin::BImemset && BId != Builtin::BIbzero)
10027 const Expr *SizeArg =
10028 Call->getArg(BId == Builtin::BImemset ? 2 : 1)->IgnoreImpCasts();
10030 auto isLiteralZero = [](
const Expr *E) {
10040 if (isLiteralZero(SizeArg) &&
10047 if (BId == Builtin::BIbzero ||
10050 S.
Diag(DiagLoc, diag::warn_suspicious_bzero_size);
10051 S.
Diag(DiagLoc, diag::note_suspicious_bzero_size_silence);
10052 }
else if (!isLiteralZero(
Call->getArg(1)->IgnoreImpCasts())) {
10053 S.
Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 0;
10054 S.
Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 0;
10062 if (BId == Builtin::BImemset &&
10066 S.
Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 1;
10067 S.
Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 1;
10072void Sema::CheckMemaccessArguments(
const CallExpr *
Call,
10079 unsigned ExpectedNumArgs =
10080 (BId == Builtin::BIstrndup || BId == Builtin::BIbzero ? 2 : 3);
10081 if (
Call->getNumArgs() < ExpectedNumArgs)
10084 unsigned LastArg = (BId == Builtin::BImemset || BId == Builtin::BIbzero ||
10085 BId == Builtin::BIstrndup ? 1 : 2);
10087 (BId == Builtin::BIbzero || BId == Builtin::BIstrndup ? 1 : 2);
10088 const Expr *LenExpr =
Call->getArg(LenArg)->IgnoreParenImpCasts();
10091 Call->getBeginLoc(),
Call->getRParenLoc()))
10100 llvm::FoldingSetNodeID SizeOfArgID;
10105 QualType FirstArgTy =
Call->getArg(0)->IgnoreParenImpCasts()->getType();
10106 if (BId == Builtin::BIbzero && !FirstArgTy->
getAs<PointerType>())
10109 for (
unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) {
10110 const Expr *Dest =
Call->getArg(ArgIdx)->IgnoreParenImpCasts();
10111 SourceRange ArgRange =
Call->getArg(ArgIdx)->getSourceRange();
10113 QualType DestTy = Dest->
getType();
10114 QualType PointeeTy;
10115 if (
const PointerType *DestPtrTy = DestTy->
getAs<PointerType>()) {
10128 !
Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess,
10132 if (SizeOfArgID == llvm::FoldingSetNodeID())
10134 llvm::FoldingSetNodeID DestID;
10136 if (DestID == SizeOfArgID) {
10139 unsigned ActionIdx = 0;
10140 StringRef ReadableName = FnName->
getName();
10142 if (
const UnaryOperator *UnaryOp = dyn_cast<UnaryOperator>(Dest))
10143 if (UnaryOp->getOpcode() == UO_AddrOf)
10152 SourceLocation SL = SizeOfArg->
getExprLoc();
10157 if (
SM.isMacroArgExpansion(SL)) {
10159 SL =
SM.getSpellingLoc(SL);
10160 DSR = SourceRange(
SM.getSpellingLoc(DSR.
getBegin()),
10162 SSR = SourceRange(
SM.getSpellingLoc(SSR.
getBegin()),
10167 PDiag(diag::warn_sizeof_pointer_expr_memaccess)
10174 PDiag(diag::warn_sizeof_pointer_expr_memaccess_note)
10185 if (SizeOfArgTy != QualType()) {
10187 Context.typesAreCompatible(SizeOfArgTy, DestTy)) {
10189 PDiag(diag::warn_sizeof_pointer_type_memaccess)
10190 << FnName << SizeOfArgTy << ArgIdx
10197 PointeeTy = DestTy;
10200 if (PointeeTy == QualType())
10205 if (
const CXXRecordDecl *ContainedRD =
10208 unsigned OperationType = 0;
10209 const bool IsCmp = BId == Builtin::BImemcmp || BId == Builtin::BIbcmp;
10212 if (ArgIdx != 0 || IsCmp) {
10213 if (BId == Builtin::BImemcpy)
10215 else if(BId == Builtin::BImemmove)
10222 PDiag(diag::warn_dyn_class_memaccess)
10223 << (IsCmp ? ArgIdx + 2 : ArgIdx) << FnName
10224 << IsContained << ContainedRD << OperationType
10225 <<
Call->getCallee()->getSourceRange());
10227 BId != Builtin::BImemset)
10230 PDiag(diag::warn_arc_object_memaccess)
10231 << ArgIdx << FnName << PointeeTy
10232 <<
Call->getCallee()->getSourceRange());
10239 bool NonTriviallyCopyableCXXRecord =
10243 if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
10246 PDiag(diag::warn_cstruct_memaccess)
10247 << ArgIdx << FnName << PointeeTy << 0);
10248 SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *
this);
10249 }
else if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
10250 NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
10254 PDiag(diag::warn_cxxstruct_memaccess)
10255 << FnName << PointeeTy);
10256 }
else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
10259 PDiag(diag::warn_cstruct_memaccess)
10260 << ArgIdx << FnName << PointeeTy << 1);
10261 SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *
this);
10262 }
else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
10263 NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
10267 PDiag(diag::warn_cxxstruct_memaccess)
10268 << FnName << PointeeTy);
10277 PDiag(diag::note_bad_memaccess_silence)
10313 if (CAT->getZExtSize() <= 1)
10321void Sema::CheckStrlcpycatArguments(
const CallExpr *
Call,
10325 unsigned NumArgs =
Call->getNumArgs();
10326 if ((NumArgs != 3) && (NumArgs != 4))
10331 const Expr *CompareWithSrc =
nullptr;
10334 Call->getBeginLoc(),
Call->getRParenLoc()))
10339 CompareWithSrc = Ex;
10342 if (
const CallExpr *SizeCall = dyn_cast<CallExpr>(SizeArg)) {
10343 if (SizeCall->getBuiltinCallee() == Builtin::BIstrlen &&
10344 SizeCall->getNumArgs() == 1)
10349 if (!CompareWithSrc)
10356 const DeclRefExpr *SrcArgDRE = dyn_cast<DeclRefExpr>(SrcArg);
10360 const DeclRefExpr *CompareWithSrcDRE = dyn_cast<DeclRefExpr>(CompareWithSrc);
10361 if (!CompareWithSrcDRE ||
10365 const Expr *OriginalSizeArg =
Call->getArg(2);
10366 Diag(CompareWithSrcDRE->
getBeginLoc(), diag::warn_strlcpycat_wrong_size)
10373 const Expr *DstArg =
Call->getArg(0)->IgnoreParenImpCasts();
10377 SmallString<128> sizeString;
10378 llvm::raw_svector_ostream
OS(sizeString);
10383 Diag(OriginalSizeArg->
getBeginLoc(), diag::note_strlcpycat_wrong_size)
10390 if (
const DeclRefExpr *D1 = dyn_cast_or_null<DeclRefExpr>(E1))
10391 if (
const DeclRefExpr *D2 = dyn_cast_or_null<DeclRefExpr>(E2))
10392 return D1->getDecl() == D2->getDecl();
10397 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
10406void Sema::CheckStrncatArguments(
const CallExpr *CE,
10421 unsigned PatternType = 0;
10429 }
else if (
const BinaryOperator *BE = dyn_cast<BinaryOperator>(LenArg)) {
10430 if (BE->getOpcode() == BO_Sub) {
10431 const Expr *L = BE->getLHS()->IgnoreParenCasts();
10432 const Expr *R = BE->getRHS()->IgnoreParenCasts();
10443 if (PatternType == 0)
10452 if (
SM.isMacroArgExpansion(SL)) {
10453 SL =
SM.getSpellingLoc(SL);
10454 SR = SourceRange(
SM.getSpellingLoc(SR.
getBegin()),
10459 QualType DstTy = DstArg->
getType();
10462 if (!isKnownSizeArray) {
10463 if (PatternType == 1)
10464 Diag(SL, diag::warn_strncat_wrong_size) << SR;
10466 Diag(SL, diag::warn_strncat_src_size) << SR;
10470 if (PatternType == 1)
10471 Diag(SL, diag::warn_strncat_large_size) << SR;
10473 Diag(SL, diag::warn_strncat_src_size) << SR;
10475 SmallString<128> sizeString;
10476 llvm::raw_svector_ostream
OS(sizeString);
10484 Diag(SL, diag::note_strncat_wrong_size)
10489void CheckFreeArgumentsOnLvalue(
Sema &S,
const std::string &CalleeName,
10498void CheckFreeArgumentsAddressof(
Sema &S,
const std::string &CalleeName,
10500 if (
const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->
getSubExpr())) {
10501 const Decl *D = Lvalue->getDecl();
10502 if (
const auto *DD = dyn_cast<DeclaratorDecl>(D)) {
10503 if (!DD->getType()->isReferenceType())
10504 return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
10508 if (
const auto *Lvalue = dyn_cast<MemberExpr>(UnaryExpr->
getSubExpr()))
10509 return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr,
10510 Lvalue->getMemberDecl());
10513void CheckFreeArgumentsPlus(
Sema &S,
const std::string &CalleeName,
10515 const auto *Lambda = dyn_cast<LambdaExpr>(
10520 S.
Diag(Lambda->getBeginLoc(), diag::warn_free_nonheap_object)
10521 << CalleeName << 2 ;
10524void CheckFreeArgumentsStackArray(
Sema &S,
const std::string &CalleeName,
10526 const auto *Var = dyn_cast<VarDecl>(Lvalue->
getDecl());
10527 if (Var ==
nullptr)
10531 << CalleeName << 0 << Var;
10534void CheckFreeArgumentsCast(
Sema &S,
const std::string &CalleeName,
10537 llvm::raw_svector_ostream
OS(SizeString);
10540 if (Kind == clang::CK_BitCast &&
10541 !
Cast->getSubExpr()->getType()->isFunctionPointerType())
10543 if (Kind == clang::CK_IntegralToPointer &&
10545 Cast->getSubExpr()->IgnoreParenImpCasts()->IgnoreParens()))
10548 switch (
Cast->getCastKind()) {
10549 case clang::CK_BitCast:
10550 case clang::CK_IntegralToPointer:
10551 case clang::CK_FunctionToPointerDecay:
10560 S.
Diag(
Cast->getBeginLoc(), diag::warn_free_nonheap_object)
10561 << CalleeName << 0 <<
OS.str();
10565void Sema::CheckFreeArguments(
const CallExpr *E) {
10566 const std::string CalleeName =
10571 if (
const auto *UnaryExpr = dyn_cast<UnaryOperator>(Arg))
10573 case UnaryOperator::Opcode::UO_AddrOf:
10574 return CheckFreeArgumentsAddressof(*
this, CalleeName, UnaryExpr);
10575 case UnaryOperator::Opcode::UO_Plus:
10576 return CheckFreeArgumentsPlus(*
this, CalleeName, UnaryExpr);
10581 if (
const auto *Lvalue = dyn_cast<DeclRefExpr>(Arg))
10583 return CheckFreeArgumentsStackArray(*
this, CalleeName, Lvalue);
10585 if (
const auto *Label = dyn_cast<AddrLabelExpr>(Arg)) {
10586 Diag(Label->getBeginLoc(), diag::warn_free_nonheap_object)
10587 << CalleeName << 0 << Label->getLabel()->getIdentifier();
10593 << CalleeName << 1 ;
10598 if (
const auto *Cast = dyn_cast<CastExpr>(E->
getArg(0)))
10599 return CheckFreeArgumentsCast(*
this, CalleeName, Cast);
10603Sema::CheckReturnValExpr(
Expr *RetValExp,
QualType lhsType,
10612 Diag(ReturnLoc, diag::warn_null_ret)
10622 if (Op == OO_New || Op == OO_Array_New) {
10623 const FunctionProtoType *Proto
10627 Diag(ReturnLoc, diag::warn_operator_new_returns_null)
10633 Diag(ReturnLoc, diag::err_wasm_table_art) << 1;
10638 if (
Context.getTargetInfo().getTriple().isPPC64())
10650 auto getCastAndLiteral = [&FPLiteral, &FPCast](
const Expr *L,
const Expr *R) {
10651 FPLiteral = dyn_cast<FloatingLiteral>(L->IgnoreParens());
10653 return FPLiteral && FPCast;
10656 if (getCastAndLiteral(LHS, RHS) || getCastAndLiteral(RHS, LHS)) {
10662 llvm::APFloat TargetC = FPLiteral->
getValue();
10663 TargetC.convert(
Context.getFloatTypeSemantics(
QualType(SourceTy, 0)),
10664 llvm::APFloat::rmNearestTiesToEven, &Lossy);
10668 Diag(Loc, diag::warn_float_compare_literal)
10669 << (Opcode == BO_EQ) <<
QualType(SourceTy, 0)
10682 if (
const auto *DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen))
10683 if (
const auto *DRR = dyn_cast<DeclRefExpr>(RightExprSansParen))
10684 if (DRL->getDecl() == DRR->getDecl())
10692 if (
const auto *FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) {
10693 if (FLL->isExact())
10695 }
else if (
const auto *FLR = dyn_cast<FloatingLiteral>(RightExprSansParen))
10696 if (FLR->isExact())
10700 if (
const auto *
CL = dyn_cast<CallExpr>(LeftExprSansParen);
10701 CL &&
CL->getBuiltinCallee())
10704 if (
const auto *CR = dyn_cast<CallExpr>(RightExprSansParen);
10705 CR && CR->getBuiltinCallee())
10709 Diag(Loc, diag::warn_floatingpoint_eq)
10730 IntRange(
unsigned Width,
bool NonNegative)
10731 : Width(Width), NonNegative(NonNegative) {}
10734 unsigned valueBits()
const {
10735 return NonNegative ? Width : Width - 1;
10739 static IntRange forBoolType() {
10740 return IntRange(1,
true);
10744 static IntRange forValueOfType(ASTContext &
C, QualType
T) {
10745 return forValueOfCanonicalType(
C,
10750 static IntRange forValueOfCanonicalType(ASTContext &
C,
const Type *
T) {
10753 if (
const auto *VT = dyn_cast<VectorType>(
T))
10754 T = VT->getElementType().getTypePtr();
10755 if (
const auto *CT = dyn_cast<ComplexType>(
T))
10756 T = CT->getElementType().getTypePtr();
10757 if (
const auto *AT = dyn_cast<AtomicType>(
T))
10758 T = AT->getValueType().getTypePtr();
10760 if (!
C.getLangOpts().CPlusPlus) {
10763 T = ED->getIntegerType().getDesugaredType(
C).getTypePtr();
10768 if (
Enum->isFixed()) {
10769 return IntRange(
C.getIntWidth(QualType(
T, 0)),
10770 !
Enum->getIntegerType()->isSignedIntegerType());
10773 unsigned NumPositive =
Enum->getNumPositiveBits();
10774 unsigned NumNegative =
Enum->getNumNegativeBits();
10776 if (NumNegative == 0)
10777 return IntRange(NumPositive,
true);
10779 return IntRange(std::max(NumPositive + 1, NumNegative),
10783 if (
const auto *EIT = dyn_cast<BitIntType>(
T))
10784 return IntRange(EIT->getNumBits(), EIT->isUnsigned());
10797 static IntRange forTargetOfCanonicalType(ASTContext &
C,
const Type *
T) {
10800 if (
const VectorType *VT = dyn_cast<VectorType>(
T))
10801 T = VT->getElementType().getTypePtr();
10802 if (
const ComplexType *CT = dyn_cast<ComplexType>(
T))
10803 T = CT->getElementType().getTypePtr();
10804 if (
const AtomicType *AT = dyn_cast<AtomicType>(
T))
10805 T = AT->getValueType().getTypePtr();
10807 T =
C.getCanonicalType(ED->getIntegerType()).getTypePtr();
10809 if (
const auto *EIT = dyn_cast<BitIntType>(
T))
10810 return IntRange(EIT->getNumBits(), EIT->isUnsigned());
10819 static IntRange join(IntRange L, IntRange R) {
10820 bool Unsigned = L.NonNegative && R.NonNegative;
10821 return IntRange(std::max(L.valueBits(), R.valueBits()) + !
Unsigned,
10822 L.NonNegative && R.NonNegative);
10826 static IntRange bit_and(IntRange L, IntRange R) {
10827 unsigned Bits = std::max(L.Width, R.Width);
10828 bool NonNegative =
false;
10829 if (L.NonNegative) {
10830 Bits = std::min(Bits, L.Width);
10831 NonNegative =
true;
10833 if (R.NonNegative) {
10834 Bits = std::min(Bits, R.Width);
10835 NonNegative =
true;
10837 return IntRange(Bits, NonNegative);
10841 static IntRange sum(IntRange L, IntRange R) {
10842 bool Unsigned = L.NonNegative && R.NonNegative;
10843 return IntRange(std::max(L.valueBits(), R.valueBits()) + 1 + !
Unsigned,
10848 static IntRange difference(IntRange L, IntRange R) {
10852 bool CanWiden = !L.NonNegative || !R.NonNegative;
10853 bool Unsigned = L.NonNegative && R.Width == 0;
10854 return IntRange(std::max(L.valueBits(), R.valueBits()) + CanWiden +
10860 static IntRange product(IntRange L, IntRange R) {
10864 bool CanWiden = !L.NonNegative && !R.NonNegative;
10865 bool Unsigned = L.NonNegative && R.NonNegative;
10866 return IntRange(L.valueBits() + R.valueBits() + CanWiden + !
Unsigned,
10871 static IntRange rem(IntRange L, IntRange R) {
10875 return IntRange(std::min(L.valueBits(), R.valueBits()) + !
Unsigned,
10883 if (value.isSigned() && value.isNegative())
10884 return IntRange(value.getSignificantBits(),
false);
10886 if (value.getBitWidth() > MaxWidth)
10887 value = value.trunc(MaxWidth);
10891 return IntRange(value.getActiveBits(),
true);
10895 if (result.
isInt())
10902 R = IntRange::join(R, El);
10910 return IntRange::join(R, I);
10925 Ty = AtomicRHS->getValueType();
10944 bool InConstantContext,
10945 bool Approximate) {
10956 if (
const auto *CE = dyn_cast<ImplicitCastExpr>(E)) {
10957 if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue)
10961 IntRange OutputTypeRange = IntRange::forValueOfType(
C,
GetExprType(CE));
10963 bool isIntegerCast = CE->getCastKind() == CK_IntegralCast ||
10964 CE->getCastKind() == CK_BooleanToSignedIntegral;
10967 if (!isIntegerCast)
10968 return OutputTypeRange;
10971 C, CE->getSubExpr(), std::min(MaxWidth, OutputTypeRange.Width),
10972 InConstantContext, Approximate);
10974 return std::nullopt;
10977 if (SubRange->Width >= OutputTypeRange.Width)
10978 return OutputTypeRange;
10982 return IntRange(SubRange->Width,
10983 SubRange->NonNegative || OutputTypeRange.NonNegative);
10986 if (
const auto *CO = dyn_cast<ConditionalOperator>(E)) {
10989 if (CO->getCond()->EvaluateAsBooleanCondition(CondResult,
C))
10991 C, CondResult ? CO->getTrueExpr() : CO->getFalseExpr(), MaxWidth,
10992 InConstantContext, Approximate);
10997 Expr *TrueExpr = CO->getTrueExpr();
10999 return std::nullopt;
11001 std::optional<IntRange> L =
11004 return std::nullopt;
11006 Expr *FalseExpr = CO->getFalseExpr();
11008 return std::nullopt;
11010 std::optional<IntRange> R =
11013 return std::nullopt;
11015 return IntRange::join(*L, *R);
11018 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
11019 IntRange (*Combine)(IntRange, IntRange) = IntRange::join;
11021 switch (BO->getOpcode()) {
11023 llvm_unreachable(
"builtin <=> should have class type");
11034 return IntRange::forBoolType();
11063 Combine = IntRange::bit_and;
11071 = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) {
11072 if (I->getValue() == 1) {
11073 IntRange R = IntRange::forValueOfType(
C,
GetExprType(E));
11074 return IntRange(R.Width,
true);
11084 case BO_ShrAssign: {
11086 C, BO->getLHS(), MaxWidth, InConstantContext, Approximate);
11088 return std::nullopt;
11092 if (std::optional<llvm::APSInt> shift =
11093 BO->getRHS()->getIntegerConstantExpr(
C)) {
11094 if (shift->isNonNegative()) {
11095 if (shift->uge(L->Width))
11096 L->Width = (L->NonNegative ? 0 : 1);
11098 L->Width -= shift->getZExtValue();
11112 Combine = IntRange::sum;
11116 if (BO->getLHS()->getType()->isPointerType())
11119 Combine = IntRange::difference;
11124 Combine = IntRange::product;
11133 C, BO->getLHS(), opWidth, InConstantContext, Approximate);
11135 return std::nullopt;
11138 if (std::optional<llvm::APSInt> divisor =
11139 BO->getRHS()->getIntegerConstantExpr(
C)) {
11140 unsigned log2 = divisor->logBase2();
11141 if (
log2 >= L->Width)
11142 L->Width = (L->NonNegative ? 0 : 1);
11144 L->Width = std::min(L->Width -
log2, MaxWidth);
11152 C, BO->getRHS(), opWidth, InConstantContext, Approximate);
11154 return std::nullopt;
11156 return IntRange(L->Width, L->NonNegative && R->NonNegative);
11160 Combine = IntRange::rem;
11172 unsigned opWidth =
C.getIntWidth(
T);
11174 InConstantContext, Approximate);
11176 return std::nullopt;
11179 InConstantContext, Approximate);
11181 return std::nullopt;
11183 IntRange
C = Combine(*L, *R);
11184 C.NonNegative |=
T->isUnsignedIntegerOrEnumerationType();
11185 C.Width = std::min(
C.Width, MaxWidth);
11189 if (
const auto *UO = dyn_cast<UnaryOperator>(E)) {
11190 switch (UO->getOpcode()) {
11193 return IntRange::forBoolType();
11207 C, UO->getSubExpr(), MaxWidth, InConstantContext, Approximate);
11210 return std::nullopt;
11215 return IntRange(std::min(SubRange->Width + 1, MaxWidth),
false);
11225 C, UO->getSubExpr(), MaxWidth, InConstantContext, Approximate);
11228 return std::nullopt;
11233 std::min(SubRange->Width + (
int)SubRange->NonNegative, MaxWidth),
11243 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(E))
11244 return TryGetExprRange(
C, OVE->getSourceExpr(), MaxWidth, InConstantContext,
11248 return IntRange(BitField->getBitWidthValue(),
11249 BitField->getType()->isUnsignedIntegerOrEnumerationType());
11252 return std::nullopt;
11258 bool InConstantContext,
11259 bool Approximate) {
11268 const llvm::fltSemantics &Src,
11269 const llvm::fltSemantics &Tgt) {
11270 llvm::APFloat truncated = value;
11273 truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
11274 truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);
11276 return truncated.bitwiseIsEqual(value);
11285 const llvm::fltSemantics &Src,
11286 const llvm::fltSemantics &Tgt) {
11303 bool IsListInit =
false);
11318 return MacroName !=
"YES" && MacroName !=
"NO" &&
11319 MacroName !=
"true" && MacroName !=
"false";
11327 (!E->
getType()->isSignedIntegerType() ||
11342struct PromotedRange {
11344 llvm::APSInt PromotedMin;
11346 llvm::APSInt PromotedMax;
11348 PromotedRange(IntRange R,
unsigned BitWidth,
bool Unsigned) {
11350 PromotedMin = PromotedMax = llvm::APSInt(BitWidth,
Unsigned);
11351 else if (R.Width >= BitWidth && !
Unsigned) {
11355 PromotedMin = llvm::APSInt::getMinValue(BitWidth,
Unsigned);
11356 PromotedMax = llvm::APSInt::getMaxValue(BitWidth,
Unsigned);
11358 PromotedMin = llvm::APSInt::getMinValue(R.Width, R.NonNegative)
11359 .extOrTrunc(BitWidth);
11360 PromotedMin.setIsUnsigned(
Unsigned);
11362 PromotedMax = llvm::APSInt::getMaxValue(R.Width, R.NonNegative)
11363 .extOrTrunc(BitWidth);
11364 PromotedMax.setIsUnsigned(
Unsigned);
11369 bool isContiguous()
const {
return PromotedMin <= PromotedMax; }
11379 InRangeFlag = 0x40,
11382 Min =
LE | InRangeFlag,
11383 InRange = InRangeFlag,
11384 Max =
GE | InRangeFlag,
11387 OnlyValue =
LE |
GE |
EQ | InRangeFlag,
11392 assert(
Value.getBitWidth() == PromotedMin.getBitWidth() &&
11393 Value.isUnsigned() == PromotedMin.isUnsigned());
11394 if (!isContiguous()) {
11395 assert(
Value.isUnsigned() &&
"discontiguous range for signed compare");
11396 if (
Value.isMinValue())
return Min;
11397 if (
Value.isMaxValue())
return Max;
11398 if (
Value >= PromotedMin)
return InRange;
11399 if (
Value <= PromotedMax)
return InRange;
11403 switch (llvm::APSInt::compareValues(
Value, PromotedMin)) {
11404 case -1:
return Less;
11405 case 0:
return PromotedMin == PromotedMax ? OnlyValue :
Min;
11407 switch (llvm::APSInt::compareValues(
Value, PromotedMax)) {
11408 case -1:
return InRange;
11409 case 0:
return Max;
11414 llvm_unreachable(
"impossible compare result");
11417 static std::optional<StringRef>
11419 if (Op == BO_Cmp) {
11421 if (ConstantOnRHS) std::swap(LTFlag, GTFlag);
11423 if (R & EQ)
return StringRef(
"'std::strong_ordering::equal'");
11424 if (R & LTFlag)
return StringRef(
"'std::strong_ordering::less'");
11425 if (R & GTFlag)
return StringRef(
"'std::strong_ordering::greater'");
11426 return std::nullopt;
11433 }
else if (Op == BO_NE) {
11437 if ((Op == BO_LT || Op == BO_GE) ^ ConstantOnRHS) {
11444 if (Op == BO_GE || Op == BO_LE)
11445 std::swap(TrueFlag, FalseFlag);
11448 return StringRef(
"true");
11450 return StringRef(
"false");
11451 return std::nullopt;
11458 while (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
11459 if (ICE->getCastKind() != CK_IntegralCast &&
11460 ICE->getCastKind() != CK_NoOp)
11462 E = ICE->getSubExpr();
11471 enum ConstantValueKind {
11476 if (
auto *BL = dyn_cast<CXXBoolLiteralExpr>(Constant))
11477 return BL->getValue() ? ConstantValueKind::LiteralTrue
11478 : ConstantValueKind::LiteralFalse;
11479 return ConstantValueKind::Miscellaneous;
11484 const llvm::APSInt &
Value,
11485 bool RhsConstant) {
11507 if (!OtherValueRange)
11512 OtherT = AT->getValueType();
11513 IntRange OtherTypeRange = IntRange::forValueOfType(S.
Context, OtherT);
11517 bool IsObjCSignedCharBool = S.
getLangOpts().ObjC &&
11523 bool OtherIsBooleanDespiteType =
11525 if (OtherIsBooleanDespiteType || IsObjCSignedCharBool)
11526 OtherTypeRange = *OtherValueRange = IntRange::forBoolType();
11530 PromotedRange OtherPromotedValueRange(*OtherValueRange,
Value.getBitWidth(),
11531 Value.isUnsigned());
11532 auto Cmp = OtherPromotedValueRange.compare(
Value);
11533 auto Result = PromotedRange::constantValue(E->
getOpcode(), Cmp, RhsConstant);
11539 bool TautologicalTypeCompare =
false;
11541 PromotedRange OtherPromotedTypeRange(OtherTypeRange,
Value.getBitWidth(),
11542 Value.isUnsigned());
11543 auto TypeCmp = OtherPromotedTypeRange.compare(
Value);
11546 TautologicalTypeCompare =
true;
11554 if (!TautologicalTypeCompare && OtherValueRange->Width == 0)
11563 bool InRange = Cmp & PromotedRange::InRangeFlag;
11569 if (
Other->refersToBitField() && InRange &&
Value == 0 &&
11570 Other->getType()->isUnsignedIntegerOrEnumerationType())
11571 TautologicalTypeCompare =
true;
11576 if (
const auto *DR = dyn_cast<DeclRefExpr>(Constant))
11577 ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
11581 llvm::raw_svector_ostream OS(PrettySourceValue);
11583 OS <<
'\'' << *ED <<
"' (" <<
Value <<
")";
11584 }
else if (
auto *BL = dyn_cast<ObjCBoolLiteralExpr>(
11586 OS << (BL->getValue() ?
"YES" :
"NO");
11591 if (!TautologicalTypeCompare) {
11593 << RhsConstant << OtherValueRange->Width << OtherValueRange->NonNegative
11599 if (IsObjCSignedCharBool) {
11601 S.
PDiag(diag::warn_tautological_compare_objc_bool)
11602 << OS.str() << *Result);
11609 if (!InRange ||
Other->isKnownToHaveBooleanValue()) {
11613 S.
PDiag(!InRange ? diag::warn_out_of_range_compare
11614 : diag::warn_tautological_bool_compare)
11616 << OtherIsBooleanDespiteType << *Result
11623 ? diag::warn_unsigned_enum_always_true_comparison
11624 : IsCharTy ? diag::warn_unsigned_char_always_true_comparison
11625 : diag::warn_unsigned_always_true_comparison)
11626 : diag::warn_tautological_constant_compare;
11629 << RhsConstant << OtherT << E->
getOpcodeStr() << OS.str() << *Result
11662 if (
T->isIntegralType(S.
Context)) {
11663 std::optional<llvm::APSInt> RHSValue =
11665 std::optional<llvm::APSInt> LHSValue =
11669 if (RHSValue && LHSValue)
11673 if ((
bool)RHSValue ^ (
bool)LHSValue) {
11675 const bool RhsConstant = (
bool)RHSValue;
11676 Expr *Const = RhsConstant ? RHS : LHS;
11678 const llvm::APSInt &
Value = RhsConstant ? *RHSValue : *LHSValue;
11687 if (!
T->hasUnsignedIntegerRepresentation()) {
11701 if (
const auto *TET = dyn_cast<TypeOfExprType>(LHS->
getType()))
11703 if (
const auto *TET = dyn_cast<TypeOfExprType>(RHS->
getType()))
11709 Expr *signedOperand, *unsignedOperand;
11712 "unsigned comparison between two signed integer expressions?");
11713 signedOperand = LHS;
11714 unsignedOperand = RHS;
11716 signedOperand = RHS;
11717 unsignedOperand = LHS;
11723 std::optional<IntRange> signedRange =
11735 if (signedRange->NonNegative)
11747 if (!unsignedRange)
11752 assert(unsignedRange->NonNegative &&
"unsigned range includes negative?");
11754 if (unsignedRange->Width < comparisonWidth)
11759 S.
PDiag(diag::warn_mixed_sign_comparison)
11778 if (
auto *BitfieldEnumDecl = BitfieldType->
getAsEnumDecl()) {
11783 !BitfieldEnumDecl->getIntegerTypeSourceInfo() &&
11784 BitfieldEnumDecl->getNumPositiveBits() > 0 &&
11785 BitfieldEnumDecl->getNumNegativeBits() == 0) {
11786 S.
Diag(InitLoc, diag::warn_no_underlying_type_specified_for_enum_bitfield)
11787 << BitfieldEnumDecl;
11794 Init->isValueDependent() ||
11795 Init->isTypeDependent())
11798 Expr *OriginalInit =
Init->IgnoreParenImpCasts();
11808 const PreferredTypeAttr *PTAttr =
nullptr;
11810 PTAttr = Bitfield->
getAttr<PreferredTypeAttr>();
11812 ED = PTAttr->getType()->getAsEnumDecl();
11820 bool SignedEnum = ED->getNumNegativeBits() > 0;
11827 unsigned DiagID = 0;
11828 if (SignedEnum && !SignedBitfield) {
11831 ? diag::warn_unsigned_bitfield_assigned_signed_enum
11833 warn_preferred_type_unsigned_bitfield_assigned_signed_enum;
11834 }
else if (SignedBitfield && !SignedEnum &&
11835 ED->getNumPositiveBits() == FieldWidth) {
11838 ? diag::warn_signed_bitfield_enum_conversion
11839 : diag::warn_preferred_type_signed_bitfield_enum_conversion;
11842 S.
Diag(InitLoc, DiagID) << Bitfield << ED;
11847 << SignedEnum << TypeRange;
11849 S.
Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
11856 unsigned BitsNeeded = SignedEnum ? std::max(ED->getNumPositiveBits() + 1,
11857 ED->getNumNegativeBits())
11858 : ED->getNumPositiveBits();
11861 if (BitsNeeded > FieldWidth) {
11865 ? diag::warn_bitfield_too_small_for_enum
11866 : diag::warn_preferred_type_bitfield_too_small_for_enum;
11867 S.
Diag(InitLoc, DiagID) << Bitfield << ED;
11871 S.
Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
11879 llvm::APSInt
Value = Result.Val.getInt();
11881 unsigned OriginalWidth =
Value.getBitWidth();
11887 bool OneAssignedToOneBitBitfield = FieldWidth == 1 &&
Value == 1;
11888 if (OneAssignedToOneBitBitfield && !S.
LangOpts.CPlusPlus) {
11895 if (!
Value.isSigned() ||
Value.isNegative())
11896 if (
UnaryOperator *UO = dyn_cast<UnaryOperator>(OriginalInit))
11897 if (UO->getOpcode() == UO_Minus || UO->getOpcode() == UO_Not)
11898 OriginalWidth =
Value.getSignificantBits();
11900 if (OriginalWidth <= FieldWidth)
11904 llvm::APSInt TruncatedValue =
Value.trunc(FieldWidth);
11908 TruncatedValue = TruncatedValue.extend(OriginalWidth);
11909 if (llvm::APSInt::isSameValue(
Value, TruncatedValue))
11913 std::string PrettyTrunc =
toString(TruncatedValue, 10);
11915 S.
Diag(InitLoc, OneAssignedToOneBitBitfield
11916 ? diag::warn_impcast_single_bit_bitield_precision_constant
11917 : diag::warn_impcast_bitfield_precision_constant)
11918 << PrettyValue << PrettyTrunc << OriginalInit->
getType()
11919 <<
Init->getSourceRange();
11951 bool PruneControlFlow =
false) {
11958 if (
T.hasAddressSpace())
11960 if (PruneControlFlow) {
11974 bool PruneControlFlow =
false) {
11981 bool IsBool =
T->isSpecificBuiltinType(BuiltinType::Bool);
11986 if (
const auto *UOp = dyn_cast<UnaryOperator>(InnerE))
11987 if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus)
11992 llvm::APFloat
Value(0.0);
11998 E, S.
Diag(CContext, diag::warn_impcast_float_to_objc_signed_char_bool)
12003 diag::warn_impcast_float_integer, PruneWarnings);
12006 bool isExact =
false;
12009 T->hasUnsignedIntegerRepresentation());
12010 llvm::APFloat::opStatus Result =
Value.convertToInteger(
12011 IntegerValue, llvm::APFloat::rmTowardZero, &isExact);
12019 unsigned precision = llvm::APFloat::semanticsPrecision(
Value.getSemantics());
12020 precision = (precision * 59 + 195) / 196;
12021 Value.toString(PrettySourceValue, precision);
12025 E, S.
Diag(CContext, diag::warn_impcast_constant_value_to_objc_bool)
12026 << PrettySourceValue);
12029 if (Result == llvm::APFloat::opOK && isExact) {
12030 if (IsLiteral)
return;
12031 return DiagnoseImpCast(S, E,
T, CContext, diag::warn_impcast_float_integer,
12037 if (!IsBool && Result == llvm::APFloat::opInvalidOp)
12040 IsLiteral ? diag::warn_impcast_literal_float_to_integer_out_of_range
12041 : diag::warn_impcast_float_to_integer_out_of_range,
12044 unsigned DiagID = 0;
12047 DiagID = diag::warn_impcast_literal_float_to_integer;
12048 }
else if (IntegerValue == 0) {
12049 if (
Value.isZero()) {
12051 diag::warn_impcast_float_integer, PruneWarnings);
12054 DiagID = diag::warn_impcast_float_to_integer_zero;
12056 if (IntegerValue.isUnsigned()) {
12057 if (!IntegerValue.isMaxValue()) {
12059 diag::warn_impcast_float_integer, PruneWarnings);
12062 if (!IntegerValue.isMaxSignedValue() &&
12063 !IntegerValue.isMinSignedValue()) {
12065 diag::warn_impcast_float_integer, PruneWarnings);
12069 DiagID = diag::warn_impcast_float_to_integer;
12074 PrettyTargetValue =
Value.isZero() ?
"false" :
"true";
12076 IntegerValue.toString(PrettyTargetValue);
12078 if (PruneWarnings) {
12081 << E->
getType() <<
T.getUnqualifiedType()
12082 << PrettySourceValue << PrettyTargetValue
12086 << E->
getType() <<
T.getUnqualifiedType() << PrettySourceValue
12095 "Must be compound assignment operation");
12106 ->getComputationResultType()
12113 if (ResultBT->isInteger())
12115 E->
getExprLoc(), diag::warn_impcast_float_integer);
12117 if (!ResultBT->isFloatingPoint())
12126 diag::warn_impcast_float_result_precision);
12131 if (!Range.Width)
return "0";
12133 llvm::APSInt ValueInRange =
Value;
12134 ValueInRange.setIsSigned(!Range.NonNegative);
12135 ValueInRange = ValueInRange.trunc(Range.Width);
12136 return toString(ValueInRange, 10);
12146 const Type *Source =
12148 if (
Target->isDependentType())
12151 const auto *FloatCandidateBT =
12152 dyn_cast<BuiltinType>(ToBool ? Source :
Target);
12153 const Type *BoolCandidateType = ToBool ?
Target : Source;
12156 FloatCandidateBT && (FloatCandidateBT->isFloatingPoint()));
12161 for (
unsigned I = 0, N = TheCall->
getNumArgs(); I < N; ++I) {
12167 S, TheCall->
getArg(I - 1),
false));
12169 S, TheCall->
getArg(I + 1),
false));
12174 diag::warn_impcast_floating_point_to_bool);
12189 if (!IsGNUNullExpr && !HasNullPtrType)
12193 if (
T->isAnyPointerType() ||
T->isBlockPointerType() ||
12194 T->isMemberPointerType() || !
T->isScalarType() ||
T->isNullPtrType())
12197 if (S.
Diags.
isIgnored(diag::warn_impcast_null_pointer_to_integer,
12210 if (IsGNUNullExpr && Loc.
isMacroID()) {
12213 if (MacroName ==
"NULL")
12221 S.
Diag(Loc, diag::warn_impcast_null_pointer_to_integer)
12235 const char FirstLiteralCharacter =
12237 if (FirstLiteralCharacter ==
'0')
12243 if (CC.
isValid() &&
T->isCharType()) {
12244 const char FirstContextCharacter =
12246 if (FirstContextCharacter ==
'{')
12254 const auto *IL = dyn_cast<IntegerLiteral>(E);
12256 if (
auto *UO = dyn_cast<UnaryOperator>(E)) {
12257 if (UO->getOpcode() == UO_Minus)
12258 return dyn_cast<IntegerLiteral>(UO->getSubExpr());
12269 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
12273 if (Opc == BO_Shl) {
12276 if (LHS && LHS->getValue() == 0)
12277 S.
Diag(ExprLoc, diag::warn_left_shift_always) << 0;
12279 RHS->getValue().isNonNegative() &&
12281 S.
Diag(ExprLoc, diag::warn_left_shift_always)
12282 << (Result.Val.getInt() != 0);
12284 S.
Diag(ExprLoc, diag::warn_left_shift_in_bool_context)
12291 if (
const auto *CO = dyn_cast<ConditionalOperator>(E)) {
12296 if ((LHS->getValue() == 0 || LHS->getValue() == 1) &&
12297 (RHS->getValue() == 0 || RHS->getValue() == 1))
12300 if (LHS->getValue() != 0 && RHS->getValue() != 0)
12301 S.
Diag(ExprLoc, diag::warn_integer_constants_in_conditional_always_true);
12309 assert(Source->isUnicodeCharacterType() &&
Target->isUnicodeCharacterType() &&
12314 llvm::APSInt
Value(32);
12315 Value = Result.Val.getInt();
12316 bool IsASCII =
Value <= 0x7F;
12317 bool IsBMP =
Value <= 0xD7FF || (
Value >= 0xE000 &&
Value <= 0xFFFF);
12318 bool ConversionPreservesSemantics =
12319 IsASCII || (!Source->isChar8Type() && !
Target->isChar8Type() && IsBMP);
12321 if (!ConversionPreservesSemantics) {
12322 auto IsSingleCodeUnitCP = [](
const QualType &
T,
12323 const llvm::APSInt &
Value) {
12324 if (
T->isChar8Type())
12325 return llvm::IsSingleCodeUnitUTF8Codepoint(
Value.getExtValue());
12326 if (
T->isChar16Type())
12327 return llvm::IsSingleCodeUnitUTF16Codepoint(
Value.getExtValue());
12328 assert(
T->isChar32Type());
12329 return llvm::IsSingleCodeUnitUTF32Codepoint(
Value.getExtValue());
12332 S.
Diag(CC, diag::warn_impcast_unicode_char_type_constant)
12341 LosesPrecision ? diag::warn_impcast_unicode_precision
12342 : diag::warn_impcast_unicode_char_type);
12356 From = MaybePointee;
12363 if (FromFn->getCFIUncheckedCalleeAttr() &&
12364 !ToFn->getCFIUncheckedCalleeAttr())
12366 if (!FromFn->getCFIUncheckedCalleeAttr() &&
12367 ToFn->getCFIUncheckedCalleeAttr())
12375 From =
Context.getCanonicalType(From);
12376 To =
Context.getCanonicalType(To);
12377 return ::AdjustingCFIUncheckedCallee(From, To) ==
Discarding;
12381 From =
Context.getCanonicalType(From);
12382 To =
Context.getCanonicalType(To);
12383 return ::AdjustingCFIUncheckedCallee(From, To) ==
Adding;
12387 bool *ICContext,
bool IsListInit) {
12392 if (Source ==
Target)
return;
12393 if (
Target->isDependentType())
return;
12403 if (Source->isAtomicType())
12407 if (
Target->isSpecificBuiltinType(BuiltinType::Bool)) {
12413 diag::warn_impcast_string_literal_to_bool);
12419 diag::warn_impcast_objective_c_literal_to_bool);
12421 if (Source->isPointerType() || Source->canDecayToPointerType()) {
12431 if (
ObjC().isSignedCharBool(
T) && Source->isIntegralType(
Context)) {
12434 if (
Result.Val.getInt() != 1 &&
Result.Val.getInt() != 0) {
12436 E,
Diag(CC, diag::warn_impcast_constant_value_to_objc_bool)
12445 if (
auto *ArrayLiteral = dyn_cast<ObjCArrayLiteral>(E))
12447 else if (
auto *DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(E))
12452 if (
Target->isSveVLSBuiltinType() &&
12459 if (
Target->isRVVVLSBuiltinType() &&
12469 return DiagnoseImpCast(*
this, E,
T, CC, diag::warn_impcast_vector_scalar);
12476 diag::warn_hlsl_impcast_vector_truncation);
12488 if (
auto VecTy = dyn_cast<VectorType>(
Target))
12489 Target = VecTy->getElementType().getTypePtr();
12499 ? diag::err_impcast_complex_scalar
12500 : diag::warn_impcast_complex_scalar);
12507 const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
12513 const Type *OriginalTarget =
Context.getCanonicalType(
T).getTypePtr();
12516 if (
ARM().areCompatibleSveTypes(
QualType(OriginalTarget, 0),
12518 ARM().areLaxCompatibleSveTypes(
QualType(OriginalTarget, 0),
12560 else if (Order < 0) {
12570 if (TargetBT && TargetBT->
isInteger()) {
12597 diag::warn_impcast_floating_point_to_bool);
12605 if (Source->isFixedPointType()) {
12606 if (
Target->isUnsaturatedFixedPointType()) {
12610 llvm::APFixedPoint
Value =
Result.Val.getFixedPoint();
12611 llvm::APFixedPoint MaxVal =
Context.getFixedPointMax(
T);
12612 llvm::APFixedPoint MinVal =
Context.getFixedPointMin(
T);
12615 PDiag(diag::warn_impcast_fixed_point_range)
12616 <<
Value.toString() <<
T
12622 }
else if (
Target->isIntegerType()) {
12626 llvm::APFixedPoint FXResult =
Result.Val.getFixedPoint();
12629 llvm::APSInt IntResult = FXResult.convertToInt(
12630 Context.getIntWidth(
T),
Target->isSignedIntegerOrEnumerationType(),
12635 PDiag(diag::warn_impcast_fixed_point_range)
12636 << FXResult.toString() <<
T
12643 }
else if (
Target->isUnsaturatedFixedPointType()) {
12644 if (Source->isIntegerType()) {
12651 llvm::APFixedPoint IntResult = llvm::APFixedPoint::getFromIntValue(
12656 PDiag(diag::warn_impcast_fixed_point_range)
12677 unsigned int SourcePrecision =
SourceRange->Width;
12681 unsigned int TargetPrecision = llvm::APFloatBase::semanticsPrecision(
12684 if (SourcePrecision > 0 && TargetPrecision > 0 &&
12685 SourcePrecision > TargetPrecision) {
12687 if (std::optional<llvm::APSInt> SourceInt =
12692 llvm::APFloat TargetFloatValue(
12694 llvm::APFloat::opStatus ConversionStatus =
12695 TargetFloatValue.convertFromAPInt(
12697 llvm::APFloat::rmNearestTiesToEven);
12699 if (ConversionStatus != llvm::APFloat::opOK) {
12701 SourceInt->toString(PrettySourceValue, 10);
12703 TargetFloatValue.toString(PrettyTargetValue, TargetPrecision);
12707 PDiag(diag::warn_impcast_integer_float_precision_constant)
12708 << PrettySourceValue << PrettyTargetValue << E->
getType() <<
T
12714 diag::warn_impcast_integer_float_precision);
12723 if (Source->isUnicodeCharacterType() &&
Target->isUnicodeCharacterType()) {
12728 if (
Target->isBooleanType())
12732 Diag(CC, diag::warn_cast_discards_cfi_unchecked_callee)
12736 if (!Source->isIntegerType() || !
Target->isIntegerType())
12741 if (
Target->isSpecificBuiltinType(BuiltinType::Bool))
12744 if (
ObjC().isSignedCharBool(
T) && !Source->isCharType() &&
12747 E,
Diag(CC, diag::warn_impcast_int_to_objc_signed_char_bool)
12752 if (!LikelySourceRange)
12755 IntRange SourceTypeRange =
12756 IntRange::forTargetOfCanonicalType(
Context, Source);
12757 IntRange TargetRange = IntRange::forTargetOfCanonicalType(
Context,
Target);
12759 if (LikelySourceRange->Width > TargetRange.Width) {
12765 llvm::APSInt
Value(32);
12775 PDiag(diag::warn_impcast_integer_precision_constant)
12776 << PrettySourceValue << PrettyTargetValue
12786 if (
const auto *UO = dyn_cast<UnaryOperator>(E)) {
12787 if (UO->getOpcode() == UO_Minus)
12789 *
this, E,
T, CC, diag::warn_impcast_integer_precision_on_negation);
12792 if (TargetRange.Width == 32 &&
Context.getIntWidth(E->
getType()) == 64)
12796 diag::warn_impcast_integer_precision);
12799 if (TargetRange.Width > SourceTypeRange.Width) {
12800 if (
auto *UO = dyn_cast<UnaryOperator>(E))
12801 if (UO->getOpcode() == UO_Minus)
12802 if (Source->isUnsignedIntegerType()) {
12803 if (
Target->isUnsignedIntegerType())
12805 diag::warn_impcast_high_order_zero_bits);
12806 if (
Target->isSignedIntegerType())
12808 diag::warn_impcast_nonnegative_result);
12812 if (TargetRange.Width == LikelySourceRange->Width &&
12813 !TargetRange.NonNegative && LikelySourceRange->NonNegative &&
12814 Source->isSignedIntegerType()) {
12828 PDiag(diag::warn_impcast_integer_precision_constant)
12829 << PrettySourceValue << PrettyTargetValue << E->
getType() <<
T
12839 ((TargetRange.NonNegative && !LikelySourceRange->NonNegative) ||
12840 (!TargetRange.NonNegative && LikelySourceRange->NonNegative &&
12841 LikelySourceRange->Width == TargetRange.Width))) {
12845 if (SourceBT && SourceBT->
isInteger() && TargetBT &&
12847 Source->isSignedIntegerType() ==
Target->isSignedIntegerType()) {
12851 unsigned DiagID = diag::warn_impcast_integer_sign;
12859 DiagID = diag::warn_impcast_integer_sign_conditional;
12876 Source =
Context.getCanonicalType(SourceType).getTypePtr();
12878 if (
const EnumType *SourceEnum = Source->getAsCanonical<EnumType>())
12879 if (
const EnumType *TargetEnum =
Target->getAsCanonical<EnumType>())
12880 if (SourceEnum->getOriginalDecl()->hasNameForLinkage() &&
12881 TargetEnum->getOriginalDecl()->hasNameForLinkage() &&
12882 SourceEnum != TargetEnum) {
12887 diag::warn_impcast_different_enum_types);
12901 if (
auto *CO = dyn_cast<AbstractConditionalOperator>(E))
12914 if (
auto *BCO = dyn_cast<BinaryConditionalOperator>(E))
12915 TrueExpr = BCO->getCommon();
12917 bool Suspicious =
false;
12921 if (
T->isBooleanType())
12926 if (!Suspicious)
return;
12929 if (!S.
Diags.
isIgnored(diag::warn_impcast_integer_sign_conditional, CC))
12936 Suspicious =
false;
12941 E->
getType(), CC, &Suspicious);
12958struct AnalyzeImplicitConversionsWorkItem {
12967 bool ExtraCheckForImplicitConversion,
12970 WorkList.push_back({E, CC,
false});
12972 if (ExtraCheckForImplicitConversion && E->
getType() !=
T)
12979 Sema &S, AnalyzeImplicitConversionsWorkItem Item,
12981 Expr *OrigE = Item.E;
13000 Expr *SourceExpr = E;
13005 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(E))
13006 if (
auto *Src = OVE->getSourceExpr())
13009 if (
const auto *UO = dyn_cast<UnaryOperator>(SourceExpr))
13010 if (UO->getOpcode() == UO_Not &&
13011 UO->getSubExpr()->isKnownToHaveBooleanValue())
13012 S.
Diag(UO->getBeginLoc(), diag::warn_bitwise_negation_bool)
13016 if (
auto *BO = dyn_cast<BinaryOperator>(SourceExpr)) {
13017 if ((BO->getOpcode() == BO_And || BO->getOpcode() == BO_Or) &&
13018 BO->getLHS()->isKnownToHaveBooleanValue() &&
13019 BO->getRHS()->isKnownToHaveBooleanValue() &&
13020 BO->getLHS()->HasSideEffects(S.
Context) &&
13021 BO->getRHS()->HasSideEffects(S.
Context)) {
13032 if (SR.str() ==
"&" || SR.str() ==
"|") {
13034 S.
Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
13035 << (BO->getOpcode() == BO_And ?
"&" :
"|")
13038 BO->getOperatorLoc(),
13039 (BO->getOpcode() == BO_And ?
"&&" :
"||"));
13040 S.
Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
13042 }
else if (BO->isCommaOp() && !S.
getLangOpts().CPlusPlus) {
13060 if (
auto *CO = dyn_cast<AbstractConditionalOperator>(SourceExpr)) {
13066 if (
const auto *
Call = dyn_cast<CallExpr>(SourceExpr))
13081 for (
auto *SE : POE->semantics())
13082 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(SE))
13083 WorkList.push_back({OVE->getSourceExpr(), CC, IsListInit});
13087 if (
auto *CE = dyn_cast<ExplicitCastExpr>(E)) {
13088 E = CE->getSubExpr();
13094 if (
auto *InitListE = dyn_cast<InitListExpr>(E)) {
13095 if (InitListE->getNumInits() == 1) {
13096 E = InitListE->getInit(0);
13103 WorkList.push_back({E, CC, IsListInit});
13107 if (
auto *OutArgE = dyn_cast<HLSLOutArgExpr>(E)) {
13108 WorkList.push_back({OutArgE->getArgLValue(), CC, IsListInit});
13112 if (OutArgE->isInOut())
13113 WorkList.push_back(
13114 {OutArgE->getCastedTemporary()->getSourceExpr(), CC, IsListInit});
13115 WorkList.push_back({OutArgE->getWritebackCast(), CC, IsListInit});
13121 if (BO->isComparisonOp())
13125 if (BO->getOpcode() == BO_Assign)
13128 if (BO->isAssignmentOp())
13144 bool IsLogicalAndOperator = BO && BO->
getOpcode() == BO_LAnd;
13146 Expr *ChildExpr = dyn_cast_or_null<Expr>(SubStmt);
13150 if (
auto *CSE = dyn_cast<CoroutineSuspendExpr>(E))
13151 if (ChildExpr == CSE->getOperand())
13157 if (IsLogicalAndOperator &&
13162 WorkList.push_back({ChildExpr, CC, IsListInit});
13176 if (
U->getOpcode() == UO_LNot) {
13178 }
else if (
U->getOpcode() != UO_AddrOf) {
13179 if (
U->getSubExpr()->getType()->isAtomicType())
13180 S.
Diag(
U->getSubExpr()->getBeginLoc(),
13181 diag::warn_atomic_implicit_seq_cst);
13192 WorkList.push_back({OrigE, CC, IsListInit});
13193 while (!WorkList.empty())
13205 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
13208 }
else if (
const MemberExpr *M = dyn_cast<MemberExpr>(E)) {
13209 if (!M->getMemberDecl()->getType()->isReferenceType())
13211 }
else if (
const CallExpr *
Call = dyn_cast<CallExpr>(E)) {
13212 if (!
Call->getCallReturnType(SemaRef.
Context)->isReferenceType())
13214 FD =
Call->getDirectCallee();
13223 SemaRef.
Diag(FD->
getLocation(), diag::note_reference_is_return_value) << FD;
13237 if (
SM.isMacroBodyExpansion(Loc))
13239 Loc =
SM.getImmediateMacroCallerLoc(Loc);
13263 unsigned DiagID = IsCompare ? diag::warn_this_null_compare
13264 : diag::warn_this_bool_conversion;
13269 bool IsAddressOf =
false;
13271 if (
auto *UO = dyn_cast<UnaryOperator>(E->
IgnoreParens())) {
13272 if (UO->getOpcode() != UO_AddrOf)
13274 IsAddressOf =
true;
13275 E = UO->getSubExpr();
13279 unsigned DiagID = IsCompare
13280 ? diag::warn_address_of_reference_null_compare
13281 : diag::warn_address_of_reference_bool_conversion;
13289 auto ComplainAboutNonnullParamOrCall = [&](
const Attr *NonnullAttr) {
13292 llvm::raw_string_ostream S(Str);
13294 unsigned DiagID = IsCompare ? diag::warn_nonnull_expr_compare
13295 : diag::warn_cast_nonnull_to_bool;
13298 Diag(NonnullAttr->getLocation(), diag::note_declared_nonnull) << IsParam;
13303 if (
auto *Callee =
Call->getDirectCallee()) {
13304 if (
const Attr *A = Callee->getAttr<ReturnsNonNullAttr>()) {
13305 ComplainAboutNonnullParamOrCall(A);
13314 if (
const auto *MCallExpr = dyn_cast<CXXMemberCallExpr>(E)) {
13315 if (
const auto *MRecordDecl = MCallExpr->getRecordDecl();
13316 MRecordDecl && MRecordDecl->isLambda()) {
13319 << MRecordDecl->getSourceRange() << Range << IsEqual;
13329 }
else if (
MemberExpr *M = dyn_cast<MemberExpr>(E)) {
13330 D = M->getMemberDecl();
13338 if (
const auto* PV = dyn_cast<ParmVarDecl>(D)) {
13341 if (
const Attr *A = PV->getAttr<NonNullAttr>()) {
13342 ComplainAboutNonnullParamOrCall(A);
13346 if (
const auto *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
13350 auto ParamIter = llvm::find(FD->
parameters(), PV);
13352 unsigned ParamNo = std::distance(FD->
param_begin(), ParamIter);
13356 ComplainAboutNonnullParamOrCall(
NonNull);
13361 if (ArgNo.getASTIndex() == ParamNo) {
13362 ComplainAboutNonnullParamOrCall(
NonNull);
13372 const bool IsArray =
T->isArrayType();
13373 const bool IsFunction =
T->isFunctionType();
13376 if (IsAddressOf && IsFunction) {
13381 if (!IsAddressOf && !IsFunction && !IsArray)
13386 llvm::raw_string_ostream S(Str);
13389 unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare
13390 : diag::warn_impcast_pointer_to_bool;
13397 DiagType = AddressOf;
13398 else if (IsFunction)
13399 DiagType = FunctionPointer;
13401 DiagType = ArrayPointer;
13403 llvm_unreachable(
"Could not determine diagnostic.");
13405 << Range << IsEqual;
13418 if (ReturnType.
isNull())
13456 CheckArrayAccess(E);
13466void Sema::CheckForIntOverflow (
const Expr *E) {
13468 SmallVector<const Expr *, 2> Exprs(1, E);
13471 const Expr *OriginalE = Exprs.pop_back_val();
13479 if (
const auto *InitList = dyn_cast<InitListExpr>(OriginalE))
13480 Exprs.append(InitList->inits().begin(), InitList->inits().end());
13483 else if (
const auto *
Call = dyn_cast<CallExpr>(E))
13484 Exprs.append(
Call->arg_begin(),
Call->arg_end());
13485 else if (
const auto *Message = dyn_cast<ObjCMessageExpr>(E))
13487 else if (
const auto *Construct = dyn_cast<CXXConstructExpr>(E))
13488 Exprs.append(Construct->arg_begin(), Construct->arg_end());
13489 else if (
const auto *Temporary = dyn_cast<CXXBindTemporaryExpr>(E))
13490 Exprs.push_back(Temporary->getSubExpr());
13491 else if (
const auto *Array = dyn_cast<ArraySubscriptExpr>(E))
13492 Exprs.push_back(Array->getIdx());
13493 else if (
const auto *Compound = dyn_cast<CompoundLiteralExpr>(E))
13494 Exprs.push_back(Compound->getInitializer());
13495 else if (
const auto *
New = dyn_cast<CXXNewExpr>(E);
13496 New &&
New->isArray()) {
13497 if (
auto ArraySize =
New->getArraySize())
13498 Exprs.push_back(*ArraySize);
13499 }
else if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(OriginalE))
13500 Exprs.push_back(MTE->getSubExpr());
13501 }
while (!Exprs.empty());
13509 using Base = ConstEvaluatedExprVisitor<SequenceChecker>;
13516 class SequenceTree {
13518 explicit Value(
unsigned Parent) : Parent(Parent), Merged(
false) {}
13519 unsigned Parent : 31;
13520 LLVM_PREFERRED_TYPE(
bool)
13521 unsigned Merged : 1;
13523 SmallVector<Value, 8> Values;
13529 friend class SequenceTree;
13533 explicit Seq(
unsigned N) : Index(N) {}
13536 Seq() : Index(0) {}
13539 SequenceTree() { Values.push_back(
Value(0)); }
13540 Seq root()
const {
return Seq(0); }
13545 Seq allocate(
Seq Parent) {
13546 Values.push_back(
Value(Parent.Index));
13547 return Seq(Values.size() - 1);
13551 void merge(
Seq S) {
13552 Values[S.Index].Merged =
true;
13558 bool isUnsequenced(
Seq Cur,
Seq Old) {
13559 unsigned C = representative(Cur.Index);
13560 unsigned Target = representative(Old.Index);
13564 C = Values[
C].Parent;
13571 unsigned representative(
unsigned K) {
13572 if (Values[K].Merged)
13574 return Values[K].Parent = representative(Values[K].Parent);
13580 using Object =
const NamedDecl *;
13594 UK_ModAsSideEffect,
13596 UK_Count = UK_ModAsSideEffect + 1
13602 const Expr *UsageExpr =
nullptr;
13603 SequenceTree::Seq
Seq;
13609 Usage Uses[UK_Count];
13612 bool Diagnosed =
false;
13616 using UsageInfoMap = llvm::SmallDenseMap<Object, UsageInfo, 16>;
13624 UsageInfoMap UsageMap;
13627 SequenceTree::Seq Region;
13631 SmallVectorImpl<std::pair<Object, Usage>> *ModAsSideEffect =
nullptr;
13635 SmallVectorImpl<const Expr *> &WorkList;
13642 struct SequencedSubexpression {
13643 SequencedSubexpression(SequenceChecker &
Self)
13644 :
Self(
Self), OldModAsSideEffect(
Self.ModAsSideEffect) {
13645 Self.ModAsSideEffect = &ModAsSideEffect;
13648 ~SequencedSubexpression() {
13649 for (
const std::pair<Object, Usage> &M : llvm::reverse(ModAsSideEffect)) {
13653 UsageInfo &UI =
Self.UsageMap[M.first];
13654 auto &SideEffectUsage = UI.Uses[UK_ModAsSideEffect];
13655 Self.addUsage(M.first, UI, SideEffectUsage.UsageExpr, UK_ModAsValue);
13656 SideEffectUsage = M.second;
13658 Self.ModAsSideEffect = OldModAsSideEffect;
13661 SequenceChecker &
Self;
13662 SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect;
13663 SmallVectorImpl<std::pair<Object, Usage>> *OldModAsSideEffect;
13670 class EvaluationTracker {
13672 EvaluationTracker(SequenceChecker &
Self)
13674 Self.EvalTracker =
this;
13677 ~EvaluationTracker() {
13678 Self.EvalTracker = Prev;
13680 Prev->EvalOK &= EvalOK;
13683 bool evaluate(
const Expr *E,
bool &
Result) {
13688 Self.SemaRef.isConstantEvaluatedContext());
13693 SequenceChecker &
Self;
13694 EvaluationTracker *Prev;
13695 bool EvalOK =
true;
13696 } *EvalTracker =
nullptr;
13700 Object getObject(
const Expr *E,
bool Mod)
const {
13702 if (
const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
13703 if (Mod && (UO->getOpcode() == UO_PreInc || UO->getOpcode() == UO_PreDec))
13704 return getObject(UO->getSubExpr(), Mod);
13705 }
else if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
13706 if (BO->getOpcode() == BO_Comma)
13707 return getObject(BO->getRHS(), Mod);
13708 if (Mod && BO->isAssignmentOp())
13709 return getObject(BO->getLHS(), Mod);
13710 }
else if (
const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
13713 return ME->getMemberDecl();
13714 }
else if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
13723 void addUsage(Object O, UsageInfo &UI,
const Expr *UsageExpr, UsageKind UK) {
13725 Usage &U = UI.Uses[UK];
13726 if (!U.UsageExpr || !Tree.isUnsequenced(Region, U.Seq)) {
13730 if (UK == UK_ModAsSideEffect && ModAsSideEffect)
13731 ModAsSideEffect->push_back(std::make_pair(O, U));
13733 U.UsageExpr = UsageExpr;
13743 void checkUsage(Object O, UsageInfo &UI,
const Expr *UsageExpr,
13744 UsageKind OtherKind,
bool IsModMod) {
13748 const Usage &U = UI.Uses[OtherKind];
13749 if (!U.UsageExpr || !Tree.isUnsequenced(Region, U.Seq))
13752 const Expr *Mod = U.UsageExpr;
13753 const Expr *ModOrUse = UsageExpr;
13754 if (OtherKind == UK_Use)
13755 std::swap(Mod, ModOrUse);
13759 SemaRef.
PDiag(IsModMod ? diag::warn_unsequenced_mod_mod
13760 : diag::warn_unsequenced_mod_use)
13761 << O << SourceRange(ModOrUse->
getExprLoc()));
13762 UI.Diagnosed =
true;
13791 void notePreUse(Object O,
const Expr *UseExpr) {
13792 UsageInfo &UI = UsageMap[O];
13794 checkUsage(O, UI, UseExpr, UK_ModAsValue,
false);
13797 void notePostUse(Object O,
const Expr *UseExpr) {
13798 UsageInfo &UI = UsageMap[O];
13799 checkUsage(O, UI, UseExpr, UK_ModAsSideEffect,
13801 addUsage(O, UI, UseExpr, UK_Use);
13804 void notePreMod(Object O,
const Expr *ModExpr) {
13805 UsageInfo &UI = UsageMap[O];
13807 checkUsage(O, UI, ModExpr, UK_ModAsValue,
true);
13808 checkUsage(O, UI, ModExpr, UK_Use,
false);
13811 void notePostMod(Object O,
const Expr *ModExpr, UsageKind UK) {
13812 UsageInfo &UI = UsageMap[O];
13813 checkUsage(O, UI, ModExpr, UK_ModAsSideEffect,
13815 addUsage(O, UI, ModExpr, UK);
13819 SequenceChecker(Sema &S,
const Expr *E,
13820 SmallVectorImpl<const Expr *> &WorkList)
13821 :
Base(S.Context), SemaRef(S), Region(Tree.root()), WorkList(WorkList) {
13825 (void)this->WorkList;
13828 void VisitStmt(
const Stmt *S) {
13832 void VisitExpr(
const Expr *E) {
13834 Base::VisitStmt(E);
13837 void VisitCoroutineSuspendExpr(
const CoroutineSuspendExpr *CSE) {
13838 for (
auto *Sub : CSE->
children()) {
13839 const Expr *ChildExpr = dyn_cast_or_null<Expr>(Sub);
13854 void VisitCastExpr(
const CastExpr *E) {
13866 void VisitSequencedExpressions(
const Expr *SequencedBefore,
13867 const Expr *SequencedAfter) {
13868 SequenceTree::Seq BeforeRegion = Tree.allocate(Region);
13869 SequenceTree::Seq AfterRegion = Tree.allocate(Region);
13870 SequenceTree::Seq OldRegion = Region;
13873 SequencedSubexpression SeqBefore(*
this);
13874 Region = BeforeRegion;
13875 Visit(SequencedBefore);
13878 Region = AfterRegion;
13879 Visit(SequencedAfter);
13881 Region = OldRegion;
13883 Tree.merge(BeforeRegion);
13884 Tree.merge(AfterRegion);
13887 void VisitArraySubscriptExpr(
const ArraySubscriptExpr *ASE) {
13892 VisitSequencedExpressions(ASE->
getLHS(), ASE->
getRHS());
13899 void VisitBinPtrMemD(
const BinaryOperator *BO) { VisitBinPtrMem(BO); }
13900 void VisitBinPtrMemI(
const BinaryOperator *BO) { VisitBinPtrMem(BO); }
13901 void VisitBinPtrMem(
const BinaryOperator *BO) {
13906 VisitSequencedExpressions(BO->
getLHS(), BO->
getRHS());
13913 void VisitBinShl(
const BinaryOperator *BO) { VisitBinShlShr(BO); }
13914 void VisitBinShr(
const BinaryOperator *BO) { VisitBinShlShr(BO); }
13915 void VisitBinShlShr(
const BinaryOperator *BO) {
13919 VisitSequencedExpressions(BO->
getLHS(), BO->
getRHS());
13926 void VisitBinComma(
const BinaryOperator *BO) {
13931 VisitSequencedExpressions(BO->
getLHS(), BO->
getRHS());
13934 void VisitBinAssign(
const BinaryOperator *BO) {
13935 SequenceTree::Seq RHSRegion;
13936 SequenceTree::Seq LHSRegion;
13938 RHSRegion = Tree.allocate(Region);
13939 LHSRegion = Tree.allocate(Region);
13941 RHSRegion = Region;
13942 LHSRegion = Region;
13944 SequenceTree::Seq OldRegion = Region;
13960 SequencedSubexpression SeqBefore(*
this);
13961 Region = RHSRegion;
13965 Region = LHSRegion;
13969 notePostUse(O, BO);
13973 Region = LHSRegion;
13977 notePostUse(O, BO);
13979 Region = RHSRegion;
13987 Region = OldRegion;
13991 : UK_ModAsSideEffect);
13993 Tree.merge(RHSRegion);
13994 Tree.merge(LHSRegion);
13998 void VisitCompoundAssignOperator(
const CompoundAssignOperator *CAO) {
13999 VisitBinAssign(CAO);
14002 void VisitUnaryPreInc(
const UnaryOperator *UO) { VisitUnaryPreIncDec(UO); }
14003 void VisitUnaryPreDec(
const UnaryOperator *UO) { VisitUnaryPreIncDec(UO); }
14004 void VisitUnaryPreIncDec(
const UnaryOperator *UO) {
14007 return VisitExpr(UO);
14015 : UK_ModAsSideEffect);
14018 void VisitUnaryPostInc(
const UnaryOperator *UO) { VisitUnaryPostIncDec(UO); }
14019 void VisitUnaryPostDec(
const UnaryOperator *UO) { VisitUnaryPostIncDec(UO); }
14020 void VisitUnaryPostIncDec(
const UnaryOperator *UO) {
14023 return VisitExpr(UO);
14027 notePostMod(O, UO, UK_ModAsSideEffect);
14030 void VisitBinLOr(
const BinaryOperator *BO) {
14036 SequenceTree::Seq LHSRegion = Tree.allocate(Region);
14037 SequenceTree::Seq RHSRegion = Tree.allocate(Region);
14038 SequenceTree::Seq OldRegion = Region;
14040 EvaluationTracker Eval(*
this);
14042 SequencedSubexpression Sequenced(*
this);
14043 Region = LHSRegion;
14050 bool EvalResult =
false;
14051 bool EvalOK = Eval.evaluate(BO->
getLHS(), EvalResult);
14052 bool ShouldVisitRHS = !EvalOK || !EvalResult;
14053 if (ShouldVisitRHS) {
14054 Region = RHSRegion;
14058 Region = OldRegion;
14059 Tree.merge(LHSRegion);
14060 Tree.merge(RHSRegion);
14063 void VisitBinLAnd(
const BinaryOperator *BO) {
14069 SequenceTree::Seq LHSRegion = Tree.allocate(Region);
14070 SequenceTree::Seq RHSRegion = Tree.allocate(Region);
14071 SequenceTree::Seq OldRegion = Region;
14073 EvaluationTracker Eval(*
this);
14075 SequencedSubexpression Sequenced(*
this);
14076 Region = LHSRegion;
14082 bool EvalResult =
false;
14083 bool EvalOK = Eval.evaluate(BO->
getLHS(), EvalResult);
14084 bool ShouldVisitRHS = !EvalOK || EvalResult;
14085 if (ShouldVisitRHS) {
14086 Region = RHSRegion;
14090 Region = OldRegion;
14091 Tree.merge(LHSRegion);
14092 Tree.merge(RHSRegion);
14095 void VisitAbstractConditionalOperator(
const AbstractConditionalOperator *CO) {
14100 SequenceTree::Seq ConditionRegion = Tree.allocate(Region);
14116 SequenceTree::Seq TrueRegion = Tree.allocate(Region);
14117 SequenceTree::Seq FalseRegion = Tree.allocate(Region);
14118 SequenceTree::Seq OldRegion = Region;
14120 EvaluationTracker Eval(*
this);
14122 SequencedSubexpression Sequenced(*
this);
14123 Region = ConditionRegion;
14133 bool EvalResult =
false;
14134 bool EvalOK = Eval.evaluate(CO->
getCond(), EvalResult);
14135 bool ShouldVisitTrueExpr = !EvalOK || EvalResult;
14136 bool ShouldVisitFalseExpr = !EvalOK || !EvalResult;
14137 if (ShouldVisitTrueExpr) {
14138 Region = TrueRegion;
14141 if (ShouldVisitFalseExpr) {
14142 Region = FalseRegion;
14146 Region = OldRegion;
14147 Tree.merge(ConditionRegion);
14148 Tree.merge(TrueRegion);
14149 Tree.merge(FalseRegion);
14152 void VisitCallExpr(
const CallExpr *CE) {
14164 SequencedSubexpression Sequenced(*
this);
14169 SequenceTree::Seq CalleeRegion;
14170 SequenceTree::Seq OtherRegion;
14171 if (SemaRef.getLangOpts().CPlusPlus17) {
14172 CalleeRegion = Tree.allocate(Region);
14173 OtherRegion = Tree.allocate(Region);
14175 CalleeRegion = Region;
14176 OtherRegion = Region;
14178 SequenceTree::Seq OldRegion = Region;
14181 Region = CalleeRegion;
14183 SequencedSubexpression Sequenced(*this);
14184 Visit(CE->getCallee());
14186 Visit(CE->getCallee());
14190 Region = OtherRegion;
14194 Region = OldRegion;
14196 Tree.merge(CalleeRegion);
14197 Tree.merge(OtherRegion);
14215 return VisitCallExpr(CXXOCE);
14226 case OO_MinusEqual:
14228 case OO_SlashEqual:
14229 case OO_PercentEqual:
14230 case OO_CaretEqual:
14233 case OO_LessLessEqual:
14234 case OO_GreaterGreaterEqual:
14235 SequencingKind = RHSBeforeLHS;
14239 case OO_GreaterGreater:
14245 SequencingKind = LHSBeforeRHS;
14249 SequencingKind = LHSBeforeRest;
14253 SequencingKind = NoSequencing;
14257 if (SequencingKind == NoSequencing)
14258 return VisitCallExpr(CXXOCE);
14261 SequencedSubexpression Sequenced(*
this);
14264 assert(SemaRef.getLangOpts().CPlusPlus17 &&
14265 "Should only get there with C++17 and above!");
14266 assert((CXXOCE->getNumArgs() == 2 || CXXOCE->getOperator() == OO_Call) &&
14267 "Should only get there with an overloaded binary operator"
14268 " or an overloaded call operator!");
14270 if (SequencingKind == LHSBeforeRest) {
14271 assert(CXXOCE->getOperator() == OO_Call &&
14272 "We should only have an overloaded call operator here!");
14281 SequenceTree::Seq PostfixExprRegion = Tree.allocate(Region);
14282 SequenceTree::Seq ArgsRegion = Tree.allocate(Region);
14283 SequenceTree::Seq OldRegion = Region;
14285 assert(CXXOCE->getNumArgs() >= 1 &&
14286 "An overloaded call operator must have at least one argument"
14287 " for the postfix-expression!");
14288 const Expr *PostfixExpr = CXXOCE->getArgs()[0];
14289 llvm::ArrayRef<const Expr *> Args(CXXOCE->getArgs() + 1,
14290 CXXOCE->getNumArgs() - 1);
14294 Region = PostfixExprRegion;
14295 SequencedSubexpression Sequenced(*this);
14296 Visit(PostfixExpr);
14300 Region = ArgsRegion;
14301 for (const Expr *Arg : Args)
14304 Region = OldRegion;
14305 Tree.merge(PostfixExprRegion);
14306 Tree.merge(ArgsRegion);
14308 assert(CXXOCE->getNumArgs() == 2 &&
14309 "Should only have two arguments here!");
14310 assert((SequencingKind == LHSBeforeRHS ||
14311 SequencingKind == RHSBeforeLHS) &&
14312 "Unexpected sequencing kind!");
14316 const Expr *E1 = CXXOCE->getArg(0);
14317 const Expr *E2 = CXXOCE->getArg(1);
14318 if (SequencingKind == RHSBeforeLHS)
14321 return VisitSequencedExpressions(E1, E2);
14328 SequencedSubexpression Sequenced(*
this);
14331 return VisitExpr(CCE);
14334 SequenceExpressionsInOrder(
14340 return VisitExpr(ILE);
14343 SequenceExpressionsInOrder(ILE->
inits());
14355 SequenceTree::Seq Parent = Region;
14356 for (
const Expr *E : ExpressionList) {
14359 Region = Tree.allocate(Parent);
14360 Elts.push_back(Region);
14366 for (
unsigned I = 0; I < Elts.size(); ++I)
14367 Tree.merge(Elts[I]);
14371SequenceChecker::UsageInfo::UsageInfo() =
default;
14375void Sema::CheckUnsequencedOperations(
const Expr *E) {
14376 SmallVector<const Expr *, 8> WorkList;
14377 WorkList.push_back(E);
14378 while (!WorkList.empty()) {
14379 const Expr *Item = WorkList.pop_back_val();
14380 SequenceChecker(*
this, Item, WorkList);
14385 bool IsConstexpr) {
14388 CheckImplicitConversions(E, CheckLoc);
14390 CheckUnsequencedOperations(E);
14392 CheckForIntOverflow(E);
14405 if (
const auto *PointerTy = dyn_cast<PointerType>(PType)) {
14409 if (
const auto *ReferenceTy = dyn_cast<ReferenceType>(PType)) {
14413 if (
const auto *ParenTy = dyn_cast<ParenType>(PType)) {
14427 S.
Diag(Loc, diag::err_array_star_in_function_definition);
14431 bool CheckParameterNames) {
14432 bool HasInvalidParm =
false;
14434 assert(Param &&
"null in a parameter list");
14443 if (!Param->isInvalidDecl() &&
14445 diag::err_typecheck_decl_incomplete_type) ||
14447 diag::err_abstract_type_in_decl,
14449 Param->setInvalidDecl();
14450 HasInvalidParm =
true;
14455 if (CheckParameterNames && Param->getIdentifier() ==
nullptr &&
14459 Diag(Param->getLocation(), diag::ext_parameter_name_omitted_c23);
14467 QualType PType = Param->getOriginalType();
14475 if (!Param->isInvalidDecl()) {
14476 if (
CXXRecordDecl *ClassDecl = Param->getType()->getAsCXXRecordDecl()) {
14477 if (!ClassDecl->isInvalidDecl() &&
14478 !ClassDecl->hasIrrelevantDestructor() &&
14479 !ClassDecl->isDependentContext() &&
14480 ClassDecl->isParamDestroyedInCallee()) {
14492 if (
const auto *
Attr = Param->getAttr<PassObjectSizeAttr>())
14493 if (!Param->getType().isConstQualified())
14494 Diag(Param->getLocation(), diag::err_attribute_pointers_only)
14498 if (
LangOpts.CPlusPlus && !Param->isInvalidDecl()) {
14503 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC->
getParent()))
14504 CheckShadowInheritedFields(Param->getLocation(), Param->getDeclName(),
14509 if (!Param->isInvalidDecl() &&
14510 Param->getOriginalType()->isWebAssemblyTableType()) {
14511 Param->setInvalidDecl();
14512 HasInvalidParm =
true;
14513 Diag(Param->getLocation(), diag::err_wasm_table_as_function_parameter);
14517 return HasInvalidParm;
14520std::optional<std::pair<
14529static std::pair<CharUnits, CharUnits>
14537 if (
Base->isVirtual()) {
14544 BaseAlignment = std::min(BaseAlignment, NonVirtualAlignment);
14551 DerivedType =
Base->getType();
14554 return std::make_pair(BaseAlignment, Offset);
14558static std::optional<std::pair<CharUnits, CharUnits>>
14564 return std::nullopt;
14569 return std::nullopt;
14573 CharUnits Offset = EltSize * IdxRes->getExtValue();
14576 return std::make_pair(P->first, P->second + Offset);
14582 return std::make_pair(
14583 P->first.alignmentAtOffset(P->second).alignmentAtOffset(EltSize),
14589std::optional<std::pair<
14597 case Stmt::CStyleCastExprClass:
14598 case Stmt::CXXStaticCastExprClass:
14599 case Stmt::ImplicitCastExprClass: {
14601 const Expr *From = CE->getSubExpr();
14602 switch (CE->getCastKind()) {
14607 case CK_UncheckedDerivedToBase:
14608 case CK_DerivedToBase: {
14618 case Stmt::ArraySubscriptExprClass: {
14623 case Stmt::DeclRefExprClass: {
14627 if (!VD->getType()->isReferenceType()) {
14629 if (VD->hasDependentAlignment())
14638 case Stmt::MemberExprClass: {
14640 auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
14644 std::optional<std::pair<CharUnits, CharUnits>> P;
14653 return std::make_pair(P->first,
14656 case Stmt::UnaryOperatorClass: {
14666 case Stmt::BinaryOperatorClass: {
14678 return std::nullopt;
14683std::optional<std::pair<
14692 case Stmt::CStyleCastExprClass:
14693 case Stmt::CXXStaticCastExprClass:
14694 case Stmt::ImplicitCastExprClass: {
14696 const Expr *From = CE->getSubExpr();
14697 switch (CE->getCastKind()) {
14702 case CK_ArrayToPointerDecay:
14704 case CK_UncheckedDerivedToBase:
14705 case CK_DerivedToBase: {
14715 case Stmt::CXXThisExprClass: {
14720 case Stmt::UnaryOperatorClass: {
14726 case Stmt::BinaryOperatorClass: {
14735 if (Opcode == BO_Add && !RHS->getType()->isIntegralOrEnumerationType())
14736 std::swap(LHS, RHS);
14746 return std::nullopt;
14751 std::optional<std::pair<CharUnits, CharUnits>> P =
14755 return P->first.alignmentAtOffset(P->second);
14773 if (!DestPtr)
return;
14779 if (DestAlign.
isOne())
return;
14783 if (!SrcPtr)
return;
14794 if (SrcAlign >= DestAlign)
return;
14799 <<
static_cast<unsigned>(DestAlign.
getQuantity())
14803void Sema::CheckArrayAccess(
const Expr *BaseExpr,
const Expr *IndexExpr,
14805 bool AllowOnePastEnd,
bool IndexNegated) {
14814 const Type *EffectiveType =
14818 Context.getAsConstantArrayType(BaseExpr->
getType());
14821 StrictFlexArraysLevel =
getLangOpts().getStrictFlexArraysLevel();
14823 const Type *BaseType =
14825 bool IsUnboundedArray =
14827 Context, StrictFlexArraysLevel,
14830 (!IsUnboundedArray && BaseType->isDependentType()))
14838 if (IndexNegated) {
14839 index.setIsUnsigned(
false);
14843 if (IsUnboundedArray) {
14846 if (
index.isUnsigned() || !
index.isNegative()) {
14848 unsigned AddrBits = ASTC.getTargetInfo().getPointerWidth(
14850 if (
index.getBitWidth() < AddrBits)
14852 std::optional<CharUnits> ElemCharUnits =
14853 ASTC.getTypeSizeInCharsIfKnown(EffectiveType);
14856 if (!ElemCharUnits || ElemCharUnits->isZero())
14858 llvm::APInt ElemBytes(
index.getBitWidth(), ElemCharUnits->getQuantity());
14863 if (
index.getActiveBits() <= AddrBits) {
14865 llvm::APInt Product(
index);
14867 Product = Product.umul_ov(ElemBytes, Overflow);
14868 if (!Overflow && Product.getActiveBits() <= AddrBits)
14874 llvm::APInt MaxElems = llvm::APInt::getMaxValue(AddrBits);
14875 MaxElems = MaxElems.zext(std::max(AddrBits + 1, ElemBytes.getBitWidth()));
14877 ElemBytes = ElemBytes.zextOrTrunc(MaxElems.getBitWidth());
14878 MaxElems = MaxElems.udiv(ElemBytes);
14881 ASE ? diag::warn_array_index_exceeds_max_addressable_bounds
14882 : diag::warn_ptr_arith_exceeds_max_addressable_bounds;
14888 <<
toString(index, 10,
true) << AddrBits
14889 << (
unsigned)ASTC.toBits(*ElemCharUnits)
14892 << (
unsigned)MaxElems.getLimitedValue(~0U)
14895 const NamedDecl *ND =
nullptr;
14897 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
14899 if (
const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
14901 if (
const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
14902 ND = ME->getMemberDecl();
14906 PDiag(diag::note_array_declared_here) << ND);
14911 if (index.isUnsigned() || !index.isNegative()) {
14921 llvm::APInt size = ArrayTy->
getSize();
14923 if (BaseType != EffectiveType) {
14931 if (!ptrarith_typesize)
14932 ptrarith_typesize =
Context.getCharWidth();
14934 if (ptrarith_typesize != array_typesize) {
14936 uint64_t ratio = array_typesize / ptrarith_typesize;
14940 if (ptrarith_typesize * ratio == array_typesize)
14941 size *= llvm::APInt(size.getBitWidth(), ratio);
14945 if (size.getBitWidth() > index.getBitWidth())
14946 index = index.zext(size.getBitWidth());
14947 else if (size.getBitWidth() < index.getBitWidth())
14948 size = size.zext(index.getBitWidth());
14954 if (AllowOnePastEnd ? index.ule(size) : index.ult(size))
14961 SourceLocation RBracketLoc =
SourceMgr.getSpellingLoc(
14963 if (
SourceMgr.isInSystemHeader(RBracketLoc)) {
14964 SourceLocation IndexLoc =
14966 if (
SourceMgr.isWrittenInSameFile(RBracketLoc, IndexLoc))
14971 unsigned DiagID = ASE ? diag::warn_array_index_exceeds_bounds
14972 : diag::warn_ptr_arith_exceeds_bounds;
14973 unsigned CastMsg = (!ASE || BaseType == EffectiveType) ? 0 : 1;
14974 QualType CastMsgTy = ASE ? ASE->
getLHS()->
getType() : QualType();
14981 unsigned DiagID = diag::warn_array_index_precedes_bounds;
14983 DiagID = diag::warn_ptr_arith_precedes_bounds;
14984 if (index.isNegative()) index = -index;
14992 const NamedDecl *ND =
nullptr;
14994 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
14996 if (
const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
14998 if (
const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
14999 ND = ME->getMemberDecl();
15003 PDiag(diag::note_array_declared_here) << ND);
15006void Sema::CheckArrayAccess(
const Expr *
expr) {
15007 int AllowOnePastEnd = 0;
15009 expr =
expr->IgnoreParenImpCasts();
15010 switch (
expr->getStmtClass()) {
15011 case Stmt::ArraySubscriptExprClass: {
15014 AllowOnePastEnd > 0);
15018 case Stmt::MemberExprClass: {
15022 case Stmt::ArraySectionExprClass: {
15028 nullptr, AllowOnePastEnd > 0);
15031 case Stmt::UnaryOperatorClass: {
15047 case Stmt::ConditionalOperatorClass: {
15049 if (
const Expr *lhs = cond->
getLHS())
15050 CheckArrayAccess(lhs);
15051 if (
const Expr *rhs = cond->
getRHS())
15052 CheckArrayAccess(rhs);
15055 case Stmt::CXXOperatorCallExprClass: {
15057 for (
const auto *Arg : OCE->arguments())
15058 CheckArrayAccess(Arg);
15068 Expr *RHS,
bool isProperty) {
15080 S.
Diag(Loc, diag::warn_arc_literal_assign)
15082 << (isProperty ? 0 : 1)
15090 Expr *RHS,
bool isProperty) {
15093 if (
cast->getCastKind() == CK_ARCConsumeObject) {
15094 S.
Diag(Loc, diag::warn_arc_retained_assign)
15096 << (isProperty ? 0 : 1)
15100 RHS =
cast->getSubExpr();
15142 if (!
Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
15171 if (
cast->getCastKind() == CK_ARCConsumeObject) {
15172 Diag(Loc, diag::warn_arc_retained_property_assign)
15176 RHS =
cast->getSubExpr();
15199 bool StmtLineInvalid;
15200 unsigned StmtLine = SourceMgr.getPresumedLineNumber(StmtLoc,
15202 if (StmtLineInvalid)
15205 bool BodyLineInvalid;
15206 unsigned BodyLine = SourceMgr.getSpellingLineNumber(Body->
getSemiLoc(),
15208 if (BodyLineInvalid)
15212 if (StmtLine != BodyLine)
15227 const NullStmt *NBody = dyn_cast<NullStmt>(Body);
15236 Diag(NBody->
getSemiLoc(), diag::note_empty_body_on_separate_line);
15240 const Stmt *PossibleBody) {
15246 if (
const ForStmt *FS = dyn_cast<ForStmt>(S)) {
15247 StmtLoc = FS->getRParenLoc();
15248 Body = FS->getBody();
15249 DiagID = diag::warn_empty_for_body;
15250 }
else if (
const WhileStmt *WS = dyn_cast<WhileStmt>(S)) {
15251 StmtLoc = WS->getRParenLoc();
15252 Body = WS->getBody();
15253 DiagID = diag::warn_empty_while_body;
15258 const NullStmt *NBody = dyn_cast<NullStmt>(Body);
15282 if (!ProbableTypo) {
15283 bool BodyColInvalid;
15284 unsigned BodyCol =
SourceMgr.getPresumedColumnNumber(
15286 if (BodyColInvalid)
15289 bool StmtColInvalid;
15292 if (StmtColInvalid)
15295 if (BodyCol > StmtCol)
15296 ProbableTypo =
true;
15299 if (ProbableTypo) {
15301 Diag(NBody->
getSemiLoc(), diag::note_empty_body_on_separate_line);
15309 if (
Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess, OpLoc))
15321 if (
const auto *CE = dyn_cast<CallExpr>(RHSExpr);
15323 RHSExpr = CE->
getArg(0);
15324 else if (
const auto *CXXSCE = dyn_cast<CXXStaticCastExpr>(RHSExpr);
15325 CXXSCE && CXXSCE->isXValue())
15326 RHSExpr = CXXSCE->getSubExpr();
15330 const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
15331 const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);
15334 if (LHSDeclRef && RHSDeclRef) {
15341 auto D =
Diag(OpLoc, diag::warn_self_move)
15357 const Expr *LHSBase = LHSExpr;
15358 const Expr *RHSBase = RHSExpr;
15359 const MemberExpr *LHSME = dyn_cast<MemberExpr>(LHSExpr);
15360 const MemberExpr *RHSME = dyn_cast<MemberExpr>(RHSExpr);
15361 if (!LHSME || !RHSME)
15364 while (LHSME && RHSME) {
15371 LHSME = dyn_cast<MemberExpr>(LHSBase);
15372 RHSME = dyn_cast<MemberExpr>(RHSBase);
15375 LHSDeclRef = dyn_cast<DeclRefExpr>(LHSBase);
15376 RHSDeclRef = dyn_cast<DeclRefExpr>(RHSBase);
15377 if (LHSDeclRef && RHSDeclRef) {
15384 Diag(OpLoc, diag::warn_self_move)
15391 Diag(OpLoc, diag::warn_self_move)
15415 bool AreUnionMembers =
false) {
15419 assert(((Field1Parent->isStructureOrClassType() &&
15420 Field2Parent->isStructureOrClassType()) ||
15421 (Field1Parent->isUnionType() && Field2Parent->isUnionType())) &&
15422 "Can't evaluate layout compatibility between a struct field and a "
15424 assert(((!AreUnionMembers && Field1Parent->isStructureOrClassType()) ||
15425 (AreUnionMembers && Field1Parent->isUnionType())) &&
15426 "AreUnionMembers should be 'true' for union fields (only).");
15440 if (Bits1 != Bits2)
15444 if (Field1->
hasAttr<clang::NoUniqueAddressAttr>() ||
15445 Field2->
hasAttr<clang::NoUniqueAddressAttr>())
15448 if (!AreUnionMembers &&
15460 if (
const CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(RD1))
15461 RD1 = D1CXX->getStandardLayoutBaseWithFields();
15463 if (
const CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(RD2))
15464 RD2 = D2CXX->getStandardLayoutBaseWithFields();
15469 return isLayoutCompatible(C, F1, F2);
15480 for (
auto *Field1 : RD1->
fields()) {
15481 auto I = UnmatchedFields.begin();
15482 auto E = UnmatchedFields.end();
15484 for ( ; I != E; ++I) {
15486 bool Result = UnmatchedFields.erase(*I);
15496 return UnmatchedFields.empty();
15522 if (
C.hasSameType(T1, T2))
15531 if (TC1 == Type::Enum)
15533 if (TC1 == Type::Record) {
15552 QualType BaseT =
Base->getType()->getCanonicalTypeUnqualified();
15583 const ValueDecl **VD, uint64_t *MagicValue,
15584 bool isConstantEvaluated) {
15592 case Stmt::UnaryOperatorClass: {
15601 case Stmt::DeclRefExprClass: {
15607 case Stmt::IntegerLiteralClass: {
15609 llvm::APInt MagicValueAPInt = IL->
getValue();
15610 if (MagicValueAPInt.getActiveBits() <= 64) {
15611 *MagicValue = MagicValueAPInt.getZExtValue();
15617 case Stmt::BinaryConditionalOperatorClass:
15618 case Stmt::ConditionalOperatorClass: {
15623 isConstantEvaluated)) {
15633 case Stmt::BinaryOperatorClass: {
15636 TypeExpr = BO->
getRHS();
15666 const llvm::DenseMap<Sema::TypeTagMagicValue, Sema::TypeTagData>
15669 bool isConstantEvaluated) {
15670 FoundWrongKind =
false;
15675 uint64_t MagicValue;
15677 if (!
FindTypeTagExpr(TypeExpr, Ctx, &VD, &MagicValue, isConstantEvaluated))
15681 if (TypeTagForDatatypeAttr *I = VD->
getAttr<TypeTagForDatatypeAttr>()) {
15682 if (I->getArgumentKind() != ArgumentKind) {
15683 FoundWrongKind =
true;
15686 TypeInfo.Type = I->getMatchingCType();
15687 TypeInfo.LayoutCompatible = I->getLayoutCompatible();
15688 TypeInfo.MustBeNull = I->getMustBeNull();
15699 MagicValues->find(std::make_pair(ArgumentKind, MagicValue));
15700 if (I == MagicValues->end())
15709 bool LayoutCompatible,
15711 if (!TypeTagForDatatypeMagicValues)
15712 TypeTagForDatatypeMagicValues.reset(
15713 new llvm::DenseMap<TypeTagMagicValue, TypeTagData>);
15716 (*TypeTagForDatatypeMagicValues)[Magic] =
15732 return (T1Kind == BuiltinType::SChar && T2Kind == BuiltinType::Char_S) ||
15733 (T1Kind == BuiltinType::UChar && T2Kind == BuiltinType::Char_U) ||
15734 (T1Kind == BuiltinType::Char_U && T2Kind == BuiltinType::UChar) ||
15735 (T1Kind == BuiltinType::Char_S && T2Kind == BuiltinType::SChar);
15738void Sema::CheckArgumentWithTypeTag(
const ArgumentWithTypeTagAttr *
Attr,
15741 const IdentifierInfo *ArgumentKind = Attr->getArgumentKind();
15742 bool IsPointerAttr = Attr->getIsPointer();
15745 unsigned TypeTagIdxAST = Attr->getTypeTagIdx().getASTIndex();
15746 if (TypeTagIdxAST >= ExprArgs.size()) {
15747 Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
15748 << 0 << Attr->getTypeTagIdx().getSourceIndex();
15751 const Expr *TypeTagExpr = ExprArgs[TypeTagIdxAST];
15752 bool FoundWrongKind;
15755 TypeTagForDatatypeMagicValues.get(), FoundWrongKind,
15757 if (FoundWrongKind)
15759 diag::warn_type_tag_for_datatype_wrong_kind)
15765 unsigned ArgumentIdxAST = Attr->getArgumentIdx().getASTIndex();
15766 if (ArgumentIdxAST >= ExprArgs.size()) {
15767 Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
15768 << 1 << Attr->getArgumentIdx().getSourceIndex();
15771 const Expr *ArgumentExpr = ExprArgs[ArgumentIdxAST];
15772 if (IsPointerAttr) {
15774 if (
const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgumentExpr))
15775 if (ICE->getType()->isVoidPointerType() &&
15776 ICE->getCastKind() == CK_BitCast)
15777 ArgumentExpr = ICE->getSubExpr();
15779 QualType ArgumentType = ArgumentExpr->
getType();
15785 if (TypeInfo.MustBeNull) {
15790 diag::warn_type_safety_null_pointer_required)
15798 QualType RequiredType = TypeInfo.Type;
15800 RequiredType =
Context.getPointerType(RequiredType);
15802 bool mismatch =
false;
15803 if (!TypeInfo.LayoutCompatible) {
15804 mismatch = !
Context.hasSameType(ArgumentType, RequiredType);
15825 Diag(ArgumentExpr->
getExprLoc(), diag::warn_type_safety_type_mismatch)
15826 << ArgumentType << ArgumentKind
15827 << TypeInfo.LayoutCompatible << RequiredType
15845 Diag(m.E->getBeginLoc(), diag::warn_taking_address_of_packed_member)
15853 if (!
T->isPointerType() && !
T->isIntegerType() && !
T->isDependentType())
15859 auto &MisalignedMembersForExpr =
15861 auto *MA = llvm::find(MisalignedMembersForExpr, MisalignedMember(Op));
15862 if (MA != MisalignedMembersForExpr.end() &&
15863 (
T->isDependentType() ||
T->isIntegerType() ||
15864 (
T->isPointerType() && (
T->getPointeeType()->isIncompleteType() ||
15866 T->getPointeeType()) <= MA->Alignment))))
15867 MisalignedMembersForExpr.erase(MA);
15876 const auto *ME = dyn_cast<MemberExpr>(E);
15888 bool AnyIsPacked =
false;
15890 QualType BaseType = ME->getBase()->getType();
15891 if (BaseType->isDependentType())
15895 auto *RD = BaseType->castAsRecordDecl();
15900 auto *FD = dyn_cast<FieldDecl>(MD);
15906 AnyIsPacked || (RD->
hasAttr<PackedAttr>() || MD->
hasAttr<PackedAttr>());
15907 ReverseMemberChain.push_back(FD);
15910 ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParens());
15912 assert(TopME &&
"We did not compute a topmost MemberExpr!");
15919 const auto *DRE = dyn_cast<DeclRefExpr>(TopBase);
15930 if (ExpectedAlignment.
isOne())
15935 for (
const FieldDecl *FD : llvm::reverse(ReverseMemberChain))
15936 Offset +=
Context.toCharUnitsFromBits(
Context.getFieldOffset(FD));
15940 Context.getCanonicalTagType(ReverseMemberChain.back()->getParent()));
15944 if (DRE && !TopME->
isArrow()) {
15947 CompleteObjectAlignment =
15948 std::max(CompleteObjectAlignment,
Context.getDeclAlign(VD));
15952 if (!Offset.isMultipleOf(ExpectedAlignment) ||
15955 CompleteObjectAlignment < ExpectedAlignment) {
15966 for (
FieldDecl *FDI : ReverseMemberChain) {
15967 if (FDI->hasAttr<PackedAttr>() ||
15968 FDI->getParent()->hasAttr<PackedAttr>()) {
15970 Alignment = std::min(
Context.getTypeAlignInChars(FD->
getType()),
15976 assert(FD &&
"We did not find a packed FieldDecl!");
15977 Action(E, FD->
getParent(), FD, Alignment);
15981void Sema::CheckAddressOfPackedMember(
Expr *rhs) {
15982 using namespace std::placeholders;
15985 rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*
this), _1,
16021bool Sema::BuiltinElementwiseMath(
CallExpr *TheCall,
16022 EltwiseBuiltinArgTyRestriction ArgTyRestr) {
16035 if (
auto *VecTy0 = (*Res)->getAs<
VectorType>())
16036 TheCall->
setType(VecTy0->getElementType());
16049 return S.
Diag(Loc, diag::err_conv_mixed_enum_types)
16066 assert(!Args.empty() &&
"Should have at least one argument.");
16068 Expr *Arg0 = Args.front();
16071 auto EmitError = [&](
Expr *ArgI) {
16073 diag::err_typecheck_call_different_arg_types)
16074 << Arg0->
getType() << ArgI->getType();
16079 for (
Expr *ArgI : Args.drop_front())
16090 for (
Expr *ArgI : Args.drop_front()) {
16091 const auto *VecI = ArgI->getType()->getAs<
VectorType>();
16094 VecI->getElementType()) ||
16095 Vec0->getNumElements() != VecI->getNumElements()) {
16104std::optional<QualType>
16108 return std::nullopt;
16112 return std::nullopt;
16115 for (
int I = 0; I < 2; ++I) {
16119 return std::nullopt;
16120 Args[I] = Converted.
get();
16127 return std::nullopt;
16130 return std::nullopt;
16132 TheCall->
setArg(0, Args[0]);
16133 TheCall->
setArg(1, Args[1]);
16144 TheCall->
getArg(1), Loc) ||
16146 TheCall->
getArg(2), Loc))
16150 for (
int I = 0; I < 3; ++I) {
16155 Args[I] = Converted.
get();
16158 int ArgOrdinal = 1;
16159 for (
Expr *Arg : Args) {
16161 ArgTyRestr, ArgOrdinal++))
16168 for (
int I = 0; I < 3; ++I)
16169 TheCall->
setArg(I, Args[I]);
16175bool Sema::PrepareBuiltinReduceMathOneArgCall(
CallExpr *TheCall) {
16187bool Sema::BuiltinNonDeterministicValue(
CallExpr *TheCall) {
16196 diag::err_builtin_invalid_arg_type)
16197 << 1 << 2 << 1 << 1 << TyArg;
16211 Expr *Matrix = MatrixArg.
get();
16213 auto *MType = Matrix->
getType()->
getAs<ConstantMatrixType>();
16216 << 1 << 3 << 0 << 0
16223 QualType ResultType =
Context.getConstantMatrixType(
16224 MType->getElementType(), MType->getNumColumns(), MType->getNumRows());
16227 TheCall->
setType(ResultType);
16230 TheCall->
setArg(0, Matrix);
16235static std::optional<unsigned>
16243 uint64_t
Dim =
Value->getZExtValue();
16262 unsigned PtrArgIdx = 0;
16263 Expr *PtrExpr = TheCall->
getArg(PtrArgIdx);
16264 Expr *RowsExpr = TheCall->
getArg(1);
16265 Expr *ColumnsExpr = TheCall->
getArg(2);
16266 Expr *StrideExpr = TheCall->
getArg(3);
16268 bool ArgError =
false;
16275 PtrExpr = PtrConv.
get();
16276 TheCall->
setArg(0, PtrExpr);
16283 auto *PtrTy = PtrExpr->
getType()->
getAs<PointerType>();
16284 QualType ElementTy;
16287 << PtrArgIdx + 1 << 0 << 5 << 0
16291 ElementTy = PtrTy->getPointeeType().getUnqualifiedType();
16295 << PtrArgIdx + 1 << 0 << 5
16302 auto ApplyArgumentConversions = [
this](Expr *E) {
16311 ExprResult RowsConv = ApplyArgumentConversions(RowsExpr);
16313 RowsExpr = RowsConv.
get();
16314 TheCall->
setArg(1, RowsExpr);
16316 RowsExpr =
nullptr;
16318 ExprResult ColumnsConv = ApplyArgumentConversions(ColumnsExpr);
16320 ColumnsExpr = ColumnsConv.
get();
16321 TheCall->
setArg(2, ColumnsExpr);
16323 ColumnsExpr =
nullptr;
16334 std::optional<unsigned> MaybeRows;
16338 std::optional<unsigned> MaybeColumns;
16343 ExprResult StrideConv = ApplyArgumentConversions(StrideExpr);
16346 StrideExpr = StrideConv.
get();
16347 TheCall->
setArg(3, StrideExpr);
16350 if (std::optional<llvm::APSInt>
Value =
16353 if (Stride < *MaybeRows) {
16355 diag::err_builtin_matrix_stride_too_small);
16361 if (ArgError || !MaybeRows || !MaybeColumns)
16365 Context.getConstantMatrixType(ElementTy, *MaybeRows, *MaybeColumns));
16374 unsigned PtrArgIdx = 1;
16375 Expr *MatrixExpr = TheCall->
getArg(0);
16376 Expr *PtrExpr = TheCall->
getArg(PtrArgIdx);
16377 Expr *StrideExpr = TheCall->
getArg(2);
16379 bool ArgError =
false;
16385 MatrixExpr = MatrixConv.
get();
16386 TheCall->
setArg(0, MatrixExpr);
16393 auto *MatrixTy = MatrixExpr->
getType()->
getAs<ConstantMatrixType>();
16396 << 1 << 3 << 0 << 0 << MatrixExpr->
getType();
16404 PtrExpr = PtrConv.
get();
16405 TheCall->
setArg(1, PtrExpr);
16413 auto *PtrTy = PtrExpr->
getType()->
getAs<PointerType>();
16416 << PtrArgIdx + 1 << 0 << 5 << 0
16420 QualType ElementTy = PtrTy->getPointeeType();
16422 Diag(PtrExpr->
getBeginLoc(), diag::err_builtin_matrix_store_to_const);
16427 !
Context.hasSameType(ElementTy, MatrixTy->getElementType())) {
16429 diag::err_builtin_matrix_pointer_arg_mismatch)
16430 << ElementTy << MatrixTy->getElementType();
16445 StrideExpr = StrideConv.
get();
16446 TheCall->
setArg(2, StrideExpr);
16451 if (std::optional<llvm::APSInt>
Value =
16454 if (Stride < MatrixTy->getNumRows()) {
16456 diag::err_builtin_matrix_stride_too_small);
16476 if (!Caller || !Caller->
hasAttr<EnforceTCBAttr>())
16481 llvm::StringSet<> CalleeTCBs;
16482 for (
const auto *A : Callee->specific_attrs<EnforceTCBAttr>())
16483 CalleeTCBs.insert(A->getTCBName());
16484 for (
const auto *A : Callee->specific_attrs<EnforceTCBLeafAttr>())
16485 CalleeTCBs.insert(A->getTCBName());
16489 for (
const auto *A : Caller->
specific_attrs<EnforceTCBAttr>()) {
16490 StringRef CallerTCB = A->getTCBName();
16491 if (CalleeTCBs.count(CallerTCB) == 0) {
16492 this->
Diag(CallExprLoc, diag::warn_tcb_enforcement_violation)
16493 << Callee << CallerTCB;
Defines the clang::ASTContext interface.
Provides definitions for the various language-specific address spaces.
Defines the Diagnostic-related interfaces.
static bool getTypeString(SmallStringEnc &Enc, const Decl *D, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
The XCore ABI includes a type information section that communicates symbol type information to the li...
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Target Target
Defines the clang::OpenCLOptions class.
Defines an enumeration for C++ overloaded operators.
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y)
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
This file declares semantic analysis functions specific to AMDGPU.
This file declares semantic analysis functions specific to ARM.
This file declares semantic analysis functions specific to BPF.
static bool isLayoutCompatibleUnion(const ASTContext &C, const RecordDecl *RD1, const RecordDecl *RD2)
Check if two standard-layout unions are layout-compatible.
static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx, const ValueDecl **VD, uint64_t *MagicValue, bool isConstantEvaluated)
Given a type tag expression find the type tag itself.
static void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E, SourceLocation CC, QualType T)
static QualType getSizeOfArgType(const Expr *E)
If E is a sizeof expression, returns its argument type.
static void CheckNonNullArgument(Sema &S, const Expr *ArgExpr, SourceLocation CallSiteLoc)
static bool checkPointerAuthValue(Sema &S, Expr *&Arg, PointerAuthOpKind OpKind, bool RequireConstant=false)
static const CXXRecordDecl * getContainedDynamicClass(QualType T, bool &IsContained)
Determine whether the given type is or contains a dynamic class type (e.g., whether it has a vtable).
static ExprResult PointerAuthSignGenericData(Sema &S, CallExpr *Call)
static void builtinAllocaAddrSpace(Sema &S, CallExpr *TheCall)
static ExprResult PointerAuthStrip(Sema &S, CallExpr *Call)
static bool isInvalidOSLogArgTypeForCodeGen(FormatStringType FSType, QualType T)
static StringLiteralCheckType checkFormatStringExpr(Sema &S, const StringLiteral *ReferenceFormatString, const Expr *E, ArrayRef< const Expr * > Args, Sema::FormatArgumentPassingKind APK, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, VariadicCallType CallType, bool InFunctionCall, llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset, bool IgnoreStringsWithoutSpecifiers=false)
static bool IsSameFloatAfterCast(const llvm::APFloat &value, const llvm::fltSemantics &Src, const llvm::fltSemantics &Tgt)
Checks whether the given value, which currently has the given source semantics, has the same value wh...
static void AnalyzeComparison(Sema &S, BinaryOperator *E)
Implements -Wsign-compare.
static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend, BinaryOperatorKind BinOpKind, bool AddendIsRight)
static std::pair< QualType, StringRef > shouldNotPrintDirectly(const ASTContext &Context, QualType IntendedTy, const Expr *E)
static QualType GetExprType(const Expr *E)
static CFIUncheckedCalleeChange AdjustingCFIUncheckedCallee(QualType From, QualType To)
static std::optional< std::pair< CharUnits, CharUnits > > getBaseAlignmentAndOffsetFromLValue(const Expr *E, ASTContext &Ctx)
This helper function takes an lvalue expression and returns the alignment of a VarDecl and a constant...
static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, Expr *Constant, Expr *Other, const llvm::APSInt &Value, bool RhsConstant)
static bool IsImplicitBoolFloatConversion(Sema &S, const Expr *Ex, bool ToBool)
static AbsoluteValueKind getAbsoluteValueKind(QualType T)
static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E, const IdentifierInfo *FnName, SourceLocation FnLoc, SourceLocation RParenLoc)
Takes the expression passed to the size_t parameter of functions such as memcmp, strncat,...
static ExprResult BuiltinDumpStruct(Sema &S, CallExpr *TheCall)
static bool CompareFormatSpecifiers(Sema &S, const StringLiteral *Ref, ArrayRef< EquatableFormatArgument > RefArgs, const StringLiteral *Fmt, ArrayRef< EquatableFormatArgument > FmtArgs, const Expr *FmtExpr, bool InFunctionCall)
static ExprResult BuiltinTriviallyRelocate(Sema &S, CallExpr *TheCall)
static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op)
static bool BuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall, Scope::ScopeFlags NeededScopeFlags, unsigned DiagID)
static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E)
Analyze the given compound assignment for the possible losing of floating-point precision.
static bool doesExprLikelyComputeSize(const Expr *SizeofExpr)
Detect if SizeofExpr is likely to calculate the sizeof an object.
static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr, const StringLiteral *ReferenceFormatString, const Expr *OrigFormatExpr, ArrayRef< const Expr * > Args, Sema::FormatArgumentPassingKind APK, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, bool inFunctionCall, VariadicCallType CallType, llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg, bool IgnoreStringsWithoutSpecifiers)
static bool BuiltinPreserveAI(Sema &S, CallExpr *TheCall)
Check the number of arguments and set the result type to the argument type.
static bool CheckForReference(Sema &SemaRef, const Expr *E, const PartialDiagnostic &PD)
static const UnaryExprOrTypeTraitExpr * getAsSizeOfExpr(const Expr *E)
static bool BuiltinAlignment(Sema &S, CallExpr *TheCall, unsigned ID)
Check that the value argument for __builtin_is_aligned(value, alignment) and __builtin_aligned_{up,...
static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC)
Check conversion of given expression to boolean.
static bool isKnownToHaveUnsignedValue(const Expr *E)
static bool checkBuiltinVectorMathArgTypes(Sema &SemaRef, ArrayRef< Expr * > Args)
Check if all arguments have the same type.
static void CheckMemaccessSize(Sema &S, unsigned BId, const CallExpr *Call)
Diagnose cases like 'memset(buf, sizeof(buf), 0)', which should have the last two arguments transpose...
static bool checkPointerAuthEnabled(Sema &S, Expr *E)
static std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range)
static ExprResult BuiltinMaskedStore(Sema &S, CallExpr *TheCall)
static const Expr * getStrlenExprArg(const Expr *E)
static bool isConstantSizeArrayWithMoreThanOneElement(QualType Ty, ASTContext &Context)
static bool IsInfOrNanFunction(StringRef calleeName, MathCheck Check)
static bool BuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall, const TargetInfo *AuxTI, unsigned BuiltinID)
BuiltinCpu{Supports|Is} - Handle __builtin_cpu_{supports|is}(char *).
static bool IsSameCharType(QualType T1, QualType T2)
static ExprResult BuiltinVectorMathConversions(Sema &S, Expr *E)
static bool CheckNonNullExpr(Sema &S, const Expr *Expr)
Checks if a the given expression evaluates to null.
static ExprResult BuiltinIsWithinLifetime(Sema &S, CallExpr *TheCall)
static bool isArgumentExpandedFromMacro(SourceManager &SM, SourceLocation CallLoc, SourceLocation ArgLoc)
Check if the ArgLoc originated from a macro passed to the call at CallLoc.
static IntRange GetValueRange(llvm::APSInt &value, unsigned MaxWidth)
static const IntegerLiteral * getIntegerLiteral(Expr *E)
static bool CheckBuiltinTargetInSupported(Sema &S, CallExpr *TheCall, ArrayRef< llvm::Triple::ArchType > SupportedArchs)
static const Expr * maybeConstEvalStringLiteral(ASTContext &Context, const Expr *E)
static bool IsStdFunction(const FunctionDecl *FDecl, const char(&Str)[StrLen])
static void AnalyzeAssignment(Sema &S, BinaryOperator *E)
Analyze the given simple or compound assignment for warning-worthy operations.
static bool BuiltinFunctionStart(Sema &S, CallExpr *TheCall)
Check that the argument to __builtin_function_start is a function.
static bool BuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall)
static bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr, SourceLocation StmtLoc, const NullStmt *Body)
static std::pair< CharUnits, CharUnits > getDerivedToBaseAlignmentAndOffset(const CastExpr *CE, QualType DerivedType, CharUnits BaseAlignment, CharUnits Offset, ASTContext &Ctx)
Compute the alignment and offset of the base class object given the derived-to-base cast expression a...
static std::pair< const ValueDecl *, CharUnits > findConstantBaseAndOffset(Sema &S, Expr *E)
static bool IsEnumConstOrFromMacro(Sema &S, const Expr *E)
static void diagnoseArrayStarInParamType(Sema &S, QualType PType, SourceLocation Loc)
static std::optional< IntRange > TryGetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, bool InConstantContext, bool Approximate)
Attempts to estimate an approximate range for the given integer expression.
static unsigned changeAbsFunction(unsigned AbsKind, AbsoluteValueKind ValueKind)
static ExprResult BuiltinMaskedLoad(Sema &S, CallExpr *TheCall)
static void CheckImplicitArgumentConversions(Sema &S, const CallExpr *TheCall, SourceLocation CC)
static void CheckConditionalOperand(Sema &S, Expr *E, QualType T, SourceLocation CC, bool &ICContext)
static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, SourceLocation CC)
static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc, Expr *RHS, bool isProperty)
static ExprResult BuiltinLaunder(Sema &S, CallExpr *TheCall)
static ExprResult PointerAuthBlendDiscriminator(Sema &S, CallExpr *Call)
static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, SourceLocation InitLoc)
Analyzes an attempt to assign the given value to a bitfield.
static void CheckCommaOperand(Sema &S, Expr *E, QualType T, SourceLocation CC, bool ExtraCheckForImplicitConversion, llvm::SmallVectorImpl< AnalyzeImplicitConversionsWorkItem > &WorkList)
static void DiagnoseFloatingImpCast(Sema &S, const Expr *E, QualType T, SourceLocation CContext)
Diagnose an implicit cast from a floating point value to an integer value.
static int classifyConstantValue(Expr *Constant)
static bool IsInAnyMacroBody(const SourceManager &SM, SourceLocation Loc)
static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range, unsigned AbsKind, QualType ArgType)
static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2)
Check if two types are layout-compatible in C++11 sense.
static bool checkPointerAuthKey(Sema &S, Expr *&Arg)
static bool checkUnsafeAssignObject(Sema &S, SourceLocation Loc, Qualifiers::ObjCLifetime LT, Expr *RHS, bool isProperty)
static bool BuiltinOverflow(Sema &S, CallExpr *TheCall, unsigned BuiltinID)
static unsigned getAbsoluteValueFunctionKind(const FunctionDecl *FDecl)
static llvm::SmallPtrSet< MemberKind *, 1 > CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty)
static bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T, SourceLocation CC)
static bool IsInfinityFunction(const FunctionDecl *FDecl)
static void DiagnoseImpCast(Sema &S, const Expr *E, QualType SourceType, QualType T, SourceLocation CContext, unsigned diag, bool PruneControlFlow=false)
Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
static void CheckNonNullArguments(Sema &S, const NamedDecl *FDecl, const FunctionProtoType *Proto, ArrayRef< const Expr * > Args, SourceLocation CallSiteLoc)
static unsigned getLargerAbsoluteValueFunction(unsigned AbsFunction)
static analyze_format_string::ArgType::MatchKind handleFormatSignedness(analyze_format_string::ArgType::MatchKind Match, DiagnosticsEngine &Diags, SourceLocation Loc)
static bool referToTheSameDecl(const Expr *E1, const Expr *E2)
Check if two expressions refer to the same declaration.
static ExprResult BuiltinMaskedScatter(Sema &S, CallExpr *TheCall)
static bool BuiltinCountZeroBitsGeneric(Sema &S, CallExpr *TheCall)
Checks that __builtin_{clzg,ctzg} was called with a first argument, which is an unsigned integer,...
static ExprResult GetVTablePointer(Sema &S, CallExpr *Call)
static bool requiresParensToAddCast(const Expr *E)
static bool HasEnumType(const Expr *E)
static ExprResult PointerAuthAuthAndResign(Sema &S, CallExpr *Call)
static ExprResult BuiltinInvoke(Sema &S, CallExpr *TheCall)
static const Expr * ignoreLiteralAdditions(const Expr *Ex, ASTContext &Ctx)
static std::optional< unsigned > getAndVerifyMatrixDimension(Expr *Expr, StringRef Name, Sema &S)
static bool convertArgumentToType(Sema &S, Expr *&Value, QualType Ty)
static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *Call)
static bool ProcessFormatStringLiteral(const Expr *FormatExpr, StringRef &FormatStrRef, size_t &StrLen, ASTContext &Context)
static bool isLayoutCompatibleStruct(const ASTContext &C, const RecordDecl *RD1, const RecordDecl *RD2)
Check if two standard-layout structs are layout-compatible.
static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall)
Checks that __builtin_popcountg was called with a single argument, which is an unsigned integer.
static const Expr * getSizeOfExprArg(const Expr *E)
If E is a sizeof expression, returns its argument expression, otherwise returns NULL.
static void DiagnoseIntInBoolContext(Sema &S, Expr *E)
static bool CheckBuiltinTargetNotInUnsupported(Sema &S, unsigned BuiltinID, CallExpr *TheCall, ArrayRef< llvm::Triple::ObjectFormatType > UnsupportedObjectFormatTypes)
static void DiagnoseMixedUnicodeImplicitConversion(Sema &S, const Type *Source, const Type *Target, Expr *E, QualType T, SourceLocation CC)
static bool BuiltinAddressof(Sema &S, CallExpr *TheCall)
Check that the argument to __builtin_addressof is a glvalue, and set the result type to the correspon...
static CharUnits getPresumedAlignmentOfPointer(const Expr *E, Sema &S)
static bool CheckMaskedBuiltinArgs(Sema &S, Expr *MaskArg, Expr *PtrArg, unsigned Pos, bool AllowConst, bool AllowAS)
static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn)
Check that the user is calling the appropriate va_start builtin for the target and calling convention...
static ExprResult PointerAuthSignOrAuth(Sema &S, CallExpr *Call, PointerAuthOpKind OpKind, bool RequireConstant)
static bool checkBuiltinVerboseTrap(CallExpr *Call, Sema &S)
static bool checkMathBuiltinElementType(Sema &S, SourceLocation Loc, QualType ArgTy, Sema::EltwiseBuiltinArgTyRestriction ArgTyRestr, int ArgOrdinal)
static bool GetMatchingCType(const IdentifierInfo *ArgumentKind, const Expr *TypeExpr, const ASTContext &Ctx, const llvm::DenseMap< Sema::TypeTagMagicValue, Sema::TypeTagData > *MagicValues, bool &FoundWrongKind, Sema::TypeTagData &TypeInfo, bool isConstantEvaluated)
Retrieve the C type corresponding to type tag TypeExpr.
static QualType getAbsoluteValueArgumentType(ASTContext &Context, unsigned AbsType)
static ExprResult BuiltinMaskedGather(Sema &S, CallExpr *TheCall)
static bool ConvertMaskedBuiltinArgs(Sema &S, CallExpr *TheCall)
static bool isNonNullType(QualType type)
Determine whether the given type has a non-null nullability annotation.
static constexpr unsigned short combineFAPK(Sema::FormatArgumentPassingKind A, Sema::FormatArgumentPassingKind B)
static bool BuiltinAnnotation(Sema &S, CallExpr *TheCall)
Check that the first argument to __builtin_annotation is an integer and the second argument is a non-...
static std::optional< std::pair< CharUnits, CharUnits > > getBaseAlignmentAndOffsetFromPtr(const Expr *E, ASTContext &Ctx)
This helper function takes a pointer expression and returns the alignment of a VarDecl and a constant...
static bool IsShiftedByte(llvm::APSInt Value)
static unsigned getBestAbsFunction(ASTContext &Context, QualType ArgType, unsigned AbsFunctionKind)
static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex)
checkBuiltinArgument - Given a call to a builtin function, perform normal type-checking on the given ...
static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E)
Analyze the operands of the given comparison.
static bool checkBuiltinVectorMathMixedEnums(Sema &S, Expr *LHS, Expr *RHS, SourceLocation Loc)
static bool isArithmeticArgumentPromotion(Sema &S, const ImplicitCastExpr *ICE)
Return true if ICE is an implicit argument promotion of an arithmetic type.
static void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC, bool IsListInit=false)
AnalyzeImplicitConversions - Find and report any interesting implicit conversions in the given expres...
static std::optional< std::pair< CharUnits, CharUnits > > getAlignmentAndOffsetFromBinAddOrSub(const Expr *PtrE, const Expr *IntE, bool IsSub, ASTContext &Ctx)
Compute the alignment and offset of a binary additive operator.
static bool BuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall)
static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn, ParmVarDecl **LastParam=nullptr)
This file declares semantic analysis for DirectX constructs.
This file declares semantic analysis for HLSL constructs.
This file declares semantic analysis functions specific to Hexagon.
This file declares semantic analysis functions specific to LoongArch.
This file declares semantic analysis functions specific to MIPS.
This file declares semantic analysis functions specific to NVPTX.
This file declares semantic analysis for Objective-C.
This file declares semantic analysis routines for OpenCL.
This file declares semantic analysis functions specific to PowerPC.
This file declares semantic analysis functions specific to RISC-V.
This file declares semantic analysis for SPIRV constructs.
This file declares semantic analysis functions specific to SystemZ.
This file declares semantic analysis functions specific to Wasm.
This file declares semantic analysis functions specific to X86.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines various enumerations that describe declaration and type specifiers.
Provides definitions for the atomic synchronization scopes.
Defines the clang::TypeLoc interface and its subclasses.
Defines enumerations for the type traits support.
C Language Family Type Representation.
__DEVICE__ int min(int __a, int __b)
__device__ __2f16 float __ockl_bool s
MatchKind
How well a given conversion specifier matches its argument.
@ NoMatch
The conversion specifier and the argument types are incompatible.
@ NoMatchPedantic
The conversion specifier and the argument type are disallowed by the C standard, but are in practice ...
@ Match
The conversion specifier and the argument type are compatible.
@ MatchPromotion
The conversion specifier and the argument type are compatible because of default argument promotions.
@ NoMatchSignedness
The conversion specifier and the argument type have different sign.
@ NoMatchTypeConfusion
The conversion specifier and the argument type are compatible, but still seems likely to be an error.
@ NoMatchPromotionTypeConfusion
The conversion specifier and the argument type are compatible but still seems likely to be an error.
unsigned getLength() const
const char * toString() const
const char * getStart() const
const char * getStart() const
HowSpecified getHowSpecified() const
unsigned getConstantAmount() const
unsigned getConstantLength() const
bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx, bool IsObjCLiteral)
Changes the specifier and length according to a QualType, retaining any flags or options.
void toString(raw_ostream &os) const
bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt, ASTContext &Ctx)
void toString(raw_ostream &os) const
llvm::APInt getValue() const
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
const LValueBase getLValueBase() const
APSInt & getComplexIntImag()
bool isComplexInt() const
bool isComplexFloat() const
APValue & getVectorElt(unsigned I)
unsigned getVectorLength() const
APSInt & getComplexIntReal()
APFloat & getComplexFloatImag()
APFloat & getComplexFloatReal()
bool isAddrLabelDiff() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
Builtin::Context & BuiltinInfo
QualType getDecayedType(QualType T) const
Return the uniqued reference to the decayed version of the given type.
int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const
Compare the rank of two floating point types as above, but compare equal if both types have the same ...
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType removeAddrSpaceQualType(QualType T) const
Remove any existing address space on the type and returns the type with qualifiers intact (or that's ...
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const clang::PrintingPolicy & getPrintingPolicy() const
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getTypedefType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypedefNameDecl *Decl, QualType UnderlyingType=QualType(), std::optional< bool > TypeMatchesDeclOrNone=std::nullopt) const
Return the unique reference to the type for the specified typedef-name decl.
CanQualType UnsignedShortTy
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
QualType getPromotedIntegerType(QualType PromotableType) const
Return the type that PromotableType will promote to: C99 6.3.1.1p2, assuming that PromotableType is a...
StringLiteral * getPredefinedStringLiteralFromCache(StringRef Key) const
Return a string representing the human readable name for the specified function declaration or file n...
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
bool isPromotableIntegerType(QualType T) const
More type predicates useful for type checking/promotion.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualAlignment() const
getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
SourceLocation getQuestionLoc() const
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Expr * getBase()
Get base of the array section.
Expr * getLowerBound()
Get lower bound of array section.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
SourceLocation getRBracketLoc() const
Expr * getLHS()
An array access can be written A[4] or 4[A] (both are equivalent).
Represents an array type, per C99 6.7.5.2 - Array Declarators.
ArraySizeModifier getSizeModifier() const
QualType getElementType() const
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
static std::unique_ptr< AtomicScopeModel > getScopeModel(AtomicOp Op)
Get atomic scope model for the atomic op code.
SourceLocation getBeginLoc() const LLVM_READONLY
Attr - This represents one attribute.
const char * getSpelling() const
Type source information for an attributed type.
TypeLoc getModifiedLoc() const
The modified type, which is generally canonically different from the attribute type.
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isLogicalOp(Opcode Opc)
SourceLocation getOperatorLoc() const
SourceLocation getExprLoc() const
static StringRef getOpcodeStr(Opcode Op)
getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to,...
static bool isAdditiveOp(Opcode Opc)
static bool isEqualityOp(Opcode Opc)
BinaryOperatorKind Opcode
This class is used for builtin types like 'int'.
bool isFloatingPoint() const
bool isSignedInteger() const
bool isUnsignedInteger() const
std::string getQuotedName(unsigned ID) const
Return the identifier name for the specified builtin inside single quotes for a diagnostic,...
const char * getHeaderName(unsigned ID) const
If this is a library function that comes from a specific header, retrieve that header name.
std::string getName(unsigned ID) const
Return the identifier name for the specified builtin, e.g.
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr....
Represents a base class of a C++ class.
Represents a call to a C++ constructor.
bool isListInitialization() const
Whether this constructor call was written as list-initialization.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
A call to an overloaded operator written using operator syntax.
SourceLocation getExprLoc() const LLVM_READONLY
OverloadedOperatorKind getOperator() const
Returns the kind of overloaded operator that this expression refers to.
Represents a list-initialization with parenthesis.
MutableArrayRef< Expr * > getInitExprs()
Represents a C++ struct/union/class.
bool isStandardLayout() const
Determine whether this class is standard-layout per C++ [class]p7.
CXXRecordDecl * getDefinition() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
bool isDynamicClass() const
Represents a C++ nested-name-specifier or a global scope specifier.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
void setArg(unsigned Arg, Expr *ArgExpr)
setArg - Set the specified argument.
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
bool isCallToStdMove() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
Expr ** getArgs()
Retrieve the call arguments.
SourceLocation getEndLoc() const
SourceLocation getRParenLoc() const
bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const
Returns true if this is a call to a builtin which does not evaluate side-effects within its arguments...
void shrinkNumArgs(unsigned NewNumArgs)
Reduce the number of arguments in this call expression.
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
path_iterator path_begin()
CastKind getCastKind() const
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
static CharSourceRange getTokenRange(SourceRange R)
SourceLocation getBegin() const
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
bool isOne() const
isOne - Test whether the quantity equals one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
ConditionalOperator - The ?
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
Represents the canonical version of C arrays with a specified constant size.
llvm::APInt getSize() const
Return the constant array size as an APInt.
static ConstantExpr * Create(const ASTContext &Context, Expr *E, const APValue &Result)
static constexpr unsigned getMaxElementsPerDimension()
Returns the maximum number of elements per dimension.
static constexpr bool isDimensionValid(size_t NumElements)
Returns true if NumElements is a valid matrix dimension.
static ConvertVectorExpr * Create(const ASTContext &C, Expr *SrcExpr, TypeSourceInfo *TI, QualType DstType, ExprValueKind VK, ExprObjectKind OK, SourceLocation BuiltinLoc, SourceLocation RParenLoc, FPOptionsOverride FPFeatures)
Expr * getOperand() const
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isStdNamespace() const
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
bool isFunctionOrMethod() const
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
SourceLocation getBeginLoc() const
SourceLocation getLocation() const
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl,...
const FunctionType * getFunctionType(bool BlocksToo=true) const
Looks through the Decl's underlying type to extract a FunctionType when possible.
bool isInvalidDecl() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
The name of a declaration.
std::string getAsString() const
Retrieve the human-readable string for this name.
SourceLocation getTypeSpecStartLoc() const
TypeSourceInfo * getTypeSourceInfo() const
bool hasErrorOccurred() const
Determine whether any errors have occurred since this object instance was created.
Concrete class used by the front-end to report problems and issues.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
An instance of this object exists for each enum constant that is defined.
bool isComplete() const
Returns true if this can be considered a complete type.
QualType getIntegerType() const
Return the integer type this enum decl corresponds to.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_NoSideEffects
Strictly evaluate the expression.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
bool isValueDependent() const
Determines whether the value of this expression depends on.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const
If the current Expr is a pointer, this will try to statically determine the strlen of the string poin...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
bool EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsFloat - Return true if this is a constant which we can fold and convert to a floating point...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isFlexibleArrayMemberLike(const ASTContext &Context, LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, bool IgnoreTemplateOrMacroSubstitution=false) const
Check whether this array fits the idiom of a flexible array member, depending on the value of -fstric...
bool EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsFixedPoint - Return true if this is a constant which we can fold and convert to a fixed poi...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
FieldDecl * getSourceBitField()
If this expression refers to a bit-field, retrieve the declaration of that bit-field.
@ NPC_ValueDependentIsNull
Specifies that a value-dependent expression of integral or dependent type should be considered a null...
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, ConstantExprKind Kind=ConstantExprKind::Normal) const
Evaluate an expression that is required to be a constant expression.
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
NullPointerConstantKind
Enumeration used to describe the kind of Null pointer constant returned from isNullPointerConstant().
@ NPCK_ZeroExpression
Expression is a Null pointer constant built from a zero integer expression that is not a simple,...
@ NPCK_ZeroLiteral
Expression is a Null pointer constant built from a literal zero.
@ NPCK_NotNull
Expression is not a Null pointer constant.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
NullPointerConstantKind isNullPointerConstant(ASTContext &Ctx, NullPointerConstantValueDependence NPC) const
isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to a Null pointer constant.
QualType getEnumCoercedType(const ASTContext &Ctx) const
If this expression is an enumeration constant, return the enumeration type under which said constant ...
void setValueKind(ExprValueKind Cat)
setValueKind - Set the value kind produced by this expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
void setObjectKind(ExprObjectKind Cat)
setObjectKind - Set the object kind produced by this expression.
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, unsigned Type) const
If the current Expr is a pointer, this will try to statically determine the number of bytes available...
const ValueDecl * getAsBuiltinConstantDeclRef(const ASTContext &Context) const
If this expression is an unambiguous reference to a single declaration, in the style of __builtin_fun...
bool isKnownToHaveBooleanValue(bool Semantic=true) const
isKnownToHaveBooleanValue - Return true if this is an integer expression that is known to return 0 or...
void EvaluateForOverflow(const ASTContext &Ctx) const
ExtVectorType - Extended vector type.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Expr * getBitWidth() const
Returns the expression that represents the bit width, if this field is a bit field.
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
llvm::APFloat getValue() const
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Represents a function declaration or definition.
unsigned getMemoryFunctionKind() const
Identify a memory copying or setting function.
const ParmVarDecl * getParamDecl(unsigned i) const
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
param_iterator param_end()
bool hasCXXExplicitFunctionObjectParameter() const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
param_iterator param_begin()
bool isVariadic() const
Whether this function is variadic.
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Represents a prototype with parameter type info, e.g.
unsigned getNumParams() const
QualType getParamType(unsigned i) const
bool isVariadic() const
Whether this function prototype is variadic.
ExtProtoInfo getExtProtoInfo() const
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
ArrayRef< QualType > getParamTypes() const
FunctionType - C99 6.7.5.3 - Function Declarators.
@ SME_PStateSMEnabledMask
@ SME_PStateSMCompatibleMask
static ArmStateValue getArmZT0State(unsigned AttrBits)
static ArmStateValue getArmZAState(unsigned AttrBits)
QualType getReturnType() const
One of these records is kept for each identifier that is lexed.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Describes an C or C++ initializer list.
ArrayRef< Expr * > inits()
Describes an entity that is being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
StrictFlexArraysLevelKind
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
static StringRef getImmediateMacroNameForDiagnostics(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
Represents the results of name lookup.
bool empty() const
Return true if no decls were found.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
UnresolvedSetImpl::iterator iterator
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
static bool isValidElementType(QualType T)
Valid elements types are the following:
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
A pointer to member type per C++ 8.3.3 - Pointers to members.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Linkage getFormalLinkage() const
Get the linkage from a semantic point of view.
bool hasLinkage() const
Determine whether this declaration has linkage.
Represent a C++ namespace.
NullStmt - This is the null statement ";": C99 6.8.3p3.
bool hasLeadingEmptyMacro() const
SourceLocation getSemiLoc() const
Represents an ObjC class declaration.
Represents one property declaration in an Objective-C interface.
ObjCPropertyAttribute::Kind getPropertyAttributesAsWritten() const
ObjCPropertyAttribute::Kind getPropertyAttributes() const
ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC property.
ObjCPropertyDecl * getExplicitProperty() const
bool isImplicitProperty() const
ObjCStringLiteral, used for Objective-C string literals i.e.
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
ParenExpr - This represents a parenthesized expression, e.g.
Represents a parameter to a function.
Pointer-authentication qualifiers.
@ MaxDiscriminator
The maximum supported pointer-authentication discriminator.
bool isAddressDiscriminated() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
PointerAuthQualifier getPointerAuth() const
PrimitiveDefaultInitializeKind
QualType withoutLocalFastQualifiers() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
void removeLocalVolatile()
QualType withCVRQualifiers(unsigned CVR) const
bool isConstQualified() const
Determine whether this type is const-qualified.
bool hasAddressSpace() const
Check if this type has any address space qualifier.
QualType getAtomicUnqualifiedType() const
Remove all qualifiers including _Atomic.
unsigned getCVRQualifiers() const
Retrieve the set of CVR (const-volatile-restrict) qualifiers applied to this type.
bool hasNonTrivialObjCLifetime() const
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
bool hasUnaligned() const
Represents a struct/union/class.
bool isNonTrivialToPrimitiveCopy() const
field_range fields() const
bool isNonTrivialToPrimitiveDefaultInitialize() const
Functions to query basic properties of non-trivial C structs.
Scope - A scope is a transient data structure that is used while parsing the program.
bool isSEHExceptScope() const
Determine whether this scope is a SEH '__except' block.
unsigned getFlags() const
getFlags - Return the flags for this scope.
const Scope * getParent() const
getParent - Return the scope that this is nested in.
ScopeFlags
ScopeFlags - These are bitfields that are or'd together when creating a scope, which defines the sort...
@ SEHFilterScope
We are currently in the filter expression of an SEH except block.
@ SEHExceptScope
This scope corresponds to an SEH except.
bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
@ ArmStreaming
Intrinsic is only available in normal mode.
@ ArmStreamingCompatible
Intrinsic is only available in Streaming-SVE mode.
bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
A generic diagnostic builder for errors which may or may not be deferred.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
bool CheckDirectXBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool CheckMipsBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
void checkArrayLiteral(QualType TargetType, ObjCArrayLiteral *ArrayLiteral)
Check an Objective-C array literal being converted to the given target type.
ObjCLiteralKind CheckLiteralKind(Expr *FromE)
void adornBoolConversionDiagWithTernaryFixit(const Expr *SourceExpr, const Sema::SemaDiagnosticBuilder &Builder)
bool isSignedCharBool(QualType Ty)
void DiagnoseCStringFormatDirectiveInCFAPI(const NamedDecl *FDecl, Expr **Args, unsigned NumArgs)
Diagnose use of s directive in an NSString which is being passed as formatting string to formatting m...
void checkDictionaryLiteral(QualType TargetType, ObjCDictionaryLiteral *DictionaryLiteral)
Check an Objective-C dictionary literal being converted to the given target type.
std::unique_ptr< NSAPI > NSAPIObj
Caches identifiers/selectors for NSFoundation APIs.
bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg)
bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc)
bool CheckBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool CheckBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
const FieldDecl * getSelfAssignmentClassMemberCandidate(const ValueDecl *SelfAssigned)
Returns a field in a CXXRecordDecl that has the same name as the decl SelfAssigned when inside a CXXM...
bool DiscardingCFIUncheckedCallee(QualType From, QualType To) const
Returns true if From is a function or pointer to a function with the cfi_unchecked_callee attribute b...
bool BuiltinConstantArgShiftedByte(CallExpr *TheCall, unsigned ArgNum, unsigned ArgBits)
BuiltinConstantArgShiftedByte - Check if argument ArgNum of TheCall is a constant expression represen...
bool IsPointerInterconvertibleBaseOf(const TypeSourceInfo *Base, const TypeSourceInfo *Derived)
bool diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function, const Expr *ThisArg, ArrayRef< const Expr * > Args, SourceLocation Loc)
Emit diagnostics for the diagnose_if attributes on Function, ignoring any non-ArgDependent DiagnoseIf...
bool BuiltinConstantArgMultiple(CallExpr *TheCall, unsigned ArgNum, unsigned Multiple)
BuiltinConstantArgMultiple - Handle a check if argument ArgNum of CallExpr TheCall is a constant expr...
LocalInstantiationScope * CurrentInstantiationScope
The current instantiation scope used to store local variables.
Scope * getCurScope() const
Retrieve the parser's current scope.
std::optional< QualType > BuiltinVectorMath(CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr=EltwiseBuiltinArgTyRestriction::None)
ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input, bool IsAfterAmp=false)
Unary Operators. 'Tok' is the token for the operator.
bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, UnresolvedSetImpl &NonTemplateOverloads)
Figure out if an expression could be turned into a call.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
@ LookupAnyName
Look up any declaration with any name.
bool checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount)
Checks that a call expression's argument count is at most the desired number.
bool checkPointerAuthDiscriminatorArg(Expr *Arg, PointerAuthDiscArgKind Kind, unsigned &IntVal)
bool ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum)
Returns true if the argument consists of one contiguous run of 1s with any number of 0s on either sid...
void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind, uint64_t MagicValue, QualType Type, bool LayoutCompatible, bool MustBeNull)
Register a magic integral constant to be used as a type tag.
bool isValidPointerAttrType(QualType T, bool RefOkay=false)
Determine if type T is a valid subject for a nonnull and similar attributes.
void DiagnoseAlwaysNonNullPointer(Expr *E, Expr::NullPointerConstantKind NullType, bool IsEqual, SourceRange Range)
Diagnose pointers that are always non-null.
VariadicCallType getVariadicCallType(FunctionDecl *FDecl, const FunctionProtoType *Proto, Expr *Fn)
bool FormatStringHasSArg(const StringLiteral *FExpr)
QualType UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, ArithConvKind ACK)
UsualArithmeticConversions - Performs various conversions that are common to binary operators (C99 6....
void CheckFloatComparison(SourceLocation Loc, const Expr *LHS, const Expr *RHS, BinaryOperatorKind Opcode)
Check for comparisons of floating-point values using == and !=.
void RefersToMemberWithReducedAlignment(Expr *E, llvm::function_ref< void(Expr *, RecordDecl *, FieldDecl *, CharUnits)> Action)
This function calls Action when it determines that E designates a misaligned member due to the packed...
const ExpressionEvaluationContextRecord & currentEvaluationContext() const
bool CheckFormatStringsCompatible(FormatStringType FST, const StringLiteral *AuthoritativeFormatString, const StringLiteral *TestedFormatString, const Expr *FunctionCallArg=nullptr)
Verify that two format strings (as understood by attribute(format) and attribute(format_matches) are ...
bool IsCXXTriviallyRelocatableType(QualType T)
Determines if a type is trivially relocatable according to the C++26 rules.
FPOptionsOverride CurFPFeatureOverrides()
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ExprResult UsualUnaryConversions(Expr *E)
UsualUnaryConversions - Performs various conversions that are common to most operators (C99 6....
bool checkPointerAuthEnabled(SourceLocation Loc, SourceRange Range)
bool BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT, QualType RhsT)
ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, FunctionDecl *FDecl)
ExprResult tryConvertExprToType(Expr *E, QualType Ty)
Try to convert an expression E to type Ty.
QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc)
CheckAddressOfOperand - The operand of & must be either a function designator or an lvalue designatin...
DiagnosticsEngine & getDiagnostics() const
bool checkAddressOfFunctionIsAvailable(const FunctionDecl *Function, bool Complain=false, SourceLocation Loc=SourceLocation())
Returns whether the given function's address can be taken or not, optionally emitting a diagnostic if...
void CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC, bool *ICContext=nullptr, bool IsListInit=false)
std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
ASTContext & getASTContext() const
CXXDestructorDecl * LookupDestructor(CXXRecordDecl *Class)
Look for the destructor of the given class.
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
bool isConstantEvaluatedOverride
Used to change context to isConstantEvaluated without pushing a heavy ExpressionEvaluationContextReco...
bool BuiltinVectorToScalarMath(CallExpr *TheCall)
bool BuiltinConstantArg(CallExpr *TheCall, unsigned ArgNum, llvm::APSInt &Result)
BuiltinConstantArg - Handle a check if argument ArgNum of CallExpr TheCall is a constant expression.
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
bool pushCodeSynthesisContext(CodeSynthesisContext Ctx)
bool AddingCFIUncheckedCallee(QualType From, QualType To) const
Returns true if From is a function or pointer to a function without the cfi_unchecked_callee attribut...
void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation OpLoc)
DiagnoseSelfMove - Emits a warning if a value is moved to itself.
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
bool BuiltinConstantArgRange(CallExpr *TheCall, unsigned ArgNum, int Low, int High, bool RangeIsError=true)
BuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr TheCall is a constant express...
bool IsLayoutCompatible(QualType T1, QualType T2) const
const LangOptions & getLangOpts() const
bool RequireCompleteExprType(Expr *E, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type of the given expression is complete.
void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange)
CheckCastAlign - Implements -Wcast-align, which warns when a pointer cast increases the alignment req...
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
bool RequireNonAbstractType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser)
bool hasCStrMethod(const Expr *E)
Check to see if a given expression could have '.c_str()' called on it.
const LangOptions & LangOpts
static const uint64_t MaximumAlignment
VarArgKind isValidVarArgType(const QualType &Ty)
Determine the degree of POD-ness for an expression.
ExprResult ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, SourceLocation BuiltinLoc, SourceLocation RParenLoc)
ConvertVectorExpr - Handle __builtin_convertvector.
static StringRef GetFormatStringTypeName(FormatStringType FST)
bool checkConstantPointerAuthKey(Expr *keyExpr, unsigned &key)
bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS)
checkUnsafeAssigns - Check whether +1 expr is being assigned to weak/__unsafe_unretained type.
EltwiseBuiltinArgTyRestriction
CleanupInfo Cleanup
Used to control the generation of ExprWithCleanups.
NamedDecl * getCurFunctionOrMethodDecl() const
getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method or C function we're in,...
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void popCodeSynthesisContext()
void DiagnoseMisalignedMembers()
Diagnoses the current set of gathered accesses.
sema::FunctionScopeInfo * getCurFunction() const
void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS)
checkUnsafeExprAssigns - Check whether +1 expr is being assigned to weak/__unsafe_unretained expressi...
std::pair< const IdentifierInfo *, uint64_t > TypeTagMagicValue
A pair of ArgumentKind identifier and magic value.
QualType BuiltinRemoveCVRef(QualType BaseType, SourceLocation Loc)
bool findMacroSpelling(SourceLocation &loc, StringRef name)
Looks through the macro-expansion chain for the given location, looking for a macro expansion with th...
ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Member, Decl *ObjCImpDecl)
The main callback when the parser finds something like expression .
void DiagnoseEmptyStmtBody(SourceLocation StmtLoc, const Stmt *Body, unsigned DiagID)
Emit DiagID if statement located on StmtLoc has a suspicious null statement as a Body,...
void DiagnoseEmptyLoopBody(const Stmt *S, const Stmt *PossibleBody)
Warn if a for/while loop statement S, which is followed by PossibleBody, has a suspicious null statem...
ExprResult DefaultLvalueConversion(Expr *E)
SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL, unsigned ByteNo) const
void CheckTCBEnforcement(const SourceLocation CallExprLoc, const NamedDecl *Callee)
Enforce the bounds of a TCB CheckTCBEnforcement - Enforces that every function in a named TCB only di...
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
bool checkArgCountAtLeast(CallExpr *Call, unsigned MinArgCount)
Checks that a call expression's argument count is at least the desired number.
FormatArgumentPassingKind
bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, CXXRecordDecl *Base, CXXBasePaths &Paths)
Determine whether the type Derived is a C++ class that is derived from the type Base.
bool isUnevaluatedContext() const
Determines whether we are currently in a context that is not evaluated as per C++ [expr] p5.
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
SourceManager & getSourceManager() const
static FormatStringType GetFormatStringType(StringRef FormatFlavor)
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount)
Checks that a call expression's argument count is in the desired range.
bool ValidateFormatString(FormatStringType FST, const StringLiteral *Str)
Verify that one format string (as understood by attribute(format)) is self-consistent; for instance,...
void DiscardMisalignedMemberAddress(const Type *T, Expr *E)
This function checks if the expression is in the sef of potentially misaligned members and it is conv...
bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr=EltwiseBuiltinArgTyRestriction::None)
bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement, const PartialDiagnostic &PD)
Conditionally issue a diagnostic based on the current evaluation context.
ExprResult BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, SourceLocation nameLoc, IndirectFieldDecl *indirectField, DeclAccessPair FoundDecl=DeclAccessPair::make(nullptr, AS_none), Expr *baseObjectExpr=nullptr, SourceLocation opLoc=SourceLocation())
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType ...
bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef< SourceLocation > Locs, const ObjCInterfaceDecl *UnknownObjCClass=nullptr, bool ObjCPropertyAccess=false, bool AvoidPartialAvailabilityChecks=false, ObjCInterfaceDecl *ClassReciever=nullptr, bool SkipTrailingRequiresClause=false)
Determine whether the use of this declaration is valid, and emit any corresponding diagnostics.
bool CheckParmsForFunctionDef(ArrayRef< ParmVarDecl * > Parameters, bool CheckParameterNames)
CheckParmsForFunctionDef - Check that the parameters of the given function are appropriate for the de...
ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr)
Binary Operators. 'Tok' is the token for the operator.
bool isConstantEvaluatedContext() const
bool BuiltinElementwiseTernaryMath(CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr=EltwiseBuiltinArgTyRestriction::FloatTy)
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult BuiltinShuffleVector(CallExpr *TheCall)
BuiltinShuffleVector - Handle __builtin_shufflevector.
QualType GetSignedVectorType(QualType V)
Return a signed ext_vector_type that is of identical size and number of elements.
void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc)
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
static bool getFormatStringInfo(const Decl *Function, unsigned FormatIdx, unsigned FirstArg, FormatStringInfo *FSI)
Given a function and its FormatAttr or FormatMatchesAttr info, attempts to populate the FomatStringIn...
bool BuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, unsigned ArgNum, unsigned ArgBits)
BuiltinConstantArgShiftedByteOr0xFF - Check if argument ArgNum of TheCall is a constant expression re...
SourceManager & SourceMgr
ExprResult UsualUnaryFPConversions(Expr *E)
UsualUnaryFPConversions - Promotes floating-point types according to the current language semantics.
DiagnosticsEngine & Diags
NamespaceDecl * getStdNamespace() const
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
void checkVariadicArgument(const Expr *E, VariadicCallType CT)
Check to see if the given expression is a valid argument to a variadic function, issuing a diagnostic...
void checkLifetimeCaptureBy(FunctionDecl *FDecl, bool IsMemberFunction, const Expr *ThisArg, ArrayRef< const Expr * > Args)
void runWithSufficientStackSpace(SourceLocation Loc, llvm::function_ref< void()> Fn)
Run some code with "sufficient" stack space.
bool BuiltinConstantArgPower2(CallExpr *TheCall, unsigned ArgNum)
BuiltinConstantArgPower2 - Check if argument ArgNum of TheCall is a constant expression representing ...
void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse=true)
Mark a function referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
ExprResult BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, SourceLocation RParenLoc, MultiExprArg Args, AtomicExpr::AtomicOp Op, AtomicArgumentOrder ArgOrder=AtomicArgumentOrder::API)
ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr)
ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
SemaLoongArch & LoongArch()
@ Diagnose
Diagnose issues that are non-constant or that are extensions.
bool CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ThrowTy, Expr *E)
CheckCXXThrowOperand - Validate the operand of a throw.
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, const FunctionProtoType *Proto)
CheckFunctionCall - Check a direct function call for various correctness and safety properties not st...
void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, const Expr *ThisArg, ArrayRef< const Expr * > Args, bool IsMemberFunction, SourceLocation Loc, SourceRange Range, VariadicCallType CallType)
Handles the checks for format strings, non-POD arguments to vararg functions, NULL arguments passed t...
ShuffleVectorExpr - clang-specific builtin-in function __builtin_shufflevector.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
bool isInSystemMacro(SourceLocation loc) const
Returns whether Loc is expanded from a macro in a system header.
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
unsigned getLength() const
StringLiteralKind getKind() const
SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken=nullptr, unsigned *StartTokenByteOffset=nullptr) const
getLocationOfByte - Return a source location that points to the specified byte of this string literal...
unsigned getByteLength() const
StringRef getString() const
SourceLocation getEndLoc() const LLVM_READONLY
unsigned getCharByteWidth() const
bool isBeingDefined() const
Return true if this decl is currently being defined.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Exposes information about the current target.
virtual bool supportsCpuSupports() const
virtual bool validateCpuIs(StringRef Name) const
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
unsigned getTypeWidth(IntType T) const
Return the width (in bits) of the specified integer type enum.
IntType getSizeType() const
virtual bool validateCpuSupports(StringRef Name) const
virtual bool supportsCpuIs() const
const TemplateArgument & get(unsigned Idx) const
Retrieve the template argument at a given index.
@ Type
The template argument is a type.
The base class of all kinds of template declarations (e.g., class, function, etc.).
Base wrapper for a particular "section" of type source info.
SourceRange getSourceRange() const LLVM_READONLY
Get the full source range.
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
SourceLocation getBeginLoc() const
Get the begin source location.
Represents a typeof (or typeof) expression (a C23 feature and GCC extension) or a typeof_unqual expre...
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
bool isBlockPointerType() const
bool isBooleanType() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
const RecordType * getAsUnionType() const
NOTE: getAs*ArrayType are methods on ASTContext.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
bool isIntegralOrUnscopedEnumerationType() const
Determine whether this type is an integral or unscoped enumeration type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool canDecayToPointerType() const
Determines whether this type can decay to a pointer type.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
bool isVoidPointerType() const
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
bool isFunctionPointerType() const
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
bool isScalarType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
bool isVariableArrayType() const
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isExtVectorType() const
bool isExtVectorBoolType() const
QualType getSveEltType(const ASTContext &Ctx) const
Returns the representative type for the element of an SVE builtin type.
bool isBitIntType() const
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isBuiltinType() const
Helper methods to distinguish type categories.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
RecordDecl * castAsRecordDecl() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
QualType getCanonicalTypeInternal() const
bool isWebAssemblyTableType() const
Returns true if this is a WebAssembly table type: either an array of reference types,...
bool isAtomicType() const
bool isFunctionProtoType() const
bool isStandardLayoutType() const
Test if this type is a standard-layout type.
EnumDecl * castAsEnumDecl() const
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isUnscopedEnumerationType() const
bool isObjCObjectType() const
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isUndeducedType() const
Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...
bool isObjectType() const
Determine whether this type is an object type.
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
bool isFunctionType() const
bool isObjCObjectPointerType() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isStructureOrClassType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
TypeClass getTypeClass() const
bool isCanonicalUnqualified() const
Determines if this type would be canonical if it had no further qualification.
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
bool isRecordType() const
bool isObjCRetainableType() const
std::optional< NullabilityKind > getNullability() const
Determine the nullability of the given type.
bool isSizelessVectorType() const
Returns true for all scalable vector types.
QualType getSizelessVectorEltType(const ASTContext &Ctx) const
Returns the representative type for the element of a sizeless vector builtin type.
Base class for declarations which introduce a typedef-name.
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a C++ unqualified-id that has been parsed.
void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Specify that this unqualified-id was parsed as an identifier.
A set of unresolved declarations.
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isWeak() const
Determine whether this symbol is weakly-imported, or declared with the weak or weak-ref attr.
Represents a variable declaration or definition.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
WhileStmt - This represents a 'while' stmt.
std::string getRepresentativeTypeName(ASTContext &C) const
MatchKind matchesType(ASTContext &C, QualType argTy) const
const char * getStart() const
HowSpecified getHowSpecified() const
unsigned getConstantLength() const
const char * toString() const
const char * getPosition() const
const OptionalFlag & isPrivate() const
bool hasValidLeftJustified() const
bool hasValidFieldWidth() const
bool hasValidSpacePrefix() const
const OptionalAmount & getPrecision() const
const OptionalFlag & hasSpacePrefix() const
bool usesPositionalArg() const
const OptionalFlag & isSensitive() const
const OptionalFlag & isLeftJustified() const
bool hasValidPrecision() const
const OptionalFlag & hasLeadingZeros() const
const OptionalFlag & hasAlternativeForm() const
bool hasValidLeadingZeros() const
void toString(raw_ostream &os) const
const PrintfConversionSpecifier & getConversionSpecifier() const
const OptionalFlag & hasPlusPrefix() const
const OptionalFlag & hasThousandsGrouping() const
bool hasValidThousandsGroupingPrefix() const
ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const
Returns the builtin type that a data argument paired with this format specifier should have.
const OptionalFlag & isPublic() const
bool consumesDataArgument() const
bool hasValidPlusPrefix() const
bool hasValidAlternativeForm() const
bool consumesDataArgument() const
const ScanfConversionSpecifier & getConversionSpecifier() const
ArgType getArgType(ASTContext &Ctx) const
void markSafeWeakUse(const Expr *E)
Record that a given expression is a "safe" access of a weak object (e.g.
Defines the clang::TargetInfo interface.
__inline void unsigned int _2
Pieces specific to fprintf format strings.
Pieces specific to fscanf format strings.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< PointerType > pointerType
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
uint32_t Literal
Literals are represented as positive integers.
ComparisonResult
Indicates the result of a tentative comparison.
bool isObjC(ID Id)
isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
@ After
Like System, but searched after the system directories.
@ FixIt
Parse and apply any fixits to the source.
bool GT(InterpState &S, CodePtr OpPC)
bool LT(InterpState &S, CodePtr OpPC)
bool NE(InterpState &S, CodePtr OpPC)
bool LE(InterpState &S, CodePtr OpPC)
bool Cast(InterpState &S, CodePtr OpPC)
bool EQ(InterpState &S, CodePtr OpPC)
bool GE(InterpState &S, CodePtr OpPC)
void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, Expr *Init)
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
bool isa(CodeGen::Address addr)
Expr * IgnoreElidableImplicitConstructorSingleStep(Expr *E)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool hasSpecificAttr(const Container &container)
@ Arithmetic
An arithmetic operation.
@ Comparison
A comparison.
@ NonNull
Values of this type can never be null.
Expr * IgnoreExprNodes(Expr *E, FnTys &&... Fns)
Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, Recursively apply each of the f...
@ Success
Annotation was successful.
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
@ OK_Ordinary
An ordinary object is located at an address in memory.
std::string FormatUTFCodeUnitAsCodepoint(unsigned Value, QualType T)
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
@ Seq
'seq' clause, allowed on 'loop' and 'routine' directives.
SmallVector< Attr *, 4 > AttrVec
AttrVec - A vector of Attr, which is how they are stored on the AST.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Dependent
Parse the block as a dependent block, which may be used in some template instantiations but not other...
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD)
MutableArrayRef< Expr * > MultiExprArg
@ Internal
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
@ Result
The result type of a method or function.
ActionResult< ParsedType > TypeResult
const FunctionProtoType * T
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
CastKind
CastKind - The kind of operation required for a conversion.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
for(const auto &A :T->param_types())
Expr * IgnoreImplicitAsWrittenSingleStep(Expr *E)
CallingConv
CallingConv - Specifies the calling convention that a function uses.
@ Generic
not a target-specific vector type
U cast(CodeGen::Address addr)
@ None
No keyword precedes the qualified type name.
@ Enum
The "enum" keyword introduces the elaborated-type-specifier.
ActionResult< Expr * > ExprResult
@ Other
Other implicit parameter.
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Extra information about a function prototype.
unsigned AArch64SMEAttributes
unsigned AnonymousTagLocations
When printing an anonymous tag name, also print the location of that entity (e.g.,...
unsigned Indentation
The number of spaces to use to indent each line.
enum clang::Sema::CodeSynthesisContext::SynthesisKind Kind
SourceLocation PointOfInstantiation
The point of instantiation or synthesis within the source code.
unsigned NumCallArgs
The number of expressions in CallArgs.
const Expr *const * CallArgs
The list of argument expressions in a synthesized call.
@ BuildingBuiltinDumpStructCall
We are building an implied call from __builtin_dump_struct.
SmallVector< MisalignedMember, 4 > MisalignedMembers
Small set of gathered accesses to potentially misaligned members due to the packed attribute.