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)
3584 UT->getDecl()->getMostRecentDecl()->hasAttr<TransparentUnionAttr>()) {
3585 if (
const auto *CLE = dyn_cast<CompoundLiteralExpr>(
Expr))
3586 if (
const auto *ILE = dyn_cast<InitListExpr>(CLE->getInitializer()))
3587 Expr = ILE->getInit(0);
3597 const Expr *ArgExpr,
3601 S.
PDiag(diag::warn_null_arg)
3607 if (
auto nullability =
type->getNullability())
3618 assert((FDecl || Proto) &&
"Need a function declaration or prototype");
3624 llvm::SmallBitVector NonNullArgs;
3630 for (
const auto *Arg : Args)
3637 unsigned IdxAST = Idx.getASTIndex();
3638 if (IdxAST >= Args.size())
3640 if (NonNullArgs.empty())
3641 NonNullArgs.resize(Args.size());
3642 NonNullArgs.set(IdxAST);
3651 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl))
3656 unsigned ParamIndex = 0;
3658 I != E; ++I, ++ParamIndex) {
3661 if (NonNullArgs.empty())
3662 NonNullArgs.resize(Args.size());
3664 NonNullArgs.set(ParamIndex);
3671 if (
const ValueDecl *VD = dyn_cast<ValueDecl>(FDecl)) {
3676 type = blockType->getPointeeType();
3690 if (NonNullArgs.empty())
3691 NonNullArgs.resize(Args.size());
3693 NonNullArgs.set(Index);
3702 for (
unsigned ArgIndex = 0, ArgIndexEnd = NonNullArgs.size();
3703 ArgIndex != ArgIndexEnd; ++ArgIndex) {
3704 if (NonNullArgs[ArgIndex])
3710 StringRef ParamName,
QualType ArgTy,
3733 CharUnits ParamAlign =
Context.getTypeAlignInChars(ParamTy);
3734 CharUnits ArgAlign =
Context.getTypeAlignInChars(ArgTy);
3738 if (ArgAlign < ParamAlign)
3739 Diag(Loc, diag::warn_param_mismatched_alignment)
3741 << ParamName << (FDecl !=
nullptr) << FDecl;
3745 const Expr *ThisArg,
3747 if (!FD || Args.empty())
3749 auto GetArgAt = [&](
int Idx) ->
const Expr * {
3750 if (Idx == LifetimeCaptureByAttr::Global ||
3751 Idx == LifetimeCaptureByAttr::Unknown)
3753 if (IsMemberFunction && Idx == 0)
3755 return Args[Idx - IsMemberFunction];
3757 auto HandleCaptureByAttr = [&](
const LifetimeCaptureByAttr *
Attr,
3762 Expr *Captured =
const_cast<Expr *
>(GetArgAt(ArgIdx));
3763 for (
int CapturingParamIdx :
Attr->params()) {
3766 if (CapturingParamIdx == LifetimeCaptureByAttr::This &&
3769 Expr *Capturing =
const_cast<Expr *
>(GetArgAt(CapturingParamIdx));
3777 I + IsMemberFunction);
3779 if (IsMemberFunction) {
3787 HandleCaptureByAttr(ATL.
getAttrAs<LifetimeCaptureByAttr>(), 0);
3800 llvm::SmallBitVector CheckedVarArgs;
3802 for (
const auto *I : FDecl->
specific_attrs<FormatMatchesAttr>()) {
3804 CheckedVarArgs.resize(Args.size());
3805 CheckFormatString(I, Args, IsMemberFunction, CallType, Loc, Range,
3810 CheckedVarArgs.resize(Args.size());
3811 CheckFormatArguments(I, Args, IsMemberFunction, CallType, Loc, Range,
3818 auto *FD = dyn_cast_or_null<FunctionDecl>(FDecl);
3822 : isa_and_nonnull<FunctionDecl>(FDecl)
3824 : isa_and_nonnull<ObjCMethodDecl>(FDecl)
3828 for (
unsigned ArgIdx = NumParams; ArgIdx < Args.size(); ++ArgIdx) {
3830 if (
const Expr *Arg = Args[ArgIdx]) {
3831 if (CheckedVarArgs.empty() || !CheckedVarArgs[ArgIdx])
3838 if (FDecl || Proto) {
3843 for (
const auto *I : FDecl->
specific_attrs<ArgumentWithTypeTagAttr>())
3844 CheckArgumentWithTypeTag(I, Args, Loc);
3850 if (!Proto && FDecl) {
3852 if (isa_and_nonnull<FunctionProtoType>(FT))
3858 const auto N = std::min<unsigned>(Proto->
getNumParams(), Args.size());
3860 bool IsScalableArg =
false;
3861 for (
unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
3863 if (
const Expr *Arg = Args[ArgIdx]) {
3867 if (
Context.getTargetInfo().getTriple().isOSAIX() && FDecl && Arg &&
3875 IsScalableArg =
true;
3877 CheckArgAlignment(Arg->
getExprLoc(), FDecl, std::to_string(ArgIdx + 1),
3886 if (
auto *CallerFD = dyn_cast<FunctionDecl>(
CurContext)) {
3887 llvm::StringMap<bool> CallerFeatureMap;
3888 Context.getFunctionFeatureMap(CallerFeatureMap, CallerFD);
3889 if (!CallerFeatureMap.contains(
"sme"))
3890 Diag(Loc, diag::err_sme_call_in_non_sme_target);
3891 }
else if (!
Context.getTargetInfo().hasFeature(
"sme")) {
3892 Diag(Loc, diag::err_sme_call_in_non_sme_target);
3901 const auto *CallerFD = dyn_cast<FunctionDecl>(
CurContext);
3903 (IsScalableArg || IsScalableRet)) {
3904 bool IsCalleeStreaming =
3906 bool IsCalleeStreamingCompatible =
3910 if (!IsCalleeStreamingCompatible &&
3914 unsigned VL = LO.VScaleMin * 128;
3915 unsigned SVL = LO.VScaleStreamingMin * 128;
3916 bool IsVLMismatch = VL && SVL && VL != SVL;
3918 auto EmitDiag = [&](
bool IsArg) {
3922 Diag(Loc, diag::warn_sme_streaming_compatible_vl_mismatch)
3923 << IsArg << IsCalleeStreaming << SVL << VL;
3926 Diag(Loc, diag::err_sme_streaming_transition_vl_mismatch)
3927 << IsArg << SVL << VL;
3929 Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
3946 bool CallerHasZAState =
false;
3947 bool CallerHasZT0State =
false;
3949 auto *
Attr = CallerFD->getAttr<ArmNewAttr>();
3951 CallerHasZAState =
true;
3953 CallerHasZT0State =
true;
3957 FPT->getExtProtoInfo().AArch64SMEAttributes) !=
3959 CallerHasZT0State |=
3961 FPT->getExtProtoInfo().AArch64SMEAttributes) !=
3967 Diag(Loc, diag::err_sme_za_call_no_za_state);
3970 Diag(Loc, diag::err_sme_zt0_call_no_zt0_state);
3974 Diag(Loc, diag::err_sme_unimplemented_za_save_restore);
3975 Diag(Loc, diag::note_sme_use_preserves_za);
3980 if (FDecl && FDecl->
hasAttr<AllocAlignAttr>()) {
3981 auto *AA = FDecl->
getAttr<AllocAlignAttr>();
3982 const Expr *Arg = Args[AA->getParamIndex().getASTIndex()];
3983 if (!Arg->isValueDependent()) {
3985 if (Arg->EvaluateAsInt(Align,
Context)) {
3986 const llvm::APSInt &I = Align.
Val.
getInt();
3987 if (!I.isPowerOf2())
3988 Diag(Arg->getExprLoc(), diag::warn_alignment_not_power_of_two)
3989 << Arg->getSourceRange();
3992 Diag(Arg->getExprLoc(), diag::warn_assume_aligned_too_great)
4018 Loc, FDecl,
"'this'", Context.getPointerType(ThisType),
4019 Context.getPointerType(Ctor->getFunctionObjectParameterType()));
4021 checkCall(FDecl, Proto,
nullptr, Args,
true,
4030 IsMemberOperatorCall;
4036 Expr *ImplicitThis =
nullptr;
4041 ImplicitThis = Args[0];
4044 }
else if (IsMemberFunction && !FDecl->
isStatic() &&
4055 ThisType =
Context.getPointerType(ThisType);
4061 CheckArgAlignment(TheCall->
getRParenLoc(), FDecl,
"'this'", ThisType,
4079 CheckAbsoluteValueFunction(TheCall, FDecl);
4080 CheckMaxUnsignedZero(TheCall, FDecl);
4081 CheckInfNaNFunction(TheCall, FDecl);
4092 case Builtin::BIstrlcpy:
4093 case Builtin::BIstrlcat:
4094 CheckStrlcpycatArguments(TheCall, FnInfo);
4096 case Builtin::BIstrncat:
4097 CheckStrncatArguments(TheCall, FnInfo);
4099 case Builtin::BIfree:
4100 CheckFreeArguments(TheCall);
4103 CheckMemaccessArguments(TheCall, CMId, FnInfo);
4112 if (
const auto *
V = dyn_cast<VarDecl>(NDecl))
4113 Ty =
V->getType().getNonReferenceType();
4114 else if (
const auto *F = dyn_cast<FieldDecl>(NDecl))
4115 Ty = F->getType().getNonReferenceType();
4152 if (!llvm::isValidAtomicOrderingCABI(Ordering))
4155 auto OrderingCABI = (llvm::AtomicOrderingCABI)Ordering;
4157 case AtomicExpr::AO__c11_atomic_init:
4158 case AtomicExpr::AO__opencl_atomic_init:
4159 llvm_unreachable(
"There is no ordering argument for an init");
4161 case AtomicExpr::AO__c11_atomic_load:
4162 case AtomicExpr::AO__opencl_atomic_load:
4163 case AtomicExpr::AO__hip_atomic_load:
4164 case AtomicExpr::AO__atomic_load_n:
4165 case AtomicExpr::AO__atomic_load:
4166 case AtomicExpr::AO__scoped_atomic_load_n:
4167 case AtomicExpr::AO__scoped_atomic_load:
4168 return OrderingCABI != llvm::AtomicOrderingCABI::release &&
4169 OrderingCABI != llvm::AtomicOrderingCABI::acq_rel;
4171 case AtomicExpr::AO__c11_atomic_store:
4172 case AtomicExpr::AO__opencl_atomic_store:
4173 case AtomicExpr::AO__hip_atomic_store:
4174 case AtomicExpr::AO__atomic_store:
4175 case AtomicExpr::AO__atomic_store_n:
4176 case AtomicExpr::AO__scoped_atomic_store:
4177 case AtomicExpr::AO__scoped_atomic_store_n:
4178 case AtomicExpr::AO__atomic_clear:
4179 return OrderingCABI != llvm::AtomicOrderingCABI::consume &&
4180 OrderingCABI != llvm::AtomicOrderingCABI::acquire &&
4181 OrderingCABI != llvm::AtomicOrderingCABI::acq_rel;
4240 const unsigned NumForm = ClearByte + 1;
4241 const unsigned NumArgs[] = {2, 2, 3, 3, 3, 3, 4, 5, 6, 2, 2};
4242 const unsigned NumVals[] = {1, 0, 1, 1, 1, 1, 2, 2, 3, 0, 0};
4250 static_assert(
sizeof(NumArgs)/
sizeof(NumArgs[0]) == NumForm
4251 &&
sizeof(NumVals)/
sizeof(NumVals[0]) == NumForm,
4252 "need to update code for modified forms");
4253 static_assert(AtomicExpr::AO__atomic_add_fetch == 0 &&
4254 AtomicExpr::AO__atomic_xor_fetch + 1 ==
4255 AtomicExpr::AO__c11_atomic_compare_exchange_strong,
4256 "need to update code for modified C11 atomics");
4257 bool IsOpenCL = Op >= AtomicExpr::AO__opencl_atomic_compare_exchange_strong &&
4258 Op <= AtomicExpr::AO__opencl_atomic_store;
4259 bool IsHIP = Op >= AtomicExpr::AO__hip_atomic_compare_exchange_strong &&
4260 Op <= AtomicExpr::AO__hip_atomic_store;
4261 bool IsScoped = Op >= AtomicExpr::AO__scoped_atomic_add_fetch &&
4262 Op <= AtomicExpr::AO__scoped_atomic_xor_fetch;
4263 bool IsC11 = (Op >= AtomicExpr::AO__c11_atomic_compare_exchange_strong &&
4264 Op <= AtomicExpr::AO__c11_atomic_store) ||
4266 bool IsN = Op == AtomicExpr::AO__atomic_load_n ||
4267 Op == AtomicExpr::AO__atomic_store_n ||
4268 Op == AtomicExpr::AO__atomic_exchange_n ||
4269 Op == AtomicExpr::AO__atomic_compare_exchange_n ||
4270 Op == AtomicExpr::AO__scoped_atomic_load_n ||
4271 Op == AtomicExpr::AO__scoped_atomic_store_n ||
4272 Op == AtomicExpr::AO__scoped_atomic_exchange_n ||
4273 Op == AtomicExpr::AO__scoped_atomic_compare_exchange_n;
4277 enum ArithOpExtraValueType {
4282 unsigned ArithAllows = AOEVT_None;
4285 case AtomicExpr::AO__c11_atomic_init:
4286 case AtomicExpr::AO__opencl_atomic_init:
4290 case AtomicExpr::AO__c11_atomic_load:
4291 case AtomicExpr::AO__opencl_atomic_load:
4292 case AtomicExpr::AO__hip_atomic_load:
4293 case AtomicExpr::AO__atomic_load_n:
4294 case AtomicExpr::AO__scoped_atomic_load_n:
4298 case AtomicExpr::AO__atomic_load:
4299 case AtomicExpr::AO__scoped_atomic_load:
4303 case AtomicExpr::AO__c11_atomic_store:
4304 case AtomicExpr::AO__opencl_atomic_store:
4305 case AtomicExpr::AO__hip_atomic_store:
4306 case AtomicExpr::AO__atomic_store:
4307 case AtomicExpr::AO__atomic_store_n:
4308 case AtomicExpr::AO__scoped_atomic_store:
4309 case AtomicExpr::AO__scoped_atomic_store_n:
4312 case AtomicExpr::AO__atomic_fetch_add:
4313 case AtomicExpr::AO__atomic_fetch_sub:
4314 case AtomicExpr::AO__atomic_add_fetch:
4315 case AtomicExpr::AO__atomic_sub_fetch:
4316 case AtomicExpr::AO__scoped_atomic_fetch_add:
4317 case AtomicExpr::AO__scoped_atomic_fetch_sub:
4318 case AtomicExpr::AO__scoped_atomic_add_fetch:
4319 case AtomicExpr::AO__scoped_atomic_sub_fetch:
4320 case AtomicExpr::AO__c11_atomic_fetch_add:
4321 case AtomicExpr::AO__c11_atomic_fetch_sub:
4322 case AtomicExpr::AO__opencl_atomic_fetch_add:
4323 case AtomicExpr::AO__opencl_atomic_fetch_sub:
4324 case AtomicExpr::AO__hip_atomic_fetch_add:
4325 case AtomicExpr::AO__hip_atomic_fetch_sub:
4326 ArithAllows = AOEVT_Pointer | AOEVT_FP;
4329 case AtomicExpr::AO__atomic_fetch_max:
4330 case AtomicExpr::AO__atomic_fetch_min:
4331 case AtomicExpr::AO__atomic_max_fetch:
4332 case AtomicExpr::AO__atomic_min_fetch:
4333 case AtomicExpr::AO__scoped_atomic_fetch_max:
4334 case AtomicExpr::AO__scoped_atomic_fetch_min:
4335 case AtomicExpr::AO__scoped_atomic_max_fetch:
4336 case AtomicExpr::AO__scoped_atomic_min_fetch:
4337 case AtomicExpr::AO__c11_atomic_fetch_max:
4338 case AtomicExpr::AO__c11_atomic_fetch_min:
4339 case AtomicExpr::AO__opencl_atomic_fetch_max:
4340 case AtomicExpr::AO__opencl_atomic_fetch_min:
4341 case AtomicExpr::AO__hip_atomic_fetch_max:
4342 case AtomicExpr::AO__hip_atomic_fetch_min:
4343 ArithAllows = AOEVT_FP;
4346 case AtomicExpr::AO__c11_atomic_fetch_and:
4347 case AtomicExpr::AO__c11_atomic_fetch_or:
4348 case AtomicExpr::AO__c11_atomic_fetch_xor:
4349 case AtomicExpr::AO__hip_atomic_fetch_and:
4350 case AtomicExpr::AO__hip_atomic_fetch_or:
4351 case AtomicExpr::AO__hip_atomic_fetch_xor:
4352 case AtomicExpr::AO__c11_atomic_fetch_nand:
4353 case AtomicExpr::AO__opencl_atomic_fetch_and:
4354 case AtomicExpr::AO__opencl_atomic_fetch_or:
4355 case AtomicExpr::AO__opencl_atomic_fetch_xor:
4356 case AtomicExpr::AO__atomic_fetch_and:
4357 case AtomicExpr::AO__atomic_fetch_or:
4358 case AtomicExpr::AO__atomic_fetch_xor:
4359 case AtomicExpr::AO__atomic_fetch_nand:
4360 case AtomicExpr::AO__atomic_and_fetch:
4361 case AtomicExpr::AO__atomic_or_fetch:
4362 case AtomicExpr::AO__atomic_xor_fetch:
4363 case AtomicExpr::AO__atomic_nand_fetch:
4364 case AtomicExpr::AO__scoped_atomic_fetch_and:
4365 case AtomicExpr::AO__scoped_atomic_fetch_or:
4366 case AtomicExpr::AO__scoped_atomic_fetch_xor:
4367 case AtomicExpr::AO__scoped_atomic_fetch_nand:
4368 case AtomicExpr::AO__scoped_atomic_and_fetch:
4369 case AtomicExpr::AO__scoped_atomic_or_fetch:
4370 case AtomicExpr::AO__scoped_atomic_xor_fetch:
4371 case AtomicExpr::AO__scoped_atomic_nand_fetch:
4375 case AtomicExpr::AO__c11_atomic_exchange:
4376 case AtomicExpr::AO__hip_atomic_exchange:
4377 case AtomicExpr::AO__opencl_atomic_exchange:
4378 case AtomicExpr::AO__atomic_exchange_n:
4379 case AtomicExpr::AO__scoped_atomic_exchange_n:
4383 case AtomicExpr::AO__atomic_exchange:
4384 case AtomicExpr::AO__scoped_atomic_exchange:
4388 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
4389 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
4390 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
4391 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
4392 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
4393 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
4397 case AtomicExpr::AO__atomic_compare_exchange:
4398 case AtomicExpr::AO__atomic_compare_exchange_n:
4399 case AtomicExpr::AO__scoped_atomic_compare_exchange:
4400 case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
4404 case AtomicExpr::AO__atomic_test_and_set:
4405 Form = TestAndSetByte;
4408 case AtomicExpr::AO__atomic_clear:
4413 unsigned AdjustedNumArgs = NumArgs[Form];
4414 if ((IsOpenCL || IsHIP || IsScoped) &&
4415 Op != AtomicExpr::AO__opencl_atomic_init)
4418 if (Args.size() < AdjustedNumArgs) {
4419 Diag(CallRange.
getEnd(), diag::err_typecheck_call_too_few_args)
4420 << 0 << AdjustedNumArgs << static_cast<unsigned>(Args.size())
4423 }
else if (Args.size() > AdjustedNumArgs) {
4424 Diag(Args[AdjustedNumArgs]->getBeginLoc(),
4425 diag::err_typecheck_call_too_many_args)
4426 << 0 << AdjustedNumArgs << static_cast<unsigned>(Args.size())
4432 Expr *Ptr = Args[0];
4437 Ptr = ConvertedPtr.
get();
4440 Diag(ExprRange.
getBegin(), diag::err_atomic_builtin_must_be_pointer)
4450 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_atomic)
4456 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_non_const_atomic)
4462 }
else if (Form != Load && Form != LoadCopy) {
4464 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_non_const_pointer)
4470 if (Form != TestAndSetByte && Form != ClearByte) {
4473 diag::err_incomplete_type))
4476 if (
Context.getTypeInfoInChars(AtomTy).Width.isZero()) {
4477 Diag(ExprRange.
getBegin(), diag::err_atomic_builtin_must_be_pointer)
4487 pointerType->getPointeeType().getCVRQualifiers());
4497 diag::err_atomic_op_needs_non_address_discriminated_pointer)
4506 auto IsAllowedValueType = [&](
QualType ValType,
4507 unsigned AllowedType) ->
bool {
4511 return AllowedType & AOEVT_Pointer;
4516 &
Context.getTargetInfo().getLongDoubleFormat() ==
4517 &llvm::APFloat::x87DoubleExtended())
4521 if (!IsAllowedValueType(ValType, ArithAllows)) {
4522 auto DID = ArithAllows & AOEVT_FP
4523 ? (ArithAllows & AOEVT_Pointer
4524 ? diag::err_atomic_op_needs_atomic_int_ptr_or_fp
4525 : diag::err_atomic_op_needs_atomic_int_or_fp)
4526 : diag::err_atomic_op_needs_atomic_int;
4533 diag::err_incomplete_type)) {
4539 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_atomic_int_or_ptr)
4550 Diag(ExprRange.
getBegin(), diag::err_atomic_op_needs_trivial_copy)
4566 Diag(ExprRange.
getBegin(), diag::err_arc_atomic_ownership)
4578 if (Form ==
Copy || Form == LoadCopy || Form == GNUXchg || Form ==
Init ||
4581 else if (Form == C11CmpXchg || Form == GNUCmpXchg || Form == TestAndSetByte)
4587 bool IsPassedByAddress =
false;
4588 if (!IsC11 && !IsHIP && !IsN) {
4590 IsPassedByAddress =
true;
4595 APIOrderedArgs.push_back(Args[0]);
4599 APIOrderedArgs.push_back(Args[1]);
4605 APIOrderedArgs.push_back(Args[2]);
4606 APIOrderedArgs.push_back(Args[1]);
4609 APIOrderedArgs.push_back(Args[2]);
4610 APIOrderedArgs.push_back(Args[3]);
4611 APIOrderedArgs.push_back(Args[1]);
4614 APIOrderedArgs.push_back(Args[2]);
4615 APIOrderedArgs.push_back(Args[4]);
4616 APIOrderedArgs.push_back(Args[1]);
4617 APIOrderedArgs.push_back(Args[3]);
4620 APIOrderedArgs.push_back(Args[2]);
4621 APIOrderedArgs.push_back(Args[4]);
4622 APIOrderedArgs.push_back(Args[5]);
4623 APIOrderedArgs.push_back(Args[1]);
4624 APIOrderedArgs.push_back(Args[3]);
4626 case TestAndSetByte:
4628 APIOrderedArgs.push_back(Args[1]);
4632 APIOrderedArgs.append(Args.begin(), Args.end());
4639 for (
unsigned i = 0; i != APIOrderedArgs.size(); ++i) {
4641 if (i < NumVals[Form] + 1) {
4654 assert(Form != Load);
4656 Ty =
Context.getPointerDiffType();
4659 else if (Form ==
Copy || Form == Xchg) {
4660 if (IsPassedByAddress) {
4667 Expr *ValArg = APIOrderedArgs[i];
4674 AS = PtrTy->getPointeeType().getAddressSpace();
4683 if (IsPassedByAddress)
4703 APIOrderedArgs[i] = Arg.
get();
4708 SubExprs.push_back(Ptr);
4712 SubExprs.push_back(APIOrderedArgs[1]);
4715 case TestAndSetByte:
4717 SubExprs.push_back(APIOrderedArgs[1]);
4723 SubExprs.push_back(APIOrderedArgs[2]);
4724 SubExprs.push_back(APIOrderedArgs[1]);
4728 SubExprs.push_back(APIOrderedArgs[3]);
4729 SubExprs.push_back(APIOrderedArgs[1]);
4730 SubExprs.push_back(APIOrderedArgs[2]);
4733 SubExprs.push_back(APIOrderedArgs[3]);
4734 SubExprs.push_back(APIOrderedArgs[1]);
4735 SubExprs.push_back(APIOrderedArgs[4]);
4736 SubExprs.push_back(APIOrderedArgs[2]);
4739 SubExprs.push_back(APIOrderedArgs[4]);
4740 SubExprs.push_back(APIOrderedArgs[1]);
4741 SubExprs.push_back(APIOrderedArgs[5]);
4742 SubExprs.push_back(APIOrderedArgs[2]);
4743 SubExprs.push_back(APIOrderedArgs[3]);
4748 if (SubExprs.size() >= 2 && Form !=
Init) {
4749 std::optional<llvm::APSInt>
Success =
4750 SubExprs[1]->getIntegerConstantExpr(
Context);
4752 Diag(SubExprs[1]->getBeginLoc(),
4753 diag::warn_atomic_op_has_invalid_memory_order)
4754 << (Form == C11CmpXchg || Form == GNUCmpXchg)
4755 << SubExprs[1]->getSourceRange();
4757 if (SubExprs.size() >= 5) {
4758 if (std::optional<llvm::APSInt> Failure =
4759 SubExprs[3]->getIntegerConstantExpr(
Context)) {
4760 if (!llvm::is_contained(
4761 {llvm::AtomicOrderingCABI::relaxed,
4762 llvm::AtomicOrderingCABI::consume,
4763 llvm::AtomicOrderingCABI::acquire,
4764 llvm::AtomicOrderingCABI::seq_cst},
4765 (llvm::AtomicOrderingCABI)Failure->getSExtValue())) {
4766 Diag(SubExprs[3]->getBeginLoc(),
4767 diag::warn_atomic_op_has_invalid_memory_order)
4768 << 2 << SubExprs[3]->getSourceRange();
4775 auto *
Scope = Args[Args.size() - 1];
4776 if (std::optional<llvm::APSInt>
Result =
4778 if (!ScopeModel->isValid(
Result->getZExtValue()))
4779 Diag(
Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_sync_scope)
4780 <<
Scope->getSourceRange();
4782 SubExprs.push_back(
Scope);
4788 if ((Op == AtomicExpr::AO__c11_atomic_load ||
4789 Op == AtomicExpr::AO__c11_atomic_store ||
4790 Op == AtomicExpr::AO__opencl_atomic_load ||
4791 Op == AtomicExpr::AO__hip_atomic_load ||
4792 Op == AtomicExpr::AO__opencl_atomic_store ||
4793 Op == AtomicExpr::AO__hip_atomic_store) &&
4794 Context.AtomicUsesUnsupportedLibcall(AE))
4796 << ((Op == AtomicExpr::AO__c11_atomic_load ||
4797 Op == AtomicExpr::AO__opencl_atomic_load ||
4798 Op == AtomicExpr::AO__hip_atomic_load)
4803 Diag(Ptr->
getExprLoc(), diag::err_atomic_builtin_bit_int_prohibit);
4819 assert(Fn &&
"builtin call without direct callee!");
4835 CallExpr *TheCall =
static_cast<CallExpr *
>(TheCallResult.
get());
4842 Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4844 <<
Callee->getSourceRange();
4853 Expr *FirstArg = TheCall->
getArg(0);
4857 FirstArg = FirstArgResult.
get();
4858 TheCall->
setArg(0, FirstArg);
4870 Diag(DRE->
getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intptr)
4877 diag::err_atomic_op_needs_non_address_discriminated_pointer)
4907 QualType ResultType = ValType;
4912#define BUILTIN_ROW(x) \
4913 { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \
4914 Builtin::BI##x##_8, Builtin::BI##x##_16 }
4916 static const unsigned BuiltinIndices[][5] = {
4941 switch (
Context.getTypeSizeInChars(ValType).getQuantity()) {
4942 case 1: SizeIndex = 0;
break;
4943 case 2: SizeIndex = 1;
break;
4944 case 4: SizeIndex = 2;
break;
4945 case 8: SizeIndex = 3;
break;
4946 case 16: SizeIndex = 4;
break;
4958 unsigned BuiltinIndex, NumFixed = 1;
4959 bool WarnAboutSemanticsChange =
false;
4960 switch (BuiltinID) {
4961 default: llvm_unreachable(
"Unknown overloaded atomic builtin!");
4962 case Builtin::BI__sync_fetch_and_add:
4963 case Builtin::BI__sync_fetch_and_add_1:
4964 case Builtin::BI__sync_fetch_and_add_2:
4965 case Builtin::BI__sync_fetch_and_add_4:
4966 case Builtin::BI__sync_fetch_and_add_8:
4967 case Builtin::BI__sync_fetch_and_add_16:
4971 case Builtin::BI__sync_fetch_and_sub:
4972 case Builtin::BI__sync_fetch_and_sub_1:
4973 case Builtin::BI__sync_fetch_and_sub_2:
4974 case Builtin::BI__sync_fetch_and_sub_4:
4975 case Builtin::BI__sync_fetch_and_sub_8:
4976 case Builtin::BI__sync_fetch_and_sub_16:
4980 case Builtin::BI__sync_fetch_and_or:
4981 case Builtin::BI__sync_fetch_and_or_1:
4982 case Builtin::BI__sync_fetch_and_or_2:
4983 case Builtin::BI__sync_fetch_and_or_4:
4984 case Builtin::BI__sync_fetch_and_or_8:
4985 case Builtin::BI__sync_fetch_and_or_16:
4989 case Builtin::BI__sync_fetch_and_and:
4990 case Builtin::BI__sync_fetch_and_and_1:
4991 case Builtin::BI__sync_fetch_and_and_2:
4992 case Builtin::BI__sync_fetch_and_and_4:
4993 case Builtin::BI__sync_fetch_and_and_8:
4994 case Builtin::BI__sync_fetch_and_and_16:
4998 case Builtin::BI__sync_fetch_and_xor:
4999 case Builtin::BI__sync_fetch_and_xor_1:
5000 case Builtin::BI__sync_fetch_and_xor_2:
5001 case Builtin::BI__sync_fetch_and_xor_4:
5002 case Builtin::BI__sync_fetch_and_xor_8:
5003 case Builtin::BI__sync_fetch_and_xor_16:
5007 case Builtin::BI__sync_fetch_and_nand:
5008 case Builtin::BI__sync_fetch_and_nand_1:
5009 case Builtin::BI__sync_fetch_and_nand_2:
5010 case Builtin::BI__sync_fetch_and_nand_4:
5011 case Builtin::BI__sync_fetch_and_nand_8:
5012 case Builtin::BI__sync_fetch_and_nand_16:
5014 WarnAboutSemanticsChange =
true;
5017 case Builtin::BI__sync_add_and_fetch:
5018 case Builtin::BI__sync_add_and_fetch_1:
5019 case Builtin::BI__sync_add_and_fetch_2:
5020 case Builtin::BI__sync_add_and_fetch_4:
5021 case Builtin::BI__sync_add_and_fetch_8:
5022 case Builtin::BI__sync_add_and_fetch_16:
5026 case Builtin::BI__sync_sub_and_fetch:
5027 case Builtin::BI__sync_sub_and_fetch_1:
5028 case Builtin::BI__sync_sub_and_fetch_2:
5029 case Builtin::BI__sync_sub_and_fetch_4:
5030 case Builtin::BI__sync_sub_and_fetch_8:
5031 case Builtin::BI__sync_sub_and_fetch_16:
5035 case Builtin::BI__sync_and_and_fetch:
5036 case Builtin::BI__sync_and_and_fetch_1:
5037 case Builtin::BI__sync_and_and_fetch_2:
5038 case Builtin::BI__sync_and_and_fetch_4:
5039 case Builtin::BI__sync_and_and_fetch_8:
5040 case Builtin::BI__sync_and_and_fetch_16:
5044 case Builtin::BI__sync_or_and_fetch:
5045 case Builtin::BI__sync_or_and_fetch_1:
5046 case Builtin::BI__sync_or_and_fetch_2:
5047 case Builtin::BI__sync_or_and_fetch_4:
5048 case Builtin::BI__sync_or_and_fetch_8:
5049 case Builtin::BI__sync_or_and_fetch_16:
5053 case Builtin::BI__sync_xor_and_fetch:
5054 case Builtin::BI__sync_xor_and_fetch_1:
5055 case Builtin::BI__sync_xor_and_fetch_2:
5056 case Builtin::BI__sync_xor_and_fetch_4:
5057 case Builtin::BI__sync_xor_and_fetch_8:
5058 case Builtin::BI__sync_xor_and_fetch_16:
5062 case Builtin::BI__sync_nand_and_fetch:
5063 case Builtin::BI__sync_nand_and_fetch_1:
5064 case Builtin::BI__sync_nand_and_fetch_2:
5065 case Builtin::BI__sync_nand_and_fetch_4:
5066 case Builtin::BI__sync_nand_and_fetch_8:
5067 case Builtin::BI__sync_nand_and_fetch_16:
5069 WarnAboutSemanticsChange =
true;
5072 case Builtin::BI__sync_val_compare_and_swap:
5073 case Builtin::BI__sync_val_compare_and_swap_1:
5074 case Builtin::BI__sync_val_compare_and_swap_2:
5075 case Builtin::BI__sync_val_compare_and_swap_4:
5076 case Builtin::BI__sync_val_compare_and_swap_8:
5077 case Builtin::BI__sync_val_compare_and_swap_16:
5082 case Builtin::BI__sync_bool_compare_and_swap:
5083 case Builtin::BI__sync_bool_compare_and_swap_1:
5084 case Builtin::BI__sync_bool_compare_and_swap_2:
5085 case Builtin::BI__sync_bool_compare_and_swap_4:
5086 case Builtin::BI__sync_bool_compare_and_swap_8:
5087 case Builtin::BI__sync_bool_compare_and_swap_16:
5093 case Builtin::BI__sync_lock_test_and_set:
5094 case Builtin::BI__sync_lock_test_and_set_1:
5095 case Builtin::BI__sync_lock_test_and_set_2:
5096 case Builtin::BI__sync_lock_test_and_set_4:
5097 case Builtin::BI__sync_lock_test_and_set_8:
5098 case Builtin::BI__sync_lock_test_and_set_16:
5102 case Builtin::BI__sync_lock_release:
5103 case Builtin::BI__sync_lock_release_1:
5104 case Builtin::BI__sync_lock_release_2:
5105 case Builtin::BI__sync_lock_release_4:
5106 case Builtin::BI__sync_lock_release_8:
5107 case Builtin::BI__sync_lock_release_16:
5113 case Builtin::BI__sync_swap:
5114 case Builtin::BI__sync_swap_1:
5115 case Builtin::BI__sync_swap_2:
5116 case Builtin::BI__sync_swap_4:
5117 case Builtin::BI__sync_swap_8:
5118 case Builtin::BI__sync_swap_16:
5126 Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
5127 << 0 << 1 + NumFixed << TheCall->
getNumArgs() << 0
5128 <<
Callee->getSourceRange();
5132 Diag(TheCall->
getEndLoc(), diag::warn_atomic_implicit_seq_cst)
5133 <<
Callee->getSourceRange();
5135 if (WarnAboutSemanticsChange) {
5136 Diag(TheCall->
getEndLoc(), diag::warn_sync_fetch_and_nand_semantics_change)
5137 <<
Callee->getSourceRange();
5142 unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
5143 std::string NewBuiltinName =
Context.BuiltinInfo.getName(NewBuiltinID);
5144 FunctionDecl *NewBuiltinDecl;
5145 if (NewBuiltinID == BuiltinID)
5146 NewBuiltinDecl = FDecl;
5149 DeclarationName DN(&
Context.Idents.get(NewBuiltinName));
5152 assert(Res.getFoundDecl());
5153 NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl());
5154 if (!NewBuiltinDecl)
5161 for (
unsigned i = 0; i != NumFixed; ++i) {
5190 QualType CalleePtrTy =
Context.getPointerType(NewBuiltinDecl->
getType());
5192 CK_BuiltinFnToFnPtr);
5203 const auto *BitIntValType = ValType->
getAs<BitIntType>();
5204 if (BitIntValType && !llvm::isPowerOf2_64(BitIntValType->getNumBits())) {
5205 Diag(FirstArg->
getExprLoc(), diag::err_atomic_builtin_ext_int_size);
5209 return TheCallResult;
5213 CallExpr *TheCall = (CallExpr *)TheCallResult.
get();
5218 assert((BuiltinID == Builtin::BI__builtin_nontemporal_store ||
5219 BuiltinID == Builtin::BI__builtin_nontemporal_load) &&
5220 "Unexpected nontemporal load/store builtin!");
5221 bool isStore = BuiltinID == Builtin::BI__builtin_nontemporal_store;
5222 unsigned numArgs = isStore ? 2 : 1;
5232 Expr *PointerArg = TheCall->
getArg(numArgs - 1);
5238 PointerArg = PointerArgResult.
get();
5239 TheCall->
setArg(numArgs - 1, PointerArg);
5243 Diag(DRE->
getBeginLoc(), diag::err_nontemporal_builtin_must_be_pointer)
5256 diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector)
5263 return TheCallResult;
5275 return TheCallResult;
5282 auto *
Literal = dyn_cast<StringLiteral>(Arg);
5284 if (
auto *ObjcLiteral = dyn_cast<ObjCStringLiteral>(Arg)) {
5285 Literal = ObjcLiteral->getString();
5289 if (!Literal || (!
Literal->isOrdinary() && !
Literal->isUTF8())) {
5296 QualType ResultTy =
Context.getPointerType(
Context.CharTy.withConst());
5297 InitializedEntity Entity =
5307 bool IsX64 = TT.getArch() == llvm::Triple::x86_64;
5308 bool IsAArch64 = (TT.getArch() == llvm::Triple::aarch64 ||
5309 TT.getArch() == llvm::Triple::aarch64_32);
5310 bool IsWindowsOrUEFI = TT.isOSWindows() || TT.isUEFI();
5311 bool IsMSVAStart = BuiltinID == Builtin::BI__builtin_ms_va_start;
5312 if (IsX64 || IsAArch64) {
5319 return S.
Diag(Fn->getBeginLoc(),
5320 diag::err_ms_va_start_used_in_sysv_function);
5327 (!IsWindowsOrUEFI && CC ==
CC_Win64))
5328 return S.
Diag(Fn->getBeginLoc(),
5329 diag::err_va_start_used_in_wrong_abi_function)
5330 << !IsWindowsOrUEFI;
5336 return S.
Diag(Fn->getBeginLoc(), diag::err_builtin_x64_aarch64_only);
5344 bool IsVariadic =
false;
5347 if (
auto *
Block = dyn_cast<BlockDecl>(Caller)) {
5348 IsVariadic =
Block->isVariadic();
5349 Params =
Block->parameters();
5350 }
else if (
auto *FD = dyn_cast<FunctionDecl>(Caller)) {
5353 }
else if (
auto *MD = dyn_cast<ObjCMethodDecl>(Caller)) {
5354 IsVariadic = MD->isVariadic();
5356 Params = MD->parameters();
5359 S.
Diag(Fn->getBeginLoc(), diag::err_va_start_captured_stmt);
5363 S.
Diag(Fn->getBeginLoc(), diag::err_va_start_outside_function);
5368 S.
Diag(Fn->getBeginLoc(), diag::err_va_start_fixed_function);
5373 *LastParam = Params.empty() ?
nullptr : Params.back();
5378bool Sema::BuiltinVAStart(
unsigned BuiltinID,
CallExpr *TheCall) {
5383 if (BuiltinID == Builtin::BI__builtin_c23_va_start) {
5407 ParmVarDecl *LastParam;
5418 if (BuiltinID == Builtin::BI__builtin_c23_va_start &&
5420 Diag(TheCall->
getExprLoc(), diag::warn_c17_compat_va_start_one_arg);
5425 if (std::optional<llvm::APSInt> Val =
5427 Val &&
LangOpts.C23 && *Val == 0 &&
5428 BuiltinID != Builtin::BI__builtin_c23_va_start) {
5429 Diag(TheCall->
getExprLoc(), diag::warn_c17_compat_va_start_one_arg);
5436 SourceLocation ParamLoc;
5437 bool IsCRegister =
false;
5438 bool SecondArgIsLastNonVariadicArgument =
false;
5439 if (
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
5440 if (
const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
5441 SecondArgIsLastNonVariadicArgument = PV == LastParam;
5444 ParamLoc = PV->getLocation();
5450 if (!SecondArgIsLastNonVariadicArgument)
5452 diag::warn_second_arg_of_va_start_not_last_non_variadic_param);
5453 else if (IsCRegister ||
Type->isReferenceType() ||
5454 Type->isSpecificBuiltinType(BuiltinType::Float) || [=] {
5457 if (!Context.isPromotableIntegerType(Type))
5459 const auto *ED = Type->getAsEnumDecl();
5462 return !Context.typesAreCompatible(ED->getPromotionType(), Type);
5464 unsigned Reason = 0;
5465 if (
Type->isReferenceType()) Reason = 1;
5466 else if (IsCRegister) Reason = 2;
5467 Diag(Arg->
getBeginLoc(), diag::warn_va_start_type_is_undefined) << Reason;
5468 Diag(ParamLoc, diag::note_parameter_type) <<
Type;
5475 auto IsSuitablyTypedFormatArgument = [
this](
const Expr *Arg) ->
bool {
5495 if (
Call->getNumArgs() < 3)
5497 diag::err_typecheck_call_too_few_args_at_least)
5498 << 0 << 3 <<
Call->getNumArgs()
5511 const Expr *Arg1 =
Call->getArg(1)->IgnoreParens();
5514 const Expr *Arg2 =
Call->getArg(2)->IgnoreParens();
5517 const QualType &ConstCharPtrTy =
5519 if (!Arg1Ty->
isPointerType() || !IsSuitablyTypedFormatArgument(Arg1))
5521 << Arg1->
getType() << ConstCharPtrTy << 1
5524 << 2 << Arg1->
getType() << ConstCharPtrTy;
5526 const QualType SizeTy =
Context.getSizeType();
5531 << Arg2->
getType() << SizeTy << 1
5534 << 3 << Arg2->
getType() << SizeTy;
5539bool Sema::BuiltinUnorderedCompare(
CallExpr *TheCall,
unsigned BuiltinID) {
5543 if (BuiltinID == Builtin::BI__builtin_isunordered &&
5571 diag::err_typecheck_call_invalid_ordered_compare)
5579bool Sema::BuiltinFPClassification(
CallExpr *TheCall,
unsigned NumArgs,
5580 unsigned BuiltinID) {
5585 if (FPO.getNoHonorInfs() && (BuiltinID == Builtin::BI__builtin_isfinite ||
5586 BuiltinID == Builtin::BI__builtin_isinf ||
5587 BuiltinID == Builtin::BI__builtin_isinf_sign))
5591 if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
5592 BuiltinID == Builtin::BI__builtin_isunordered))
5596 bool IsFPClass = NumArgs == 2;
5599 unsigned FPArgNo = IsFPClass ? 0 : NumArgs - 1;
5603 for (
unsigned i = 0; i < FPArgNo; ++i) {
5604 Expr *Arg = TheCall->
getArg(i);
5617 Expr *OrigArg = TheCall->
getArg(FPArgNo);
5625 if (
Context.getTargetInfo().useFP16ConversionIntrinsics()) {
5630 OrigArg = Res.
get();
5636 OrigArg = Res.
get();
5638 TheCall->
setArg(FPArgNo, OrigArg);
5640 QualType VectorResultTy;
5641 QualType ElementTy = OrigArg->
getType();
5646 ElementTy = ElementTy->
castAs<VectorType>()->getElementType();
5652 diag::err_typecheck_call_invalid_unary_fp)
5664 if (!VectorResultTy.
isNull())
5665 ResultTy = VectorResultTy;
5674bool Sema::BuiltinComplex(
CallExpr *TheCall) {
5679 for (
unsigned I = 0; I != 2; ++I) {
5680 Expr *Arg = TheCall->
getArg(I);
5690 return Diag(Arg->
getBeginLoc(), diag::err_typecheck_call_requires_real_fp)
5705 Expr *Real = TheCall->
getArg(0);
5706 Expr *Imag = TheCall->
getArg(1);
5709 diag::err_typecheck_call_different_arg_types)
5724 diag::err_typecheck_call_too_few_args_at_least)
5725 << 0 << 2 << NumArgs
5732 unsigned NumElements = 0;
5747 unsigned NumResElements = NumArgs - 2;
5756 diag::err_vec_builtin_incompatible_vector)
5761 }
else if (!
Context.hasSameUnqualifiedType(LHSType, RHSType)) {
5763 diag::err_vec_builtin_incompatible_vector)
5768 }
else if (NumElements != NumResElements) {
5771 ?
Context.getExtVectorType(EltType, NumResElements)
5772 :
Context.getVectorType(EltType, NumResElements,
5777 for (
unsigned I = 2; I != NumArgs; ++I) {
5785 diag::err_shufflevector_nonconstant_argument)
5791 else if (
Result->getActiveBits() > 64 ||
5792 Result->getZExtValue() >= NumElements * 2)
5794 diag::err_shufflevector_argument_too_large)
5819 diag::err_convertvector_non_vector)
5822 return ExprError(
Diag(BuiltinLoc, diag::err_builtin_non_vector_type)
5824 <<
"__builtin_convertvector");
5829 if (SrcElts != DstElts)
5831 diag::err_convertvector_incompatible_vector)
5839bool Sema::BuiltinPrefetch(
CallExpr *TheCall) {
5844 diag::err_typecheck_call_too_many_args_at_most)
5845 << 0 << 3 << NumArgs << 0
5850 for (
unsigned i = 1; i != NumArgs; ++i)
5857bool Sema::BuiltinArithmeticFence(
CallExpr *TheCall) {
5858 if (!Context.getTargetInfo().checkArithmeticFenceSupported())
5859 return Diag(TheCall->
getBeginLoc(), diag::err_builtin_target_unsupported)
5869 return Diag(TheCall->
getEndLoc(), diag::err_typecheck_expect_flt_or_vector)
5879bool Sema::BuiltinAssume(
CallExpr *TheCall) {
5880 Expr *Arg = TheCall->
getArg(0);
5891bool Sema::BuiltinAllocaWithAlign(
CallExpr *TheCall) {
5893 Expr *Arg = TheCall->
getArg(1);
5897 if (
const auto *UE =
5899 if (UE->getKind() == UETT_AlignOf ||
5900 UE->getKind() == UETT_PreferredAlignOf)
5906 if (!
Result.isPowerOf2())
5907 return Diag(TheCall->
getBeginLoc(), diag::err_alignment_not_power_of_two)
5914 if (
Result > std::numeric_limits<int32_t>::max())
5922bool Sema::BuiltinAssumeAligned(
CallExpr *TheCall) {
5927 Expr *FirstArg = TheCall->
getArg(0);
5933 Diag(TheCall->
getBeginLoc(), diag::err_builtin_assume_aligned_invalid_arg)
5937 TheCall->
setArg(0, FirstArgResult.
get());
5941 Expr *SecondArg = TheCall->
getArg(1);
5949 if (!
Result.isPowerOf2())
5950 return Diag(TheCall->
getBeginLoc(), diag::err_alignment_not_power_of_two)
5962 Expr *ThirdArg = TheCall->
getArg(2);
5965 TheCall->
setArg(2, ThirdArg);
5971bool Sema::BuiltinOSLogFormat(
CallExpr *TheCall) {
5972 unsigned BuiltinID =
5974 bool IsSizeCall = BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size;
5977 unsigned NumRequiredArgs = IsSizeCall ? 1 : 2;
5978 if (NumArgs < NumRequiredArgs) {
5979 return Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args)
5980 << 0 << NumRequiredArgs << NumArgs
5983 if (NumArgs >= NumRequiredArgs + 0x100) {
5985 diag::err_typecheck_call_too_many_args_at_most)
5986 << 0 << (NumRequiredArgs + 0xff) << NumArgs
5997 if (Arg.isInvalid())
5999 TheCall->
setArg(i, Arg.get());
6004 unsigned FormatIdx = i;
6014 unsigned FirstDataArg = i;
6015 while (i < NumArgs) {
6033 llvm::SmallBitVector CheckedVarArgs(NumArgs,
false);
6035 bool Success = CheckFormatArguments(
6038 TheCall->
getBeginLoc(), SourceRange(), CheckedVarArgs);
6062 return Diag(TheCall->
getBeginLoc(), diag::err_constant_integer_arg_type)
6071 int High,
bool RangeIsError) {
6085 if (
Result.getSExtValue() < Low ||
Result.getSExtValue() > High) {
6093 PDiag(diag::warn_argument_invalid_range)
6136 return Diag(TheCall->
getBeginLoc(), diag::err_argument_not_power_of_2)
6141 if (
Value.isNegative())
6152 if ((
Value & 0xFF) != 0)
6177 Result.setIsUnsigned(
true);
6182 return Diag(TheCall->
getBeginLoc(), diag::err_argument_not_shifted_byte)
6202 Result.setIsUnsigned(
true);
6210 diag::err_argument_not_shifted_byte_or_xxff)
6214bool Sema::BuiltinLongjmp(
CallExpr *TheCall) {
6215 if (!Context.getTargetInfo().hasSjLjLowering())
6216 return Diag(TheCall->
getBeginLoc(), diag::err_builtin_longjmp_unsupported)
6227 return Diag(TheCall->
getBeginLoc(), diag::err_builtin_longjmp_invalid_val)
6233bool Sema::BuiltinSetjmp(
CallExpr *TheCall) {
6234 if (!Context.getTargetInfo().hasSjLjLowering())
6235 return Diag(TheCall->
getBeginLoc(), diag::err_builtin_setjmp_unsupported)
6240bool Sema::BuiltinCountedByRef(
CallExpr *TheCall) {
6255 diag::err_builtin_counted_by_ref_must_be_flex_array_member)
6260 diag::err_builtin_counted_by_ref_has_side_effects)
6263 if (
const auto *ME = dyn_cast<MemberExpr>(Arg)) {
6264 if (!ME->isFlexibleArrayMemberLike(
6267 diag::err_builtin_counted_by_ref_must_be_flex_array_member)
6271 ME->getMemberDecl()->getType()->getAs<CountAttributedType>();
6274 if (
const FieldDecl *CountFD = FAMDecl->findCountedByField()) {
6281 diag::err_builtin_counted_by_ref_must_be_flex_array_member)
6291bool Sema::CheckInvalidBuiltinCountedByRef(
const Expr *E,
6293 const CallExpr *CE =
6302 diag::err_builtin_counted_by_ref_cannot_leak_reference)
6307 diag::err_builtin_counted_by_ref_cannot_leak_reference)
6312 diag::err_builtin_counted_by_ref_cannot_leak_reference)
6316 Diag(E->
getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
6320 Diag(E->
getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
6330class UncoveredArgHandler {
6331 enum {
Unknown = -1, AllCovered = -2 };
6333 signed FirstUncoveredArg =
Unknown;
6334 SmallVector<const Expr *, 4> DiagnosticExprs;
6337 UncoveredArgHandler() =
default;
6339 bool hasUncoveredArg()
const {
6340 return (FirstUncoveredArg >= 0);
6343 unsigned getUncoveredArg()
const {
6344 assert(hasUncoveredArg() &&
"no uncovered argument");
6345 return FirstUncoveredArg;
6348 void setAllCovered() {
6351 DiagnosticExprs.clear();
6352 FirstUncoveredArg = AllCovered;
6355 void Update(
signed NewFirstUncoveredArg,
const Expr *StrExpr) {
6356 assert(NewFirstUncoveredArg >= 0 &&
"Outside range");
6359 if (FirstUncoveredArg == AllCovered)
6364 if (NewFirstUncoveredArg == FirstUncoveredArg)
6365 DiagnosticExprs.push_back(StrExpr);
6366 else if (NewFirstUncoveredArg > FirstUncoveredArg) {
6367 DiagnosticExprs.clear();
6368 DiagnosticExprs.push_back(StrExpr);
6369 FirstUncoveredArg = NewFirstUncoveredArg;
6373 void Diagnose(Sema &S,
bool IsFunctionCall,
const Expr *ArgExpr);
6376enum StringLiteralCheckType {
6378 SLCT_UncheckedLiteral,
6386 bool AddendIsRight) {
6387 unsigned BitWidth = Offset.getBitWidth();
6388 unsigned AddendBitWidth = Addend.getBitWidth();
6390 if (Addend.isUnsigned()) {
6391 Addend = Addend.zext(++AddendBitWidth);
6392 Addend.setIsSigned(
true);
6395 if (AddendBitWidth > BitWidth) {
6396 Offset = Offset.sext(AddendBitWidth);
6397 BitWidth = AddendBitWidth;
6398 }
else if (BitWidth > AddendBitWidth) {
6399 Addend = Addend.sext(BitWidth);
6403 llvm::APSInt ResOffset = Offset;
6404 if (BinOpKind == BO_Add)
6405 ResOffset = Offset.sadd_ov(Addend, Ov);
6407 assert(AddendIsRight && BinOpKind == BO_Sub &&
6408 "operator must be add or sub with addend on the right");
6409 ResOffset = Offset.ssub_ov(Addend, Ov);
6415 assert(BitWidth <= std::numeric_limits<unsigned>::max() / 2 &&
6416 "index (intermediate) result too big");
6417 Offset = Offset.sext(2 * BitWidth);
6418 sumOffsets(Offset, Addend, BinOpKind, AddendIsRight);
6430class FormatStringLiteral {
6431 const StringLiteral *FExpr;
6435 FormatStringLiteral(
const StringLiteral *fexpr, int64_t Offset = 0)
6436 : FExpr(fexpr), Offset(Offset) {}
6438 const StringLiteral *getFormatString()
const {
return FExpr; }
6440 StringRef getString()
const {
return FExpr->
getString().drop_front(Offset); }
6442 unsigned getByteLength()
const {
6443 return FExpr->
getByteLength() - getCharByteWidth() * Offset;
6446 unsigned getLength()
const {
return FExpr->
getLength() - Offset; }
6453 bool isAscii()
const {
return FExpr->
isOrdinary(); }
6454 bool isWide()
const {
return FExpr->
isWide(); }
6455 bool isUTF8()
const {
return FExpr->
isUTF8(); }
6456 bool isUTF16()
const {
return FExpr->
isUTF16(); }
6457 bool isUTF32()
const {
return FExpr->
isUTF32(); }
6458 bool isPascal()
const {
return FExpr->
isPascal(); }
6460 SourceLocation getLocationOfByte(
6461 unsigned ByteNo,
const SourceManager &
SM,
const LangOptions &Features,
6462 const TargetInfo &
Target,
unsigned *StartToken =
nullptr,
6463 unsigned *StartTokenByteOffset =
nullptr)
const {
6465 StartToken, StartTokenByteOffset);
6468 SourceLocation getBeginLoc() const LLVM_READONLY {
6472 SourceLocation getEndLoc() const LLVM_READONLY {
return FExpr->
getEndLoc(); }
6478 Sema &S,
const FormatStringLiteral *FExpr,
6483 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
6484 bool IgnoreStringsWithoutSpecifiers);
6498 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
6499 llvm::APSInt Offset,
bool IgnoreStringsWithoutSpecifiers =
false) {
6501 return SLCT_NotALiteral;
6503 assert(Offset.isSigned() &&
"invalid offset");
6506 return SLCT_NotALiteral;
6515 return SLCT_UncheckedLiteral;
6518 case Stmt::InitListExprClass:
6522 S, ReferenceFormatString, SLE, Args, APK, format_idx, firstDataArg,
6523 Type, CallType,
false, CheckedVarArgs,
6524 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6526 return SLCT_NotALiteral;
6527 case Stmt::BinaryConditionalOperatorClass:
6528 case Stmt::ConditionalOperatorClass: {
6537 bool CheckLeft =
true, CheckRight =
true;
6540 if (
C->getCond()->EvaluateAsBooleanCondition(
6552 StringLiteralCheckType Left;
6554 Left = SLCT_UncheckedLiteral;
6557 S, ReferenceFormatString,
C->getTrueExpr(), Args, APK, format_idx,
6558 firstDataArg,
Type, CallType, InFunctionCall, CheckedVarArgs,
6559 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6560 if (Left == SLCT_NotALiteral || !CheckRight) {
6566 S, ReferenceFormatString,
C->getFalseExpr(), Args, APK, format_idx,
6567 firstDataArg,
Type, CallType, InFunctionCall, CheckedVarArgs,
6568 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6570 return (CheckLeft && Left < Right) ? Left : Right;
6573 case Stmt::ImplicitCastExprClass:
6577 case Stmt::OpaqueValueExprClass:
6582 return SLCT_NotALiteral;
6584 case Stmt::PredefinedExprClass:
6588 return SLCT_UncheckedLiteral;
6590 case Stmt::DeclRefExprClass: {
6596 bool isConstant =
false;
6600 isConstant = AT->getElementType().isConstant(S.
Context);
6602 isConstant =
T.isConstant(S.
Context) &&
6603 PT->getPointeeType().isConstant(S.
Context);
6604 }
else if (
T->isObjCObjectPointerType()) {
6607 isConstant =
T.isConstant(S.
Context);
6611 if (
const Expr *
Init = VD->getAnyInitializer()) {
6614 if (InitList->isStringLiteralInit())
6615 Init = InitList->getInit(0)->IgnoreParenImpCasts();
6618 S, ReferenceFormatString,
Init, Args, APK, format_idx,
6619 firstDataArg,
Type, CallType,
6620 false, CheckedVarArgs, UncoveredArg, Offset);
6671 if (
const auto *PV = dyn_cast<ParmVarDecl>(VD)) {
6672 if (
const auto *D = dyn_cast<Decl>(PV->getDeclContext())) {
6673 for (
const auto *PVFormatMatches :
6674 D->specific_attrs<FormatMatchesAttr>()) {
6679 if (PV->getFunctionScopeIndex() == CalleeFSI.
FormatIdx) {
6683 S.
Diag(Args[format_idx]->getBeginLoc(),
6684 diag::warn_format_string_type_incompatible)
6685 << PVFormatMatches->getType()->getName()
6687 if (!InFunctionCall) {
6688 S.
Diag(PVFormatMatches->getFormatString()->getBeginLoc(),
6689 diag::note_format_string_defined);
6691 return SLCT_UncheckedLiteral;
6694 S, ReferenceFormatString, PVFormatMatches->getFormatString(),
6695 Args, APK, format_idx, firstDataArg,
Type, CallType,
6696 false, CheckedVarArgs, UncoveredArg,
6697 Offset, IgnoreStringsWithoutSpecifiers);
6701 for (
const auto *PVFormat : D->specific_attrs<FormatAttr>()) {
6704 PVFormat->getFirstArg(), &CallerFSI))
6706 if (PV->getFunctionScopeIndex() == CallerFSI.
FormatIdx) {
6710 S.
Diag(Args[format_idx]->getBeginLoc(),
6711 diag::warn_format_string_type_incompatible)
6712 << PVFormat->getType()->getName()
6714 if (!InFunctionCall) {
6717 return SLCT_UncheckedLiteral;
6730 return SLCT_UncheckedLiteral;
6738 return SLCT_NotALiteral;
6741 case Stmt::CallExprClass:
6742 case Stmt::CXXMemberCallExprClass: {
6746 StringLiteralCheckType CommonResult;
6747 for (
const auto *FA : ND->specific_attrs<FormatArgAttr>()) {
6748 const Expr *Arg = CE->
getArg(FA->getFormatIdx().getASTIndex());
6750 S, ReferenceFormatString, Arg, Args, APK, format_idx, firstDataArg,
6751 Type, CallType, InFunctionCall, CheckedVarArgs, UncoveredArg,
6752 Offset, IgnoreStringsWithoutSpecifiers);
6754 CommonResult = Result;
6759 return CommonResult;
6761 if (
const auto *FD = dyn_cast<FunctionDecl>(ND)) {
6763 if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
6764 BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) {
6767 S, ReferenceFormatString, Arg, Args, APK, format_idx,
6768 firstDataArg,
Type, CallType, InFunctionCall, CheckedVarArgs,
6769 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6775 S, ReferenceFormatString, SLE, Args, APK, format_idx, firstDataArg,
6776 Type, CallType,
false, CheckedVarArgs,
6777 UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
6778 return SLCT_NotALiteral;
6780 case Stmt::ObjCMessageExprClass: {
6782 if (
const auto *MD = ME->getMethodDecl()) {
6783 if (
const auto *FA = MD->getAttr<FormatArgAttr>()) {
6792 if (MD->isInstanceMethod() && (IFace = MD->getClassInterface()) &&
6794 MD->getSelector().isKeywordSelector(
6795 {
"localizedStringForKey",
"value",
"table"})) {
6796 IgnoreStringsWithoutSpecifiers =
true;
6799 const Expr *Arg = ME->getArg(FA->getFormatIdx().getASTIndex());
6801 S, ReferenceFormatString, Arg, Args, APK, format_idx, firstDataArg,
6802 Type, CallType, InFunctionCall, CheckedVarArgs, UncoveredArg,
6803 Offset, IgnoreStringsWithoutSpecifiers);
6807 return SLCT_NotALiteral;
6809 case Stmt::ObjCStringLiteralClass:
6810 case Stmt::StringLiteralClass: {
6819 if (Offset.isNegative() || Offset > StrE->
getLength()) {
6822 return SLCT_NotALiteral;
6824 FormatStringLiteral FStr(StrE, Offset.sextOrTrunc(64).getSExtValue());
6826 format_idx, firstDataArg,
Type, InFunctionCall,
6827 CallType, CheckedVarArgs, UncoveredArg,
6828 IgnoreStringsWithoutSpecifiers);
6829 return SLCT_CheckedLiteral;
6832 return SLCT_NotALiteral;
6834 case Stmt::BinaryOperatorClass: {
6848 if (LIsInt != RIsInt) {
6852 if (BinOpKind == BO_Add) {
6865 return SLCT_NotALiteral;
6867 case Stmt::UnaryOperatorClass: {
6869 auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->
getSubExpr());
6870 if (UnaOp->
getOpcode() == UO_AddrOf && ASE) {
6872 if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.
Context,
6882 return SLCT_NotALiteral;
6886 return SLCT_NotALiteral;
6897 const auto *LVE = Result.Val.getLValueBase().dyn_cast<
const Expr *>();
6898 if (isa_and_nonnull<StringLiteral>(LVE))
6919 return "freebsd_kprintf";
6928 return llvm::StringSwitch<FormatStringType>(Flavor)
6930 .Cases(
"gnu_printf",
"printf",
"printf0",
"syslog",
6935 .Cases(
"kprintf",
"cmn_err",
"vcmn_err",
"zcmn_err",
6951bool Sema::CheckFormatArguments(
const FormatAttr *Format,
6955 llvm::SmallBitVector &CheckedVarArgs) {
6956 FormatStringInfo FSI;
6960 return CheckFormatArguments(
6961 Args, FSI.ArgPassingKind,
nullptr, FSI.FormatIdx, FSI.FirstDataArg,
6966bool Sema::CheckFormatString(
const FormatMatchesAttr *Format,
6970 llvm::SmallBitVector &CheckedVarArgs) {
6971 FormatStringInfo FSI;
6975 return CheckFormatArguments(Args, FSI.ArgPassingKind,
6976 Format->getFormatString(), FSI.FormatIdx,
6978 CallType, Loc, Range, CheckedVarArgs);
6986 unsigned format_idx,
unsigned firstDataArg,
6990 llvm::SmallBitVector &CheckedVarArgs) {
6992 if (format_idx >= Args.size()) {
6993 Diag(Loc, diag::warn_missing_format_string) <<
Range;
6997 const Expr *OrigFormatExpr = Args[format_idx]->IgnoreParenCasts();
7011 UncoveredArgHandler UncoveredArg;
7013 *
this, ReferenceFormatString, OrigFormatExpr, Args, APK, format_idx,
7014 firstDataArg,
Type, CallType,
7015 true, CheckedVarArgs, UncoveredArg,
7016 llvm::APSInt(64,
false) = 0);
7019 if (UncoveredArg.hasUncoveredArg()) {
7020 unsigned ArgIdx = UncoveredArg.getUncoveredArg() + firstDataArg;
7021 assert(ArgIdx < Args.size() &&
"ArgIdx outside bounds");
7022 UncoveredArg.Diagnose(*
this,
true, Args[ArgIdx]);
7025 if (CT != SLCT_NotALiteral)
7027 return CT == SLCT_CheckedLiteral;
7038 SourceLocation FormatLoc = Args[format_idx]->getBeginLoc();
7045 if (Args.size() == firstDataArg) {
7046 Diag(FormatLoc, diag::warn_format_nonliteral_noargs)
7054 Diag(FormatLoc, diag::note_format_security_fixit)
7058 Diag(FormatLoc, diag::note_format_security_fixit)
7063 Diag(FormatLoc, diag::warn_format_nonliteral)
7074 const FormatStringLiteral *FExpr;
7075 const Expr *OrigFormatExpr;
7077 const unsigned FirstDataArg;
7078 const unsigned NumDataArgs;
7081 ArrayRef<const Expr *> Args;
7083 llvm::SmallBitVector CoveredArgs;
7084 bool usesPositionalArgs =
false;
7085 bool atFirstArg =
true;
7086 bool inFunctionCall;
7088 llvm::SmallBitVector &CheckedVarArgs;
7089 UncoveredArgHandler &UncoveredArg;
7092 CheckFormatHandler(Sema &
s,
const FormatStringLiteral *fexpr,
7094 unsigned firstDataArg,
unsigned numDataArgs,
7096 ArrayRef<const Expr *> Args,
unsigned formatIdx,
7098 llvm::SmallBitVector &CheckedVarArgs,
7099 UncoveredArgHandler &UncoveredArg)
7100 : S(
s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FSType(
type),
7101 FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg),
7102 ArgPassingKind(APK), Args(Args), FormatIdx(formatIdx),
7103 inFunctionCall(inFunctionCall), CallType(callType),
7104 CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) {
7105 CoveredArgs.resize(numDataArgs);
7106 CoveredArgs.reset();
7109 bool HasFormatArguments()
const {
7114 void DoneProcessing();
7116 void HandleIncompleteSpecifier(
const char *startSpecifier,
7117 unsigned specifierLen)
override;
7119 void HandleInvalidLengthModifier(
7120 const analyze_format_string::FormatSpecifier &FS,
7121 const analyze_format_string::ConversionSpecifier &CS,
7122 const char *startSpecifier,
unsigned specifierLen,
7125 void HandleNonStandardLengthModifier(
7126 const analyze_format_string::FormatSpecifier &FS,
7127 const char *startSpecifier,
unsigned specifierLen);
7129 void HandleNonStandardConversionSpecifier(
7130 const analyze_format_string::ConversionSpecifier &CS,
7131 const char *startSpecifier,
unsigned specifierLen);
7133 void HandlePosition(
const char *startPos,
unsigned posLen)
override;
7135 void HandleInvalidPosition(
const char *startSpecifier,
7136 unsigned specifierLen,
7139 void HandleZeroPosition(
const char *startPos,
unsigned posLen)
override;
7141 void HandleNullChar(
const char *nullCharacter)
override;
7143 template <
typename Range>
7145 EmitFormatDiagnostic(Sema &S,
bool inFunctionCall,
const Expr *ArgumentExpr,
7146 const PartialDiagnostic &PDiag, SourceLocation StringLoc,
7147 bool IsStringLocation, Range StringRange,
7148 ArrayRef<FixItHint> Fixit = {});
7151 bool HandleInvalidConversionSpecifier(
unsigned argIndex, SourceLocation Loc,
7152 const char *startSpec,
7153 unsigned specifierLen,
7154 const char *csStart,
unsigned csLen);
7156 void HandlePositionalNonpositionalArgs(SourceLocation Loc,
7157 const char *startSpec,
7158 unsigned specifierLen);
7160 SourceRange getFormatStringRange();
7161 CharSourceRange getSpecifierRange(
const char *startSpecifier,
7162 unsigned specifierLen);
7163 SourceLocation getLocationOfByte(
const char *x);
7165 const Expr *getDataArg(
unsigned i)
const;
7167 bool CheckNumArgs(
const analyze_format_string::FormatSpecifier &FS,
7168 const analyze_format_string::ConversionSpecifier &CS,
7169 const char *startSpecifier,
unsigned specifierLen,
7172 template <
typename Range>
7173 void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
7174 bool IsStringLocation, Range StringRange,
7175 ArrayRef<FixItHint> Fixit = {});
7180SourceRange CheckFormatHandler::getFormatStringRange() {
7185getSpecifierRange(
const char *startSpecifier,
unsigned specifierLen) {
7187 SourceLocation End = getLocationOfByte(startSpecifier + specifierLen - 1);
7195SourceLocation CheckFormatHandler::getLocationOfByte(
const char *x) {
7200void CheckFormatHandler::HandleIncompleteSpecifier(
const char *startSpecifier,
7201 unsigned specifierLen){
7202 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_incomplete_specifier),
7203 getLocationOfByte(startSpecifier),
7205 getSpecifierRange(startSpecifier, specifierLen));
7208void CheckFormatHandler::HandleInvalidLengthModifier(
7211 const char *startSpecifier,
unsigned specifierLen,
unsigned DiagID) {
7223 getSpecifierRange(startSpecifier, specifierLen));
7225 S.
Diag(getLocationOfByte(LM.
getStart()), diag::note_format_fix_specifier)
7226 << FixedLM->toString()
7231 if (DiagID == diag::warn_format_nonsensical_length)
7237 getSpecifierRange(startSpecifier, specifierLen),
7242void CheckFormatHandler::HandleNonStandardLengthModifier(
7244 const char *startSpecifier,
unsigned specifierLen) {
7253 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard)
7257 getSpecifierRange(startSpecifier, specifierLen));
7259 S.
Diag(getLocationOfByte(LM.
getStart()), diag::note_format_fix_specifier)
7260 << FixedLM->toString()
7264 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard)
7268 getSpecifierRange(startSpecifier, specifierLen));
7272void CheckFormatHandler::HandleNonStandardConversionSpecifier(
7274 const char *startSpecifier,
unsigned specifierLen) {
7280 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard)
7284 getSpecifierRange(startSpecifier, specifierLen));
7287 S.
Diag(getLocationOfByte(CS.
getStart()), diag::note_format_fix_specifier)
7288 << FixedCS->toString()
7291 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard)
7295 getSpecifierRange(startSpecifier, specifierLen));
7299void CheckFormatHandler::HandlePosition(
const char *startPos,
7302 diag::warn_format_non_standard_positional_arg,
SourceLocation()))
7303 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_non_standard_positional_arg),
7304 getLocationOfByte(startPos),
7306 getSpecifierRange(startPos, posLen));
7309void CheckFormatHandler::HandleInvalidPosition(
7310 const char *startSpecifier,
unsigned specifierLen,
7313 diag::warn_format_invalid_positional_specifier,
SourceLocation()))
7314 EmitFormatDiagnostic(
7315 S.
PDiag(diag::warn_format_invalid_positional_specifier) << (
unsigned)p,
7316 getLocationOfByte(startSpecifier),
true,
7317 getSpecifierRange(startSpecifier, specifierLen));
7320void CheckFormatHandler::HandleZeroPosition(
const char *startPos,
7324 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_zero_positional_specifier),
7325 getLocationOfByte(startPos),
7327 getSpecifierRange(startPos, posLen));
7330void CheckFormatHandler::HandleNullChar(
const char *nullCharacter) {
7333 EmitFormatDiagnostic(
7334 S.
PDiag(diag::warn_printf_format_string_contains_null_char),
7335 getLocationOfByte(nullCharacter),
true,
7336 getFormatStringRange());
7342const Expr *CheckFormatHandler::getDataArg(
unsigned i)
const {
7343 return Args[FirstDataArg + i];
7346void CheckFormatHandler::DoneProcessing() {
7349 if (HasFormatArguments()) {
7352 signed notCoveredArg = CoveredArgs.find_first();
7353 if (notCoveredArg >= 0) {
7354 assert((
unsigned)notCoveredArg < NumDataArgs);
7355 UncoveredArg.Update(notCoveredArg, OrigFormatExpr);
7357 UncoveredArg.setAllCovered();
7362void UncoveredArgHandler::Diagnose(
Sema &S,
bool IsFunctionCall,
7363 const Expr *ArgExpr) {
7364 assert(hasUncoveredArg() && !DiagnosticExprs.empty() &&
7376 for (
auto E : DiagnosticExprs)
7379 CheckFormatHandler::EmitFormatDiagnostic(
7380 S, IsFunctionCall, DiagnosticExprs[0],
7386CheckFormatHandler::HandleInvalidConversionSpecifier(
unsigned argIndex,
7388 const char *startSpec,
7389 unsigned specifierLen,
7390 const char *csStart,
7392 bool keepGoing =
true;
7393 if (argIndex < NumDataArgs) {
7396 CoveredArgs.set(argIndex);
7412 std::string CodePointStr;
7413 if (!llvm::sys::locale::isPrint(*csStart)) {
7414 llvm::UTF32 CodePoint;
7415 const llvm::UTF8 **B =
reinterpret_cast<const llvm::UTF8 **
>(&csStart);
7416 const llvm::UTF8 *E =
7417 reinterpret_cast<const llvm::UTF8 *
>(csStart + csLen);
7418 llvm::ConversionResult
Result =
7419 llvm::convertUTF8Sequence(B, E, &CodePoint, llvm::strictConversion);
7421 if (
Result != llvm::conversionOK) {
7422 unsigned char FirstChar = *csStart;
7423 CodePoint = (llvm::UTF32)FirstChar;
7426 llvm::raw_string_ostream
OS(CodePointStr);
7427 if (CodePoint < 256)
7428 OS <<
"\\x" << llvm::format(
"%02x", CodePoint);
7429 else if (CodePoint <= 0xFFFF)
7430 OS <<
"\\u" << llvm::format(
"%04x", CodePoint);
7432 OS <<
"\\U" << llvm::format(
"%08x", CodePoint);
7436 EmitFormatDiagnostic(
7437 S.
PDiag(diag::warn_format_invalid_conversion) << Specifier, Loc,
7438 true, getSpecifierRange(startSpec, specifierLen));
7444CheckFormatHandler::HandlePositionalNonpositionalArgs(
SourceLocation Loc,
7445 const char *startSpec,
7446 unsigned specifierLen) {
7447 EmitFormatDiagnostic(
7448 S.
PDiag(diag::warn_format_mix_positional_nonpositional_args),
7449 Loc,
true, getSpecifierRange(startSpec, specifierLen));
7453CheckFormatHandler::CheckNumArgs(
7456 const char *startSpecifier,
unsigned specifierLen,
unsigned argIndex) {
7458 if (HasFormatArguments() && argIndex >= NumDataArgs) {
7460 ? (S.
PDiag(diag::warn_printf_positional_arg_exceeds_data_args)
7461 << (argIndex+1) << NumDataArgs)
7462 : S.
PDiag(diag::warn_printf_insufficient_data_args);
7463 EmitFormatDiagnostic(
7464 PDiag, getLocationOfByte(CS.
getStart()),
true,
7465 getSpecifierRange(startSpecifier, specifierLen));
7469 UncoveredArg.setAllCovered();
7475template<
typename Range>
7478 bool IsStringLocation,
7481 EmitFormatDiagnostic(S, inFunctionCall, Args[FormatIdx], PDiag,
7482 Loc, IsStringLocation, StringRange, FixIt);
7512template <
typename Range>
7513void CheckFormatHandler::EmitFormatDiagnostic(
7514 Sema &S,
bool InFunctionCall,
const Expr *ArgumentExpr,
7517 if (InFunctionCall) {
7522 S.
Diag(IsStringLocation ? ArgumentExpr->
getExprLoc() : Loc, PDiag)
7526 S.
Diag(IsStringLocation ? Loc : StringRange.getBegin(),
7527 diag::note_format_string_defined);
7529 Note << StringRange;
7538class CheckPrintfHandler :
public CheckFormatHandler {
7540 CheckPrintfHandler(Sema &
s,
const FormatStringLiteral *fexpr,
7542 unsigned firstDataArg,
unsigned numDataArgs,
bool isObjC,
7544 ArrayRef<const Expr *> Args,
unsigned formatIdx,
7546 llvm::SmallBitVector &CheckedVarArgs,
7547 UncoveredArgHandler &UncoveredArg)
7548 : CheckFormatHandler(
s, fexpr, origFormatExpr,
type, firstDataArg,
7549 numDataArgs, beg, APK, Args, formatIdx,
7550 inFunctionCall, CallType, CheckedVarArgs,
7553 bool isObjCContext()
const {
return FSType == FormatStringType::NSString; }
7556 bool allowsObjCArg()
const {
7557 return FSType == FormatStringType::NSString ||
7558 FSType == FormatStringType::OSLog ||
7559 FSType == FormatStringType::OSTrace;
7562 bool HandleInvalidPrintfConversionSpecifier(
7563 const analyze_printf::PrintfSpecifier &FS,
7564 const char *startSpecifier,
7565 unsigned specifierLen)
override;
7567 void handleInvalidMaskType(StringRef MaskType)
override;
7569 bool HandlePrintfSpecifier(
const analyze_printf::PrintfSpecifier &FS,
7570 const char *startSpecifier,
unsigned specifierLen,
7571 const TargetInfo &
Target)
override;
7572 bool checkFormatExpr(
const analyze_printf::PrintfSpecifier &FS,
7573 const char *StartSpecifier,
7574 unsigned SpecifierLen,
7577 bool HandleAmount(
const analyze_format_string::OptionalAmount &Amt,
unsigned k,
7578 const char *startSpecifier,
unsigned specifierLen);
7579 void HandleInvalidAmount(
const analyze_printf::PrintfSpecifier &FS,
7580 const analyze_printf::OptionalAmount &Amt,
7582 const char *startSpecifier,
unsigned specifierLen);
7583 void HandleFlag(
const analyze_printf::PrintfSpecifier &FS,
7584 const analyze_printf::OptionalFlag &flag,
7585 const char *startSpecifier,
unsigned specifierLen);
7586 void HandleIgnoredFlag(
const analyze_printf::PrintfSpecifier &FS,
7587 const analyze_printf::OptionalFlag &ignoredFlag,
7588 const analyze_printf::OptionalFlag &flag,
7589 const char *startSpecifier,
unsigned specifierLen);
7590 bool checkForCStrMembers(
const analyze_printf::ArgType &AT,
7593 void HandleEmptyObjCModifierFlag(
const char *startFlag,
7594 unsigned flagLen)
override;
7596 void HandleInvalidObjCModifierFlag(
const char *startFlag,
7597 unsigned flagLen)
override;
7600 HandleObjCFlagsWithNonObjCConversion(
const char *flagsStart,
7601 const char *flagsEnd,
7602 const char *conversionPosition)
override;
7607class EquatableFormatArgument {
7609 enum SpecifierSensitivity :
unsigned {
7616 enum FormatArgumentRole :
unsigned {
7624 analyze_format_string::ArgType ArgType;
7626 StringRef SpecifierLetter;
7627 CharSourceRange
Range;
7628 SourceLocation ElementLoc;
7629 FormatArgumentRole
Role : 2;
7630 SpecifierSensitivity Sensitivity : 2;
7631 unsigned Position : 14;
7632 unsigned ModifierFor : 14;
7634 void EmitDiagnostic(Sema &S, PartialDiagnostic PDiag,
const Expr *FmtExpr,
7635 bool InFunctionCall)
const;
7638 EquatableFormatArgument(CharSourceRange Range, SourceLocation ElementLoc,
7640 StringRef SpecifierLetter,
7641 analyze_format_string::ArgType ArgType,
7642 FormatArgumentRole
Role,
7643 SpecifierSensitivity Sensitivity,
unsigned Position,
7644 unsigned ModifierFor)
7645 : ArgType(ArgType), LengthMod(LengthMod),
7646 SpecifierLetter(SpecifierLetter),
Range(
Range), ElementLoc(ElementLoc),
7647 Role(
Role), Sensitivity(Sensitivity), Position(Position),
7648 ModifierFor(ModifierFor) {}
7650 unsigned getPosition()
const {
return Position; }
7651 SourceLocation getSourceLocation()
const {
return ElementLoc; }
7653 analyze_format_string::LengthModifier getLengthModifier()
const {
7654 return analyze_format_string::LengthModifier(
nullptr, LengthMod);
7656 void setModifierFor(
unsigned V) { ModifierFor =
V; }
7658 std::string buildFormatSpecifier()
const {
7660 llvm::raw_string_ostream(result)
7661 << getLengthModifier().toString() << SpecifierLetter;
7665 bool VerifyCompatible(Sema &S,
const EquatableFormatArgument &
Other,
7666 const Expr *FmtExpr,
bool InFunctionCall)
const;
7670class DecomposePrintfHandler :
public CheckPrintfHandler {
7671 llvm::SmallVectorImpl<EquatableFormatArgument> &Specs;
7674 DecomposePrintfHandler(Sema &
s,
const FormatStringLiteral *fexpr,
7675 const Expr *origFormatExpr,
7677 unsigned numDataArgs,
bool isObjC,
const char *beg,
7679 ArrayRef<const Expr *> Args,
unsigned formatIdx,
7681 llvm::SmallBitVector &CheckedVarArgs,
7682 UncoveredArgHandler &UncoveredArg,
7683 llvm::SmallVectorImpl<EquatableFormatArgument> &Specs)
7684 : CheckPrintfHandler(
s, fexpr, origFormatExpr,
type, firstDataArg,
7685 numDataArgs,
isObjC, beg, APK, Args, formatIdx,
7686 inFunctionCall, CallType, CheckedVarArgs,
7688 Specs(Specs), HadError(
false) {}
7692 GetSpecifiers(Sema &S,
const FormatStringLiteral *FSL,
const Expr *FmtExpr,
7694 llvm::SmallVectorImpl<EquatableFormatArgument> &Args);
7696 virtual bool HandlePrintfSpecifier(
const analyze_printf::PrintfSpecifier &FS,
7697 const char *startSpecifier,
7698 unsigned specifierLen,
7699 const TargetInfo &
Target)
override;
7704bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
7706 unsigned specifierLen) {
7710 return HandleInvalidConversionSpecifier(FS.
getArgIndex(),
7712 startSpecifier, specifierLen,
7716void CheckPrintfHandler::handleInvalidMaskType(StringRef MaskType) {
7717 S.
Diag(getLocationOfByte(MaskType.data()), diag::err_invalid_mask_type_size);
7725 return T->isRecordType() ||
T->isComplexType();
7728bool CheckPrintfHandler::HandleAmount(
7730 const char *startSpecifier,
unsigned specifierLen) {
7732 if (HasFormatArguments()) {
7734 if (argIndex >= NumDataArgs) {
7735 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_asterisk_missing_arg)
7739 getSpecifierRange(startSpecifier, specifierLen));
7749 CoveredArgs.set(argIndex);
7750 const Expr *Arg = getDataArg(argIndex);
7761 ? diag::err_printf_asterisk_wrong_type
7762 : diag::warn_printf_asterisk_wrong_type;
7763 EmitFormatDiagnostic(S.
PDiag(DiagID)
7768 getSpecifierRange(startSpecifier, specifierLen));
7778void CheckPrintfHandler::HandleInvalidAmount(
7782 const char *startSpecifier,
7783 unsigned specifierLen) {
7793 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_nonsensical_optional_amount)
7797 getSpecifierRange(startSpecifier, specifierLen),
7803 const char *startSpecifier,
7804 unsigned specifierLen) {
7808 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_nonsensical_flag)
7812 getSpecifierRange(startSpecifier, specifierLen),
7817void CheckPrintfHandler::HandleIgnoredFlag(
7821 const char *startSpecifier,
7822 unsigned specifierLen) {
7824 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_ignored_flag)
7828 getSpecifierRange(startSpecifier, specifierLen),
7830 getSpecifierRange(ignoredFlag.
getPosition(), 1)));
7833void CheckPrintfHandler::HandleEmptyObjCModifierFlag(
const char *startFlag,
7836 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_empty_objc_flag),
7837 getLocationOfByte(startFlag),
7839 getSpecifierRange(startFlag, flagLen));
7842void CheckPrintfHandler::HandleInvalidObjCModifierFlag(
const char *startFlag,
7845 auto Range = getSpecifierRange(startFlag, flagLen);
7846 StringRef flag(startFlag, flagLen);
7847 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_invalid_objc_flag) << flag,
7848 getLocationOfByte(startFlag),
7853void CheckPrintfHandler::HandleObjCFlagsWithNonObjCConversion(
7854 const char *flagsStart,
const char *flagsEnd,
const char *conversionPosition) {
7856 auto Range = getSpecifierRange(flagsStart, flagsEnd - flagsStart + 1);
7857 auto diag = diag::warn_printf_ObjCflags_without_ObjCConversion;
7858 EmitFormatDiagnostic(S.
PDiag(
diag) << StringRef(conversionPosition, 1),
7859 getLocationOfByte(conversionPosition),
7865 const Expr *FmtExpr,
7866 bool InFunctionCall)
const {
7867 CheckFormatHandler::EmitFormatDiagnostic(S, InFunctionCall, FmtExpr, PDiag,
7868 ElementLoc,
true, Range);
7871bool EquatableFormatArgument::VerifyCompatible(
7872 Sema &S,
const EquatableFormatArgument &
Other,
const Expr *FmtExpr,
7873 bool InFunctionCall)
const {
7878 S, S.
PDiag(diag::warn_format_cmp_role_mismatch) <<
Role <<
Other.Role,
7879 FmtExpr, InFunctionCall);
7880 S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with) << 0 <<
Other.Range;
7884 if (
Role != FAR_Data) {
7885 if (ModifierFor !=
Other.ModifierFor) {
7888 S.
PDiag(diag::warn_format_cmp_modifierfor_mismatch)
7889 << (ModifierFor + 1) << (
Other.ModifierFor + 1),
7890 FmtExpr, InFunctionCall);
7891 S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with) << 0 <<
Other.Range;
7897 bool HadError =
false;
7898 if (Sensitivity !=
Other.Sensitivity) {
7901 S.
PDiag(diag::warn_format_cmp_sensitivity_mismatch)
7902 << Sensitivity <<
Other.Sensitivity,
7903 FmtExpr, InFunctionCall);
7904 HadError = S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with)
7905 << 0 <<
Other.Range;
7908 switch (ArgType.matchesArgType(S.
Context,
Other.ArgType)) {
7912 case MK::MatchPromotion:
7916 case MK::NoMatchTypeConfusion:
7917 case MK::NoMatchPromotionTypeConfusion:
7919 S.
PDiag(diag::warn_format_cmp_specifier_mismatch)
7920 << buildFormatSpecifier()
7921 <<
Other.buildFormatSpecifier(),
7922 FmtExpr, InFunctionCall);
7923 HadError = S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with)
7924 << 0 <<
Other.Range;
7927 case MK::NoMatchPedantic:
7929 S.
PDiag(diag::warn_format_cmp_specifier_mismatch_pedantic)
7930 << buildFormatSpecifier()
7931 <<
Other.buildFormatSpecifier(),
7932 FmtExpr, InFunctionCall);
7933 HadError = S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with)
7934 << 0 <<
Other.Range;
7937 case MK::NoMatchSignedness:
7939 S.
PDiag(diag::warn_format_cmp_specifier_sign_mismatch)
7940 << buildFormatSpecifier()
7941 <<
Other.buildFormatSpecifier(),
7942 FmtExpr, InFunctionCall);
7943 HadError = S.
Diag(
Other.ElementLoc, diag::note_format_cmp_with)
7944 << 0 <<
Other.Range;
7950bool DecomposePrintfHandler::GetSpecifiers(
7951 Sema &S,
const FormatStringLiteral *FSL,
const Expr *FmtExpr,
7954 StringRef
Data = FSL->getString();
7955 const char *Str =
Data.data();
7956 llvm::SmallBitVector BV;
7957 UncoveredArgHandler UA;
7958 const Expr *PrintfArgs[] = {FSL->getFormatString()};
7959 DecomposePrintfHandler H(S, FSL, FSL->getFormatString(),
Type, 0, 0, IsObjC,
7971 llvm::stable_sort(Args, [](
const EquatableFormatArgument &A,
7972 const EquatableFormatArgument &B) {
7973 return A.getPosition() < B.getPosition();
7978bool DecomposePrintfHandler::HandlePrintfSpecifier(
7981 if (!CheckPrintfHandler::HandlePrintfSpecifier(FS, startSpecifier,
7996 const unsigned Unset = ~0;
7997 unsigned FieldWidthIndex = Unset;
7998 unsigned PrecisionIndex = Unset;
8002 if (!FieldWidth.isInvalid() && FieldWidth.hasDataArgument()) {
8003 FieldWidthIndex = Specs.size();
8004 Specs.emplace_back(getSpecifierRange(startSpecifier, specifierLen),
8005 getLocationOfByte(FieldWidth.getStart()),
8007 FieldWidth.getArgType(S.
Context),
8008 EquatableFormatArgument::FAR_FieldWidth,
8009 EquatableFormatArgument::SS_None,
8010 FieldWidth.usesPositionalArg()
8011 ? FieldWidth.getPositionalArgIndex() - 1
8017 if (!Precision.isInvalid() && Precision.hasDataArgument()) {
8018 PrecisionIndex = Specs.size();
8020 getSpecifierRange(startSpecifier, specifierLen),
8021 getLocationOfByte(Precision.getStart()),
8023 Precision.getArgType(S.
Context), EquatableFormatArgument::FAR_Precision,
8024 EquatableFormatArgument::SS_None,
8025 Precision.usesPositionalArg() ? Precision.getPositionalArgIndex() - 1
8031 unsigned SpecIndex =
8033 if (FieldWidthIndex != Unset)
8034 Specs[FieldWidthIndex].setModifierFor(SpecIndex);
8035 if (PrecisionIndex != Unset)
8036 Specs[PrecisionIndex].setModifierFor(SpecIndex);
8038 EquatableFormatArgument::SpecifierSensitivity Sensitivity;
8040 Sensitivity = EquatableFormatArgument::SS_Private;
8042 Sensitivity = EquatableFormatArgument::SS_Public;
8044 Sensitivity = EquatableFormatArgument::SS_Sensitive;
8046 Sensitivity = EquatableFormatArgument::SS_None;
8049 getSpecifierRange(startSpecifier, specifierLen),
8052 EquatableFormatArgument::FAR_Data, Sensitivity, SpecIndex, 0);
8057 Specs.emplace_back(getSpecifierRange(startSpecifier, specifierLen),
8062 EquatableFormatArgument::FAR_Auxiliary, Sensitivity,
8063 SpecIndex + 1, SpecIndex);
8071template<
typename MemberKind>
8089 if (MemberKind *FK = dyn_cast<MemberKind>(
decl))
8104 for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
8106 if ((*MI)->getMinRequiredArguments() == 0)
8114bool CheckPrintfHandler::checkForCStrMembers(
8121 for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
8124 if (
Method->getMinRequiredArguments() == 0 &&
8137bool CheckPrintfHandler::HandlePrintfSpecifier(
8151 HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()),
8152 startSpecifier, specifierLen);
8160 startSpecifier, specifierLen)) {
8165 startSpecifier, specifierLen)) {
8169 if (!CS.consumesDataArgument()) {
8177 if (argIndex < NumDataArgs) {
8181 CoveredArgs.set(argIndex);
8188 if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex + 1))
8191 if (HasFormatArguments()) {
8193 CoveredArgs.set(argIndex + 1);
8196 const Expr *Ex = getDataArg(argIndex);
8200 : ArgType::CPointerTy;
8202 EmitFormatDiagnostic(
8203 S.
PDiag(diag::warn_format_conversion_argument_type_mismatch)
8207 getSpecifierRange(startSpecifier, specifierLen));
8210 Ex = getDataArg(argIndex + 1);
8213 EmitFormatDiagnostic(
8214 S.
PDiag(diag::warn_format_conversion_argument_type_mismatch)
8218 getSpecifierRange(startSpecifier, specifierLen));
8225 if (!allowsObjCArg() && CS.isObjCArg()) {
8226 return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
8233 return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
8240 EmitFormatDiagnostic(S.
PDiag(diag::warn_os_log_format_narg),
8241 getLocationOfByte(CS.getStart()),
8243 getSpecifierRange(startSpecifier, specifierLen));
8253 return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
8260 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_invalid_annotation)
8264 getSpecifierRange(startSpecifier, specifierLen));
8267 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_invalid_annotation)
8271 getSpecifierRange(startSpecifier, specifierLen));
8275 const llvm::Triple &Triple =
Target.getTriple();
8277 (Triple.isAndroid() || Triple.isOSFuchsia())) {
8278 EmitFormatDiagnostic(S.
PDiag(diag::warn_printf_narg_not_supported),
8279 getLocationOfByte(CS.getStart()),
8281 getSpecifierRange(startSpecifier, specifierLen));
8287 startSpecifier, specifierLen);
8293 startSpecifier, specifierLen);
8299 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_P_no_precision),
8300 getLocationOfByte(startSpecifier),
8302 getSpecifierRange(startSpecifier, specifierLen));
8311 HandleFlag(FS, FS.
hasPlusPrefix(), startSpecifier, specifierLen);
8313 HandleFlag(FS, FS.
hasSpacePrefix(), startSpecifier, specifierLen);
8322 startSpecifier, specifierLen);
8325 startSpecifier, specifierLen);
8330 HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
8331 diag::warn_format_nonsensical_length);
8333 HandleNonStandardLengthModifier(FS, startSpecifier, specifierLen);
8335 HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
8336 diag::warn_format_non_standard_conversion_spec);
8339 HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen);
8342 if (!HasFormatArguments())
8345 if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
8348 const Expr *Arg = getDataArg(argIndex);
8352 return checkFormatExpr(FS, startSpecifier, specifierLen, Arg);
8364 case Stmt::ArraySubscriptExprClass:
8365 case Stmt::CallExprClass:
8366 case Stmt::CharacterLiteralClass:
8367 case Stmt::CXXBoolLiteralExprClass:
8368 case Stmt::DeclRefExprClass:
8369 case Stmt::FloatingLiteralClass:
8370 case Stmt::IntegerLiteralClass:
8371 case Stmt::MemberExprClass:
8372 case Stmt::ObjCArrayLiteralClass:
8373 case Stmt::ObjCBoolLiteralExprClass:
8374 case Stmt::ObjCBoxedExprClass:
8375 case Stmt::ObjCDictionaryLiteralClass:
8376 case Stmt::ObjCEncodeExprClass:
8377 case Stmt::ObjCIvarRefExprClass:
8378 case Stmt::ObjCMessageExprClass:
8379 case Stmt::ObjCPropertyRefExprClass:
8380 case Stmt::ObjCStringLiteralClass:
8381 case Stmt::ObjCSubscriptRefExprClass:
8382 case Stmt::ParenExprClass:
8383 case Stmt::StringLiteralClass:
8384 case Stmt::UnaryOperatorClass:
8391static std::pair<QualType, StringRef>
8398 StringRef Name = UserTy->getDecl()->getName();
8399 QualType CastTy = llvm::StringSwitch<QualType>(Name)
8400 .Case(
"CFIndex", Context.getNSIntegerType())
8401 .Case(
"NSInteger", Context.getNSIntegerType())
8402 .Case(
"NSUInteger", Context.getNSUIntegerType())
8403 .Case(
"SInt32", Context.IntTy)
8404 .Case(
"UInt32", Context.UnsignedIntTy)
8408 return std::make_pair(CastTy, Name);
8410 TyTy = UserTy->desugar();
8414 if (
const ParenExpr *PE = dyn_cast<ParenExpr>(E))
8416 PE->getSubExpr()->getType(),
8425 StringRef TrueName, FalseName;
8427 std::tie(TrueTy, TrueName) =
8429 CO->getTrueExpr()->getType(),
8431 std::tie(FalseTy, FalseName) =
8433 CO->getFalseExpr()->getType(),
8434 CO->getFalseExpr());
8436 if (TrueTy == FalseTy)
8437 return std::make_pair(TrueTy, TrueName);
8438 else if (TrueTy.
isNull())
8439 return std::make_pair(FalseTy, FalseName);
8440 else if (FalseTy.
isNull())
8441 return std::make_pair(TrueTy, TrueName);
8444 return std::make_pair(
QualType(), StringRef());
8463 From = VecTy->getElementType();
8465 To = VecTy->getElementType();
8476 diag::warn_format_conversion_argument_type_mismatch_signedness,
8480 diag::warn_format_conversion_argument_type_mismatch, Loc)) {
8489 const char *StartSpecifier,
8490 unsigned SpecifierLen,
8502 while (
const TypeOfExprType *TET = dyn_cast<TypeOfExprType>(ExprTy)) {
8503 ExprTy = TET->getUnderlyingExpr()->getType();
8518 getSpecifierRange(StartSpecifier, SpecifierLen);
8520 llvm::raw_svector_ostream os(FSString);
8522 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_bool_as_character)
8533 getSpecifierRange(StartSpecifier, SpecifierLen);
8534 EmitFormatDiagnostic(S.
PDiag(diag::warn_format_P_with_objc_pointer),
8544 if (
Match == ArgType::Match)
8548 assert(
Match != ArgType::NoMatchPromotionTypeConfusion);
8557 E = ICE->getSubExpr();
8567 if (OrigMatch == ArgType::NoMatchSignedness &&
8568 ImplicitMatch != ArgType::NoMatchSignedness)
8575 if (ImplicitMatch == ArgType::Match)
8593 if (
Match == ArgType::MatchPromotion)
8597 if (
Match == ArgType::MatchPromotion) {
8601 ImplicitMatch != ArgType::NoMatchPromotionTypeConfusion &&
8602 ImplicitMatch != ArgType::NoMatchTypeConfusion)
8606 if (ImplicitMatch == ArgType::NoMatchPedantic ||
8607 ImplicitMatch == ArgType::NoMatchTypeConfusion)
8608 Match = ImplicitMatch;
8609 assert(
Match != ArgType::MatchPromotion);
8612 bool IsEnum =
false;
8613 bool IsScopedEnum =
false;
8616 IntendedTy = ED->getIntegerType();
8617 if (!ED->isScoped()) {
8618 ExprTy = IntendedTy;
8623 IsScopedEnum =
true;
8630 if (isObjCContext() &&
8641 const llvm::APInt &
V = IL->getValue();
8651 if (TD->getUnderlyingType() == IntendedTy)
8661 bool ShouldNotPrintDirectly =
false; StringRef CastTyName;
8669 if (!IsScopedEnum &&
8670 (CastTyName ==
"NSInteger" || CastTyName ==
"NSUInteger") &&
8674 IntendedTy = CastTy;
8675 ShouldNotPrintDirectly =
true;
8680 PrintfSpecifier fixedFS = FS;
8687 llvm::raw_svector_ostream os(buf);
8690 CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);
8692 if (IntendedTy == ExprTy && !ShouldNotPrintDirectly && !IsScopedEnum) {
8698 llvm_unreachable(
"expected non-matching");
8700 Diag = diag::warn_format_conversion_argument_type_mismatch_signedness;
8703 Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
8706 Diag = diag::warn_format_conversion_argument_type_mismatch_confusion;
8709 Diag = diag::warn_format_conversion_argument_type_mismatch;
8730 llvm::raw_svector_ostream CastFix(CastBuf);
8731 CastFix << (S.
LangOpts.CPlusPlus ?
"static_cast<" :
"(");
8733 CastFix << (S.
LangOpts.CPlusPlus ?
">" :
")");
8739 if ((IntendedMatch != ArgType::Match) || ShouldNotPrintDirectly)
8744 SourceRange CastRange(CCast->getLParenLoc(), CCast->getRParenLoc());
8766 if (ShouldNotPrintDirectly && !IsScopedEnum) {
8772 Name = TypedefTy->getDecl()->getName();
8776 ? diag::warn_format_argument_needs_cast_pedantic
8777 : diag::warn_format_argument_needs_cast;
8778 EmitFormatDiagnostic(S.
PDiag(
Diag) << Name << IntendedTy << IsEnum
8789 ? diag::warn_format_conversion_argument_type_mismatch_pedantic
8790 : diag::warn_format_conversion_argument_type_mismatch;
8792 EmitFormatDiagnostic(
8804 bool EmitTypeMismatch =
false;
8813 llvm_unreachable(
"expected non-matching");
8815 Diag = diag::warn_format_conversion_argument_type_mismatch_signedness;
8818 Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
8821 Diag = diag::warn_format_conversion_argument_type_mismatch_confusion;
8825 ? diag::err_format_conversion_argument_type_mismatch
8826 : diag::warn_format_conversion_argument_type_mismatch;
8830 EmitFormatDiagnostic(
8839 EmitTypeMismatch =
true;
8841 EmitFormatDiagnostic(
8842 S.
PDiag(diag::warn_non_pod_vararg_with_format_string)
8843 << S.
getLangOpts().CPlusPlus11 << ExprTy << CallType
8847 checkForCStrMembers(AT, E);
8853 EmitTypeMismatch =
true;
8855 EmitFormatDiagnostic(
8856 S.
PDiag(diag::err_cannot_pass_objc_interface_to_vararg_format)
8857 << S.
getLangOpts().CPlusPlus11 << ExprTy << CallType
8870 if (EmitTypeMismatch) {
8876 EmitFormatDiagnostic(
8877 S.
PDiag(diag::warn_format_conversion_argument_type_mismatch)
8883 assert(FirstDataArg + FS.
getArgIndex() < CheckedVarArgs.size() &&
8884 "format string specifier index out of range");
8885 CheckedVarArgs[FirstDataArg + FS.
getArgIndex()] =
true;
8895class CheckScanfHandler :
public CheckFormatHandler {
8897 CheckScanfHandler(Sema &
s,
const FormatStringLiteral *fexpr,
8899 unsigned firstDataArg,
unsigned numDataArgs,
8901 ArrayRef<const Expr *> Args,
unsigned formatIdx,
8903 llvm::SmallBitVector &CheckedVarArgs,
8904 UncoveredArgHandler &UncoveredArg)
8905 : CheckFormatHandler(
s, fexpr, origFormatExpr,
type, firstDataArg,
8906 numDataArgs, beg, APK, Args, formatIdx,
8907 inFunctionCall, CallType, CheckedVarArgs,
8910 bool HandleScanfSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
8911 const char *startSpecifier,
8912 unsigned specifierLen)
override;
8914 bool HandleInvalidScanfConversionSpecifier(
8915 const analyze_scanf::ScanfSpecifier &FS,
8916 const char *startSpecifier,
8917 unsigned specifierLen)
override;
8919 void HandleIncompleteScanList(
const char *start,
const char *end)
override;
8924void CheckScanfHandler::HandleIncompleteScanList(
const char *start,
8926 EmitFormatDiagnostic(S.
PDiag(diag::warn_scanf_scanlist_incomplete),
8927 getLocationOfByte(end),
true,
8928 getSpecifierRange(start, end - start));
8931bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier(
8933 const char *startSpecifier,
8934 unsigned specifierLen) {
8938 return HandleInvalidConversionSpecifier(FS.
getArgIndex(),
8940 startSpecifier, specifierLen,
8944bool CheckScanfHandler::HandleScanfSpecifier(
8946 const char *startSpecifier,
8947 unsigned specifierLen) {
8961 HandlePositionalNonpositionalArgs(getLocationOfByte(CS.
getStart()),
8962 startSpecifier, specifierLen);
8973 EmitFormatDiagnostic(S.
PDiag(diag::warn_scanf_nonzero_width),
8988 if (argIndex < NumDataArgs) {
8992 CoveredArgs.set(argIndex);
8998 HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
8999 diag::warn_format_nonsensical_length);
9001 HandleNonStandardLengthModifier(FS, startSpecifier, specifierLen);
9003 HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
9004 diag::warn_format_non_standard_conversion_spec);
9007 HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen);
9010 if (!HasFormatArguments())
9013 if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
9017 const Expr *Ex = getDataArg(argIndex);
9035 ScanfSpecifier fixedFS = FS;
9040 Pedantic ? diag::warn_format_conversion_argument_type_mismatch_pedantic
9042 ? diag::warn_format_conversion_argument_type_mismatch_signedness
9043 : diag::warn_format_conversion_argument_type_mismatch;
9048 llvm::raw_svector_ostream os(buf);
9051 EmitFormatDiagnostic(
9056 getSpecifierRange(startSpecifier, specifierLen),
9058 getSpecifierRange(startSpecifier, specifierLen), os.str()));
9065 getSpecifierRange(startSpecifier, specifierLen));
9075 const Expr *FmtExpr,
bool InFunctionCall) {
9076 bool HadError =
false;
9077 auto FmtIter = FmtArgs.begin(), FmtEnd = FmtArgs.end();
9078 auto RefIter = RefArgs.begin(), RefEnd = RefArgs.end();
9079 while (FmtIter < FmtEnd && RefIter < RefEnd) {
9091 for (; FmtIter < FmtEnd; ++FmtIter) {
9095 if (FmtIter->getPosition() < RefIter->getPosition())
9099 if (FmtIter->getPosition() > RefIter->getPosition())
9103 !FmtIter->VerifyCompatible(S, *RefIter, FmtExpr, InFunctionCall);
9107 RefIter = std::find_if(RefIter + 1, RefEnd, [=](
const auto &Arg) {
9108 return Arg.getPosition() != RefIter->getPosition();
9112 if (FmtIter < FmtEnd) {
9113 CheckFormatHandler::EmitFormatDiagnostic(
9114 S, InFunctionCall, FmtExpr,
9115 S.
PDiag(diag::warn_format_cmp_specifier_arity) << 1,
9116 FmtExpr->
getBeginLoc(),
false, FmtIter->getSourceRange());
9117 HadError = S.
Diag(Ref->
getBeginLoc(), diag::note_format_cmp_with) << 1;
9118 }
else if (RefIter < RefEnd) {
9119 CheckFormatHandler::EmitFormatDiagnostic(
9120 S, InFunctionCall, FmtExpr,
9121 S.
PDiag(diag::warn_format_cmp_specifier_arity) << 0,
9124 << 1 << RefIter->getSourceRange();
9130 Sema &S,
const FormatStringLiteral *FExpr,
9135 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
9136 bool IgnoreStringsWithoutSpecifiers) {
9138 if (!FExpr->isAscii() && !FExpr->isUTF8()) {
9139 CheckFormatHandler::EmitFormatDiagnostic(
9140 S, inFunctionCall, Args[format_idx],
9141 S.
PDiag(diag::warn_format_string_is_wide_literal), FExpr->getBeginLoc(),
9147 StringRef StrRef = FExpr->getString();
9148 const char *Str = StrRef.data();
9152 assert(
T &&
"String literal not of constant array type!");
9153 size_t TypeSize =
T->getZExtSize();
9154 size_t StrLen = std::min(std::max(TypeSize,
size_t(1)) - 1, StrRef.size());
9155 const unsigned numDataArgs = Args.size() - firstDataArg;
9157 if (IgnoreStringsWithoutSpecifiers &&
9164 if (TypeSize <= StrRef.size() && !StrRef.substr(0, TypeSize).contains(
'\0')) {
9165 CheckFormatHandler::EmitFormatDiagnostic(
9166 S, inFunctionCall, Args[format_idx],
9167 S.
PDiag(diag::warn_printf_format_string_not_null_terminated),
9168 FExpr->getBeginLoc(),
9174 if (StrLen == 0 && numDataArgs > 0) {
9175 CheckFormatHandler::EmitFormatDiagnostic(
9176 S, inFunctionCall, Args[format_idx],
9177 S.
PDiag(diag::warn_empty_format_string), FExpr->getBeginLoc(),
9188 if (ReferenceFormatString ==
nullptr) {
9189 CheckPrintfHandler H(S, FExpr, OrigFormatExpr,
Type, firstDataArg,
9190 numDataArgs, IsObjC, Str, APK, Args, format_idx,
9191 inFunctionCall, CallType, CheckedVarArgs,
9201 Type, ReferenceFormatString, FExpr->getFormatString(),
9202 inFunctionCall ?
nullptr : Args[format_idx]);
9205 CheckScanfHandler H(S, FExpr, OrigFormatExpr,
Type, firstDataArg,
9206 numDataArgs, Str, APK, Args, format_idx, inFunctionCall,
9207 CallType, CheckedVarArgs, UncoveredArg);
9227 FormatStringLiteral RefLit = AuthoritativeFormatString;
9228 FormatStringLiteral TestLit = TestedFormatString;
9230 bool DiagAtStringLiteral;
9231 if (FunctionCallArg) {
9232 Arg = FunctionCallArg;
9233 DiagAtStringLiteral =
false;
9235 Arg = TestedFormatString;
9236 DiagAtStringLiteral =
true;
9238 if (DecomposePrintfHandler::GetSpecifiers(*
this, &RefLit,
9239 AuthoritativeFormatString,
Type,
9240 IsObjC,
true, RefArgs) &&
9241 DecomposePrintfHandler::GetSpecifiers(*
this, &TestLit, Arg,
Type, IsObjC,
9242 DiagAtStringLiteral, FmtArgs)) {
9244 TestedFormatString, FmtArgs, Arg,
9245 DiagAtStringLiteral);
9258 FormatStringLiteral RefLit = Str;
9262 if (!DecomposePrintfHandler::GetSpecifiers(*
this, &RefLit, Str,
Type, IsObjC,
9271 bool HadError =
false;
9272 auto Iter = Args.begin();
9273 auto End = Args.end();
9274 while (Iter != End) {
9275 const auto &FirstInGroup = *Iter;
9277 Iter != End && Iter->getPosition() == FirstInGroup.getPosition();
9279 HadError |= !Iter->VerifyCompatible(*
this, FirstInGroup, Str,
true);
9288 const char *Str = StrRef.data();
9291 assert(
T &&
"String literal not of constant array type!");
9292 size_t TypeSize =
T->getZExtSize();
9293 size_t StrLen = std::min(std::max(TypeSize,
size_t(1)) - 1, StrRef.size());
9304 switch (AbsFunction) {
9308 case Builtin::BI__builtin_abs:
9309 return Builtin::BI__builtin_labs;
9310 case Builtin::BI__builtin_labs:
9311 return Builtin::BI__builtin_llabs;
9312 case Builtin::BI__builtin_llabs:
9315 case Builtin::BI__builtin_fabsf:
9316 return Builtin::BI__builtin_fabs;
9317 case Builtin::BI__builtin_fabs:
9318 return Builtin::BI__builtin_fabsl;
9319 case Builtin::BI__builtin_fabsl:
9322 case Builtin::BI__builtin_cabsf:
9323 return Builtin::BI__builtin_cabs;
9324 case Builtin::BI__builtin_cabs:
9325 return Builtin::BI__builtin_cabsl;
9326 case Builtin::BI__builtin_cabsl:
9329 case Builtin::BIabs:
9330 return Builtin::BIlabs;
9331 case Builtin::BIlabs:
9332 return Builtin::BIllabs;
9333 case Builtin::BIllabs:
9336 case Builtin::BIfabsf:
9337 return Builtin::BIfabs;
9338 case Builtin::BIfabs:
9339 return Builtin::BIfabsl;
9340 case Builtin::BIfabsl:
9343 case Builtin::BIcabsf:
9344 return Builtin::BIcabs;
9345 case Builtin::BIcabs:
9346 return Builtin::BIcabsl;
9347 case Builtin::BIcabsl:
9376 unsigned AbsFunctionKind) {
9377 unsigned BestKind = 0;
9378 uint64_t ArgSize = Context.getTypeSize(ArgType);
9379 for (
unsigned Kind = AbsFunctionKind; Kind != 0;
9382 if (Context.getTypeSize(ParamType) >= ArgSize) {
9385 else if (Context.hasSameType(ParamType, ArgType)) {
9401 if (
T->isIntegralOrEnumerationType())
9403 if (
T->isRealFloatingType())
9405 if (
T->isAnyComplexType())
9408 llvm_unreachable(
"Type not integer, floating, or complex");
9415 switch (ValueKind) {
9420 case Builtin::BI__builtin_fabsf:
9421 case Builtin::BI__builtin_fabs:
9422 case Builtin::BI__builtin_fabsl:
9423 case Builtin::BI__builtin_cabsf:
9424 case Builtin::BI__builtin_cabs:
9425 case Builtin::BI__builtin_cabsl:
9426 return Builtin::BI__builtin_abs;
9427 case Builtin::BIfabsf:
9428 case Builtin::BIfabs:
9429 case Builtin::BIfabsl:
9430 case Builtin::BIcabsf:
9431 case Builtin::BIcabs:
9432 case Builtin::BIcabsl:
9433 return Builtin::BIabs;
9439 case Builtin::BI__builtin_abs:
9440 case Builtin::BI__builtin_labs:
9441 case Builtin::BI__builtin_llabs:
9442 case Builtin::BI__builtin_cabsf:
9443 case Builtin::BI__builtin_cabs:
9444 case Builtin::BI__builtin_cabsl:
9445 return Builtin::BI__builtin_fabsf;
9446 case Builtin::BIabs:
9447 case Builtin::BIlabs:
9448 case Builtin::BIllabs:
9449 case Builtin::BIcabsf:
9450 case Builtin::BIcabs:
9451 case Builtin::BIcabsl:
9452 return Builtin::BIfabsf;
9458 case Builtin::BI__builtin_abs:
9459 case Builtin::BI__builtin_labs:
9460 case Builtin::BI__builtin_llabs:
9461 case Builtin::BI__builtin_fabsf:
9462 case Builtin::BI__builtin_fabs:
9463 case Builtin::BI__builtin_fabsl:
9464 return Builtin::BI__builtin_cabsf;
9465 case Builtin::BIabs:
9466 case Builtin::BIlabs:
9467 case Builtin::BIllabs:
9468 case Builtin::BIfabsf:
9469 case Builtin::BIfabs:
9470 case Builtin::BIfabsl:
9471 return Builtin::BIcabsf;
9474 llvm_unreachable(
"Unable to convert function");
9485 case Builtin::BI__builtin_abs:
9486 case Builtin::BI__builtin_fabs:
9487 case Builtin::BI__builtin_fabsf:
9488 case Builtin::BI__builtin_fabsl:
9489 case Builtin::BI__builtin_labs:
9490 case Builtin::BI__builtin_llabs:
9491 case Builtin::BI__builtin_cabs:
9492 case Builtin::BI__builtin_cabsf:
9493 case Builtin::BI__builtin_cabsl:
9494 case Builtin::BIabs:
9495 case Builtin::BIlabs:
9496 case Builtin::BIllabs:
9497 case Builtin::BIfabs:
9498 case Builtin::BIfabsf:
9499 case Builtin::BIfabsl:
9500 case Builtin::BIcabs:
9501 case Builtin::BIcabsf:
9502 case Builtin::BIcabsl:
9505 llvm_unreachable(
"Unknown Builtin type");
9511 unsigned AbsKind,
QualType ArgType) {
9512 bool EmitHeaderHint =
true;
9513 const char *HeaderName =
nullptr;
9514 std::string FunctionName;
9515 if (S.
getLangOpts().CPlusPlus && !ArgType->isAnyComplexType()) {
9516 FunctionName =
"std::abs";
9517 if (ArgType->isIntegralOrEnumerationType()) {
9518 HeaderName =
"cstdlib";
9519 }
else if (ArgType->isRealFloatingType()) {
9520 HeaderName =
"cmath";
9522 llvm_unreachable(
"Invalid Type");
9531 for (
const auto *I : R) {
9534 FDecl = dyn_cast<FunctionDecl>(UsingD->getTargetDecl());
9536 FDecl = dyn_cast<FunctionDecl>(I);
9551 EmitHeaderHint =
false;
9569 EmitHeaderHint =
false;
9573 }
else if (!R.
empty()) {
9579 S.
Diag(Loc, diag::note_replace_abs_function)
9585 if (!EmitHeaderHint)
9588 S.
Diag(Loc, diag::note_include_header_or_declare) << HeaderName
9592template <std::
size_t StrLen>
9594 const char (&Str)[StrLen]) {
9607 auto MatchesAny = [&](std::initializer_list<llvm::StringRef> names) {
9608 return llvm::is_contained(names, calleeName);
9613 return MatchesAny({
"__builtin_nan",
"__builtin_nanf",
"__builtin_nanl",
9614 "__builtin_nanf16",
"__builtin_nanf128"});
9616 return MatchesAny({
"__builtin_inf",
"__builtin_inff",
"__builtin_infl",
9617 "__builtin_inff16",
"__builtin_inff128"});
9619 llvm_unreachable(
"unknown MathCheck");
9623 if (FDecl->
getName() !=
"infinity")
9626 if (
const CXXMethodDecl *MDecl = dyn_cast<CXXMethodDecl>(FDecl)) {
9628 if (RDecl->
getName() !=
"numeric_limits")
9645 if (FPO.getNoHonorNaNs() &&
9648 Diag(
Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
9649 << 1 << 0 <<
Call->getSourceRange();
9653 if (FPO.getNoHonorInfs() &&
9657 Diag(
Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
9658 << 0 << 0 <<
Call->getSourceRange();
9662void Sema::CheckAbsoluteValueFunction(
const CallExpr *
Call,
9664 if (
Call->getNumArgs() != 1)
9669 if (AbsKind == 0 && !IsStdAbs)
9672 QualType ArgType =
Call->getArg(0)->IgnoreParenImpCasts()->getType();
9673 QualType ParamType =
Call->getArg(0)->getType();
9678 std::string FunctionName =
9679 IsStdAbs ?
"std::abs" :
Context.BuiltinInfo.getName(AbsKind);
9680 Diag(
Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType;
9681 Diag(
Call->getExprLoc(), diag::note_remove_abs)
9710 if (ArgValueKind == ParamValueKind) {
9711 if (
Context.getTypeSize(ArgType) <=
Context.getTypeSize(ParamType))
9715 Diag(
Call->getExprLoc(), diag::warn_abs_too_small)
9716 << FDecl << ArgType << ParamType;
9718 if (NewAbsKind == 0)
9722 Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
9731 if (NewAbsKind == 0)
9734 Diag(
Call->getExprLoc(), diag::warn_wrong_absolute_value_type)
9735 << FDecl << ParamValueKind << ArgValueKind;
9738 Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
9744 if (!
Call || !FDecl)
return;
9748 if (
Call->getExprLoc().isMacroID())
return;
9751 if (
Call->getNumArgs() != 2)
return;
9754 if (!ArgList)
return;
9755 if (ArgList->size() != 1)
return;
9758 const auto& TA = ArgList->
get(0);
9760 QualType ArgType = TA.getAsType();
9764 auto IsLiteralZeroArg = [](
const Expr* E) ->
bool {
9765 const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);
9766 if (!MTE)
return false;
9767 const auto *
Num = dyn_cast<IntegerLiteral>(MTE->getSubExpr());
9768 if (!
Num)
return false;
9769 if (
Num->getValue() != 0)
return false;
9773 const Expr *FirstArg =
Call->getArg(0);
9774 const Expr *SecondArg =
Call->getArg(1);
9775 const bool IsFirstArgZero = IsLiteralZeroArg(FirstArg);
9776 const bool IsSecondArgZero = IsLiteralZeroArg(SecondArg);
9779 if (IsFirstArgZero == IsSecondArgZero)
return;
9784 SourceRange ZeroRange = IsFirstArgZero ? FirstRange : SecondRange;
9786 Diag(
Call->getExprLoc(), diag::warn_max_unsigned_zero)
9787 << IsFirstArgZero <<
Call->getCallee()->getSourceRange() << ZeroRange;
9790 SourceRange RemovalRange;
9791 if (IsFirstArgZero) {
9792 RemovalRange = SourceRange(FirstRange.
getBegin(),
9799 Diag(
Call->getExprLoc(), diag::note_remove_max_call)
9814 const auto *Size = dyn_cast<BinaryOperator>(E);
9819 if (!Size->isComparisonOp() && !Size->isLogicalOp())
9823 S.
Diag(Size->getOperatorLoc(), diag::warn_memsize_comparison)
9824 << SizeRange << FnName;
9825 S.
Diag(FnLoc, diag::note_memsize_comparison_paren)
9830 S.
Diag(SizeRange.
getBegin(), diag::note_memsize_comparison_cast_silence)
9841 bool &IsContained) {
9843 const Type *Ty =
T->getBaseElementTypeUnsafe();
9844 IsContained =
false;
9857 for (
auto *FD : RD->
fields()) {
9870 if (
const auto *Unary = dyn_cast<UnaryExprOrTypeTraitExpr>(E))
9871 if (Unary->getKind() == UETT_SizeOf)
9880 if (!
SizeOf->isArgumentType())
9881 return SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
9888 return SizeOf->getTypeOfArgument();
9894struct SearchNonTrivialToInitializeField
9897 DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField>;
9899 SearchNonTrivialToInitializeField(
const Expr *E, Sema &S) : E(E), S(S) {}
9902 SourceLocation SL) {
9903 if (
const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
9904 asDerived().visitArray(PDIK, AT, SL);
9908 Super::visitWithKind(PDIK, FT, SL);
9911 void visitARCStrong(QualType FT, SourceLocation SL) {
9914 void visitARCWeak(QualType FT, SourceLocation SL) {
9917 void visitStruct(QualType FT, SourceLocation SL) {
9922 const ArrayType *AT, SourceLocation SL) {
9923 visit(getContext().getBaseElementType(AT), SL);
9925 void visitTrivial(QualType FT, SourceLocation SL) {}
9927 static void diag(QualType RT,
const Expr *E, Sema &S) {
9928 SearchNonTrivialToInitializeField(E, S).visitStruct(RT, SourceLocation());
9937struct SearchNonTrivialToCopyField
9939 using Super = CopiedTypeVisitor<SearchNonTrivialToCopyField, false>;
9941 SearchNonTrivialToCopyField(
const Expr *E, Sema &S) : E(E), S(S) {}
9944 SourceLocation SL) {
9945 if (
const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
9946 asDerived().visitArray(PCK, AT, SL);
9950 Super::visitWithKind(PCK, FT, SL);
9953 void visitARCStrong(QualType FT, SourceLocation SL) {
9956 void visitARCWeak(QualType FT, SourceLocation SL) {
9959 void visitPtrAuth(QualType FT, SourceLocation SL) {
9962 void visitStruct(QualType FT, SourceLocation SL) {
9967 SourceLocation SL) {
9968 visit(getContext().getBaseElementType(AT), SL);
9971 SourceLocation SL) {}
9972 void visitTrivial(QualType FT, SourceLocation SL) {}
9973 void visitVolatileTrivial(QualType FT, SourceLocation SL) {}
9975 static void diag(QualType RT,
const Expr *E, Sema &S) {
9976 SearchNonTrivialToCopyField(E, S).visitStruct(RT, SourceLocation());
9991 if (
const auto *BO = dyn_cast<BinaryOperator>(SizeofExpr)) {
9992 if (BO->getOpcode() != BO_Mul && BO->getOpcode() != BO_Add)
10016 return SM.getFileID(CallLoc) !=
SM.getFileID(ArgLoc);
10018 return SM.getFileID(
SM.getImmediateMacroCallerLoc(CallLoc)) !=
10019 SM.getFileID(
SM.getImmediateMacroCallerLoc(ArgLoc));
10025 if (BId != Builtin::BImemset && BId != Builtin::BIbzero)
10028 const Expr *SizeArg =
10029 Call->getArg(BId == Builtin::BImemset ? 2 : 1)->IgnoreImpCasts();
10031 auto isLiteralZero = [](
const Expr *E) {
10041 if (isLiteralZero(SizeArg) &&
10048 if (BId == Builtin::BIbzero ||
10051 S.
Diag(DiagLoc, diag::warn_suspicious_bzero_size);
10052 S.
Diag(DiagLoc, diag::note_suspicious_bzero_size_silence);
10053 }
else if (!isLiteralZero(
Call->getArg(1)->IgnoreImpCasts())) {
10054 S.
Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 0;
10055 S.
Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 0;
10063 if (BId == Builtin::BImemset &&
10067 S.
Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 1;
10068 S.
Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 1;
10073void Sema::CheckMemaccessArguments(
const CallExpr *
Call,
10080 unsigned ExpectedNumArgs =
10081 (BId == Builtin::BIstrndup || BId == Builtin::BIbzero ? 2 : 3);
10082 if (
Call->getNumArgs() < ExpectedNumArgs)
10085 unsigned LastArg = (BId == Builtin::BImemset || BId == Builtin::BIbzero ||
10086 BId == Builtin::BIstrndup ? 1 : 2);
10088 (BId == Builtin::BIbzero || BId == Builtin::BIstrndup ? 1 : 2);
10089 const Expr *LenExpr =
Call->getArg(LenArg)->IgnoreParenImpCasts();
10092 Call->getBeginLoc(),
Call->getRParenLoc()))
10101 llvm::FoldingSetNodeID SizeOfArgID;
10106 QualType FirstArgTy =
Call->getArg(0)->IgnoreParenImpCasts()->getType();
10107 if (BId == Builtin::BIbzero && !FirstArgTy->
getAs<PointerType>())
10110 for (
unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) {
10111 const Expr *Dest =
Call->getArg(ArgIdx)->IgnoreParenImpCasts();
10112 SourceRange ArgRange =
Call->getArg(ArgIdx)->getSourceRange();
10114 QualType DestTy = Dest->
getType();
10115 QualType PointeeTy;
10116 if (
const PointerType *DestPtrTy = DestTy->
getAs<PointerType>()) {
10129 !
Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess,
10133 if (SizeOfArgID == llvm::FoldingSetNodeID())
10135 llvm::FoldingSetNodeID DestID;
10137 if (DestID == SizeOfArgID) {
10140 unsigned ActionIdx = 0;
10141 StringRef ReadableName = FnName->
getName();
10143 if (
const UnaryOperator *UnaryOp = dyn_cast<UnaryOperator>(Dest))
10144 if (UnaryOp->getOpcode() == UO_AddrOf)
10153 SourceLocation SL = SizeOfArg->
getExprLoc();
10158 if (
SM.isMacroArgExpansion(SL)) {
10160 SL =
SM.getSpellingLoc(SL);
10161 DSR = SourceRange(
SM.getSpellingLoc(DSR.
getBegin()),
10163 SSR = SourceRange(
SM.getSpellingLoc(SSR.
getBegin()),
10168 PDiag(diag::warn_sizeof_pointer_expr_memaccess)
10175 PDiag(diag::warn_sizeof_pointer_expr_memaccess_note)
10186 if (SizeOfArgTy != QualType()) {
10188 Context.typesAreCompatible(SizeOfArgTy, DestTy)) {
10190 PDiag(diag::warn_sizeof_pointer_type_memaccess)
10191 << FnName << SizeOfArgTy << ArgIdx
10198 PointeeTy = DestTy;
10201 if (PointeeTy == QualType())
10206 if (
const CXXRecordDecl *ContainedRD =
10209 unsigned OperationType = 0;
10210 const bool IsCmp = BId == Builtin::BImemcmp || BId == Builtin::BIbcmp;
10213 if (ArgIdx != 0 || IsCmp) {
10214 if (BId == Builtin::BImemcpy)
10216 else if(BId == Builtin::BImemmove)
10223 PDiag(diag::warn_dyn_class_memaccess)
10224 << (IsCmp ? ArgIdx + 2 : ArgIdx) << FnName
10225 << IsContained << ContainedRD << OperationType
10226 <<
Call->getCallee()->getSourceRange());
10228 BId != Builtin::BImemset)
10231 PDiag(diag::warn_arc_object_memaccess)
10232 << ArgIdx << FnName << PointeeTy
10233 <<
Call->getCallee()->getSourceRange());
10240 bool NonTriviallyCopyableCXXRecord =
10244 if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
10247 PDiag(diag::warn_cstruct_memaccess)
10248 << ArgIdx << FnName << PointeeTy << 0);
10249 SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *
this);
10250 }
else if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
10251 NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
10255 PDiag(diag::warn_cxxstruct_memaccess)
10256 << FnName << PointeeTy);
10257 }
else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
10260 PDiag(diag::warn_cstruct_memaccess)
10261 << ArgIdx << FnName << PointeeTy << 1);
10262 SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *
this);
10263 }
else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
10264 NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
10268 PDiag(diag::warn_cxxstruct_memaccess)
10269 << FnName << PointeeTy);
10278 PDiag(diag::note_bad_memaccess_silence)
10314 if (CAT->getZExtSize() <= 1)
10322void Sema::CheckStrlcpycatArguments(
const CallExpr *
Call,
10326 unsigned NumArgs =
Call->getNumArgs();
10327 if ((NumArgs != 3) && (NumArgs != 4))
10332 const Expr *CompareWithSrc =
nullptr;
10335 Call->getBeginLoc(),
Call->getRParenLoc()))
10340 CompareWithSrc = Ex;
10343 if (
const CallExpr *SizeCall = dyn_cast<CallExpr>(SizeArg)) {
10344 if (SizeCall->getBuiltinCallee() == Builtin::BIstrlen &&
10345 SizeCall->getNumArgs() == 1)
10350 if (!CompareWithSrc)
10357 const DeclRefExpr *SrcArgDRE = dyn_cast<DeclRefExpr>(SrcArg);
10361 const DeclRefExpr *CompareWithSrcDRE = dyn_cast<DeclRefExpr>(CompareWithSrc);
10362 if (!CompareWithSrcDRE ||
10366 const Expr *OriginalSizeArg =
Call->getArg(2);
10367 Diag(CompareWithSrcDRE->
getBeginLoc(), diag::warn_strlcpycat_wrong_size)
10374 const Expr *DstArg =
Call->getArg(0)->IgnoreParenImpCasts();
10378 SmallString<128> sizeString;
10379 llvm::raw_svector_ostream
OS(sizeString);
10384 Diag(OriginalSizeArg->
getBeginLoc(), diag::note_strlcpycat_wrong_size)
10391 if (
const DeclRefExpr *D1 = dyn_cast_or_null<DeclRefExpr>(E1))
10392 if (
const DeclRefExpr *D2 = dyn_cast_or_null<DeclRefExpr>(E2))
10393 return D1->getDecl() == D2->getDecl();
10398 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
10407void Sema::CheckStrncatArguments(
const CallExpr *CE,
10422 unsigned PatternType = 0;
10430 }
else if (
const BinaryOperator *BE = dyn_cast<BinaryOperator>(LenArg)) {
10431 if (BE->getOpcode() == BO_Sub) {
10432 const Expr *L = BE->getLHS()->IgnoreParenCasts();
10433 const Expr *R = BE->getRHS()->IgnoreParenCasts();
10444 if (PatternType == 0)
10453 if (
SM.isMacroArgExpansion(SL)) {
10454 SL =
SM.getSpellingLoc(SL);
10455 SR = SourceRange(
SM.getSpellingLoc(SR.
getBegin()),
10460 QualType DstTy = DstArg->
getType();
10463 if (!isKnownSizeArray) {
10464 if (PatternType == 1)
10465 Diag(SL, diag::warn_strncat_wrong_size) << SR;
10467 Diag(SL, diag::warn_strncat_src_size) << SR;
10471 if (PatternType == 1)
10472 Diag(SL, diag::warn_strncat_large_size) << SR;
10474 Diag(SL, diag::warn_strncat_src_size) << SR;
10476 SmallString<128> sizeString;
10477 llvm::raw_svector_ostream
OS(sizeString);
10485 Diag(SL, diag::note_strncat_wrong_size)
10490void CheckFreeArgumentsOnLvalue(
Sema &S,
const std::string &CalleeName,
10499void CheckFreeArgumentsAddressof(
Sema &S,
const std::string &CalleeName,
10501 if (
const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->
getSubExpr())) {
10502 const Decl *D = Lvalue->getDecl();
10503 if (
const auto *DD = dyn_cast<DeclaratorDecl>(D)) {
10504 if (!DD->getType()->isReferenceType())
10505 return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
10509 if (
const auto *Lvalue = dyn_cast<MemberExpr>(UnaryExpr->
getSubExpr()))
10510 return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr,
10511 Lvalue->getMemberDecl());
10514void CheckFreeArgumentsPlus(
Sema &S,
const std::string &CalleeName,
10516 const auto *Lambda = dyn_cast<LambdaExpr>(
10521 S.
Diag(Lambda->getBeginLoc(), diag::warn_free_nonheap_object)
10522 << CalleeName << 2 ;
10525void CheckFreeArgumentsStackArray(
Sema &S,
const std::string &CalleeName,
10527 const auto *Var = dyn_cast<VarDecl>(Lvalue->
getDecl());
10528 if (Var ==
nullptr)
10532 << CalleeName << 0 << Var;
10535void CheckFreeArgumentsCast(
Sema &S,
const std::string &CalleeName,
10538 llvm::raw_svector_ostream
OS(SizeString);
10541 if (Kind == clang::CK_BitCast &&
10542 !
Cast->getSubExpr()->getType()->isFunctionPointerType())
10544 if (Kind == clang::CK_IntegralToPointer &&
10546 Cast->getSubExpr()->IgnoreParenImpCasts()->IgnoreParens()))
10549 switch (
Cast->getCastKind()) {
10550 case clang::CK_BitCast:
10551 case clang::CK_IntegralToPointer:
10552 case clang::CK_FunctionToPointerDecay:
10561 S.
Diag(
Cast->getBeginLoc(), diag::warn_free_nonheap_object)
10562 << CalleeName << 0 <<
OS.str();
10566void Sema::CheckFreeArguments(
const CallExpr *E) {
10567 const std::string CalleeName =
10572 if (
const auto *UnaryExpr = dyn_cast<UnaryOperator>(Arg))
10574 case UnaryOperator::Opcode::UO_AddrOf:
10575 return CheckFreeArgumentsAddressof(*
this, CalleeName, UnaryExpr);
10576 case UnaryOperator::Opcode::UO_Plus:
10577 return CheckFreeArgumentsPlus(*
this, CalleeName, UnaryExpr);
10582 if (
const auto *Lvalue = dyn_cast<DeclRefExpr>(Arg))
10584 return CheckFreeArgumentsStackArray(*
this, CalleeName, Lvalue);
10586 if (
const auto *Label = dyn_cast<AddrLabelExpr>(Arg)) {
10587 Diag(Label->getBeginLoc(), diag::warn_free_nonheap_object)
10588 << CalleeName << 0 << Label->getLabel()->getIdentifier();
10594 << CalleeName << 1 ;
10599 if (
const auto *Cast = dyn_cast<CastExpr>(E->
getArg(0)))
10600 return CheckFreeArgumentsCast(*
this, CalleeName, Cast);
10604Sema::CheckReturnValExpr(
Expr *RetValExp,
QualType lhsType,
10613 Diag(ReturnLoc, diag::warn_null_ret)
10623 if (Op == OO_New || Op == OO_Array_New) {
10624 const FunctionProtoType *Proto
10628 Diag(ReturnLoc, diag::warn_operator_new_returns_null)
10634 Diag(ReturnLoc, diag::err_wasm_table_art) << 1;
10639 if (
Context.getTargetInfo().getTriple().isPPC64())
10651 auto getCastAndLiteral = [&FPLiteral, &FPCast](
const Expr *L,
const Expr *R) {
10652 FPLiteral = dyn_cast<FloatingLiteral>(L->IgnoreParens());
10654 return FPLiteral && FPCast;
10657 if (getCastAndLiteral(LHS, RHS) || getCastAndLiteral(RHS, LHS)) {
10663 llvm::APFloat TargetC = FPLiteral->
getValue();
10664 TargetC.convert(
Context.getFloatTypeSemantics(
QualType(SourceTy, 0)),
10665 llvm::APFloat::rmNearestTiesToEven, &Lossy);
10669 Diag(Loc, diag::warn_float_compare_literal)
10670 << (Opcode == BO_EQ) <<
QualType(SourceTy, 0)
10683 if (
const auto *DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen))
10684 if (
const auto *DRR = dyn_cast<DeclRefExpr>(RightExprSansParen))
10685 if (DRL->getDecl() == DRR->getDecl())
10693 if (
const auto *FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) {
10694 if (FLL->isExact())
10696 }
else if (
const auto *FLR = dyn_cast<FloatingLiteral>(RightExprSansParen))
10697 if (FLR->isExact())
10701 if (
const auto *
CL = dyn_cast<CallExpr>(LeftExprSansParen);
10702 CL &&
CL->getBuiltinCallee())
10705 if (
const auto *CR = dyn_cast<CallExpr>(RightExprSansParen);
10706 CR && CR->getBuiltinCallee())
10710 Diag(Loc, diag::warn_floatingpoint_eq)
10731 IntRange(
unsigned Width,
bool NonNegative)
10732 : Width(Width), NonNegative(NonNegative) {}
10735 unsigned valueBits()
const {
10736 return NonNegative ? Width : Width - 1;
10740 static IntRange forBoolType() {
10741 return IntRange(1,
true);
10745 static IntRange forValueOfType(ASTContext &
C, QualType
T) {
10746 return forValueOfCanonicalType(
C,
10751 static IntRange forValueOfCanonicalType(ASTContext &
C,
const Type *
T) {
10754 if (
const auto *VT = dyn_cast<VectorType>(
T))
10755 T = VT->getElementType().getTypePtr();
10756 if (
const auto *CT = dyn_cast<ComplexType>(
T))
10757 T = CT->getElementType().getTypePtr();
10758 if (
const auto *AT = dyn_cast<AtomicType>(
T))
10759 T = AT->getValueType().getTypePtr();
10761 if (!
C.getLangOpts().CPlusPlus) {
10764 T = ED->getIntegerType().getDesugaredType(
C).getTypePtr();
10769 if (
Enum->isFixed()) {
10770 return IntRange(
C.getIntWidth(QualType(
T, 0)),
10771 !
Enum->getIntegerType()->isSignedIntegerType());
10774 unsigned NumPositive =
Enum->getNumPositiveBits();
10775 unsigned NumNegative =
Enum->getNumNegativeBits();
10777 if (NumNegative == 0)
10778 return IntRange(NumPositive,
true);
10780 return IntRange(std::max(NumPositive + 1, NumNegative),
10784 if (
const auto *EIT = dyn_cast<BitIntType>(
T))
10785 return IntRange(EIT->getNumBits(), EIT->isUnsigned());
10798 static IntRange forTargetOfCanonicalType(ASTContext &
C,
const Type *
T) {
10801 if (
const VectorType *VT = dyn_cast<VectorType>(
T))
10802 T = VT->getElementType().getTypePtr();
10803 if (
const ComplexType *CT = dyn_cast<ComplexType>(
T))
10804 T = CT->getElementType().getTypePtr();
10805 if (
const AtomicType *AT = dyn_cast<AtomicType>(
T))
10806 T = AT->getValueType().getTypePtr();
10808 T =
C.getCanonicalType(ED->getIntegerType()).getTypePtr();
10810 if (
const auto *EIT = dyn_cast<BitIntType>(
T))
10811 return IntRange(EIT->getNumBits(), EIT->isUnsigned());
10820 static IntRange join(IntRange L, IntRange R) {
10821 bool Unsigned = L.NonNegative && R.NonNegative;
10822 return IntRange(std::max(L.valueBits(), R.valueBits()) + !
Unsigned,
10823 L.NonNegative && R.NonNegative);
10827 static IntRange bit_and(IntRange L, IntRange R) {
10828 unsigned Bits = std::max(L.Width, R.Width);
10829 bool NonNegative =
false;
10830 if (L.NonNegative) {
10831 Bits = std::min(Bits, L.Width);
10832 NonNegative =
true;
10834 if (R.NonNegative) {
10835 Bits = std::min(Bits, R.Width);
10836 NonNegative =
true;
10838 return IntRange(Bits, NonNegative);
10842 static IntRange sum(IntRange L, IntRange R) {
10843 bool Unsigned = L.NonNegative && R.NonNegative;
10844 return IntRange(std::max(L.valueBits(), R.valueBits()) + 1 + !
Unsigned,
10849 static IntRange difference(IntRange L, IntRange R) {
10853 bool CanWiden = !L.NonNegative || !R.NonNegative;
10854 bool Unsigned = L.NonNegative && R.Width == 0;
10855 return IntRange(std::max(L.valueBits(), R.valueBits()) + CanWiden +
10861 static IntRange product(IntRange L, IntRange R) {
10865 bool CanWiden = !L.NonNegative && !R.NonNegative;
10866 bool Unsigned = L.NonNegative && R.NonNegative;
10867 return IntRange(L.valueBits() + R.valueBits() + CanWiden + !
Unsigned,
10872 static IntRange rem(IntRange L, IntRange R) {
10876 return IntRange(std::min(L.valueBits(), R.valueBits()) + !
Unsigned,
10884 if (value.isSigned() && value.isNegative())
10885 return IntRange(value.getSignificantBits(),
false);
10887 if (value.getBitWidth() > MaxWidth)
10888 value = value.trunc(MaxWidth);
10892 return IntRange(value.getActiveBits(),
true);
10896 if (result.
isInt())
10903 R = IntRange::join(R, El);
10911 return IntRange::join(R, I);
10926 Ty = AtomicRHS->getValueType();
10945 bool InConstantContext,
10946 bool Approximate) {
10957 if (
const auto *CE = dyn_cast<ImplicitCastExpr>(E)) {
10958 if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue)
10962 IntRange OutputTypeRange = IntRange::forValueOfType(
C,
GetExprType(CE));
10964 bool isIntegerCast = CE->getCastKind() == CK_IntegralCast ||
10965 CE->getCastKind() == CK_BooleanToSignedIntegral;
10968 if (!isIntegerCast)
10969 return OutputTypeRange;
10972 C, CE->getSubExpr(), std::min(MaxWidth, OutputTypeRange.Width),
10973 InConstantContext, Approximate);
10975 return std::nullopt;
10978 if (SubRange->Width >= OutputTypeRange.Width)
10979 return OutputTypeRange;
10983 return IntRange(SubRange->Width,
10984 SubRange->NonNegative || OutputTypeRange.NonNegative);
10987 if (
const auto *CO = dyn_cast<ConditionalOperator>(E)) {
10990 if (CO->getCond()->EvaluateAsBooleanCondition(CondResult,
C))
10992 C, CondResult ? CO->getTrueExpr() : CO->getFalseExpr(), MaxWidth,
10993 InConstantContext, Approximate);
10998 Expr *TrueExpr = CO->getTrueExpr();
11000 return std::nullopt;
11002 std::optional<IntRange> L =
11005 return std::nullopt;
11007 Expr *FalseExpr = CO->getFalseExpr();
11009 return std::nullopt;
11011 std::optional<IntRange> R =
11014 return std::nullopt;
11016 return IntRange::join(*L, *R);
11019 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
11020 IntRange (*Combine)(IntRange, IntRange) = IntRange::join;
11022 switch (BO->getOpcode()) {
11024 llvm_unreachable(
"builtin <=> should have class type");
11035 return IntRange::forBoolType();
11064 Combine = IntRange::bit_and;
11072 = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) {
11073 if (I->getValue() == 1) {
11074 IntRange R = IntRange::forValueOfType(
C,
GetExprType(E));
11075 return IntRange(R.Width,
true);
11085 case BO_ShrAssign: {
11087 C, BO->getLHS(), MaxWidth, InConstantContext, Approximate);
11089 return std::nullopt;
11093 if (std::optional<llvm::APSInt> shift =
11094 BO->getRHS()->getIntegerConstantExpr(
C)) {
11095 if (shift->isNonNegative()) {
11096 if (shift->uge(L->Width))
11097 L->Width = (L->NonNegative ? 0 : 1);
11099 L->Width -= shift->getZExtValue();
11113 Combine = IntRange::sum;
11117 if (BO->getLHS()->getType()->isPointerType())
11120 Combine = IntRange::difference;
11125 Combine = IntRange::product;
11134 C, BO->getLHS(), opWidth, InConstantContext, Approximate);
11136 return std::nullopt;
11139 if (std::optional<llvm::APSInt> divisor =
11140 BO->getRHS()->getIntegerConstantExpr(
C)) {
11141 unsigned log2 = divisor->logBase2();
11142 if (
log2 >= L->Width)
11143 L->Width = (L->NonNegative ? 0 : 1);
11145 L->Width = std::min(L->Width -
log2, MaxWidth);
11153 C, BO->getRHS(), opWidth, InConstantContext, Approximate);
11155 return std::nullopt;
11157 return IntRange(L->Width, L->NonNegative && R->NonNegative);
11161 Combine = IntRange::rem;
11173 unsigned opWidth =
C.getIntWidth(
T);
11175 InConstantContext, Approximate);
11177 return std::nullopt;
11180 InConstantContext, Approximate);
11182 return std::nullopt;
11184 IntRange
C = Combine(*L, *R);
11185 C.NonNegative |=
T->isUnsignedIntegerOrEnumerationType();
11186 C.Width = std::min(
C.Width, MaxWidth);
11190 if (
const auto *UO = dyn_cast<UnaryOperator>(E)) {
11191 switch (UO->getOpcode()) {
11194 return IntRange::forBoolType();
11208 C, UO->getSubExpr(), MaxWidth, InConstantContext, Approximate);
11211 return std::nullopt;
11216 return IntRange(std::min(SubRange->Width + 1, MaxWidth),
false);
11226 C, UO->getSubExpr(), MaxWidth, InConstantContext, Approximate);
11229 return std::nullopt;
11234 std::min(SubRange->Width + (
int)SubRange->NonNegative, MaxWidth),
11244 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(E))
11245 return TryGetExprRange(
C, OVE->getSourceExpr(), MaxWidth, InConstantContext,
11249 return IntRange(BitField->getBitWidthValue(),
11250 BitField->getType()->isUnsignedIntegerOrEnumerationType());
11253 return std::nullopt;
11259 bool InConstantContext,
11260 bool Approximate) {
11269 const llvm::fltSemantics &Src,
11270 const llvm::fltSemantics &Tgt) {
11271 llvm::APFloat truncated = value;
11274 truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
11275 truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);
11277 return truncated.bitwiseIsEqual(value);
11286 const llvm::fltSemantics &Src,
11287 const llvm::fltSemantics &Tgt) {
11304 bool IsListInit =
false);
11319 return MacroName !=
"YES" && MacroName !=
"NO" &&
11320 MacroName !=
"true" && MacroName !=
"false";
11328 (!E->
getType()->isSignedIntegerType() ||
11343struct PromotedRange {
11345 llvm::APSInt PromotedMin;
11347 llvm::APSInt PromotedMax;
11349 PromotedRange(IntRange R,
unsigned BitWidth,
bool Unsigned) {
11351 PromotedMin = PromotedMax = llvm::APSInt(BitWidth,
Unsigned);
11352 else if (R.Width >= BitWidth && !
Unsigned) {
11356 PromotedMin = llvm::APSInt::getMinValue(BitWidth,
Unsigned);
11357 PromotedMax = llvm::APSInt::getMaxValue(BitWidth,
Unsigned);
11359 PromotedMin = llvm::APSInt::getMinValue(R.Width, R.NonNegative)
11360 .extOrTrunc(BitWidth);
11361 PromotedMin.setIsUnsigned(
Unsigned);
11363 PromotedMax = llvm::APSInt::getMaxValue(R.Width, R.NonNegative)
11364 .extOrTrunc(BitWidth);
11365 PromotedMax.setIsUnsigned(
Unsigned);
11370 bool isContiguous()
const {
return PromotedMin <= PromotedMax; }
11380 InRangeFlag = 0x40,
11383 Min =
LE | InRangeFlag,
11384 InRange = InRangeFlag,
11385 Max =
GE | InRangeFlag,
11388 OnlyValue =
LE |
GE |
EQ | InRangeFlag,
11393 assert(
Value.getBitWidth() == PromotedMin.getBitWidth() &&
11394 Value.isUnsigned() == PromotedMin.isUnsigned());
11395 if (!isContiguous()) {
11396 assert(
Value.isUnsigned() &&
"discontiguous range for signed compare");
11397 if (
Value.isMinValue())
return Min;
11398 if (
Value.isMaxValue())
return Max;
11399 if (
Value >= PromotedMin)
return InRange;
11400 if (
Value <= PromotedMax)
return InRange;
11404 switch (llvm::APSInt::compareValues(
Value, PromotedMin)) {
11405 case -1:
return Less;
11406 case 0:
return PromotedMin == PromotedMax ? OnlyValue :
Min;
11408 switch (llvm::APSInt::compareValues(
Value, PromotedMax)) {
11409 case -1:
return InRange;
11410 case 0:
return Max;
11415 llvm_unreachable(
"impossible compare result");
11418 static std::optional<StringRef>
11420 if (Op == BO_Cmp) {
11422 if (ConstantOnRHS) std::swap(LTFlag, GTFlag);
11424 if (R & EQ)
return StringRef(
"'std::strong_ordering::equal'");
11425 if (R & LTFlag)
return StringRef(
"'std::strong_ordering::less'");
11426 if (R & GTFlag)
return StringRef(
"'std::strong_ordering::greater'");
11427 return std::nullopt;
11434 }
else if (Op == BO_NE) {
11438 if ((Op == BO_LT || Op == BO_GE) ^ ConstantOnRHS) {
11445 if (Op == BO_GE || Op == BO_LE)
11446 std::swap(TrueFlag, FalseFlag);
11449 return StringRef(
"true");
11451 return StringRef(
"false");
11452 return std::nullopt;
11459 while (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
11460 if (ICE->getCastKind() != CK_IntegralCast &&
11461 ICE->getCastKind() != CK_NoOp)
11463 E = ICE->getSubExpr();
11472 enum ConstantValueKind {
11477 if (
auto *BL = dyn_cast<CXXBoolLiteralExpr>(Constant))
11478 return BL->getValue() ? ConstantValueKind::LiteralTrue
11479 : ConstantValueKind::LiteralFalse;
11480 return ConstantValueKind::Miscellaneous;
11485 const llvm::APSInt &
Value,
11486 bool RhsConstant) {
11508 if (!OtherValueRange)
11513 OtherT = AT->getValueType();
11514 IntRange OtherTypeRange = IntRange::forValueOfType(S.
Context, OtherT);
11518 bool IsObjCSignedCharBool = S.
getLangOpts().ObjC &&
11524 bool OtherIsBooleanDespiteType =
11526 if (OtherIsBooleanDespiteType || IsObjCSignedCharBool)
11527 OtherTypeRange = *OtherValueRange = IntRange::forBoolType();
11531 PromotedRange OtherPromotedValueRange(*OtherValueRange,
Value.getBitWidth(),
11532 Value.isUnsigned());
11533 auto Cmp = OtherPromotedValueRange.compare(
Value);
11534 auto Result = PromotedRange::constantValue(E->
getOpcode(), Cmp, RhsConstant);
11540 bool TautologicalTypeCompare =
false;
11542 PromotedRange OtherPromotedTypeRange(OtherTypeRange,
Value.getBitWidth(),
11543 Value.isUnsigned());
11544 auto TypeCmp = OtherPromotedTypeRange.compare(
Value);
11547 TautologicalTypeCompare =
true;
11555 if (!TautologicalTypeCompare && OtherValueRange->Width == 0)
11564 bool InRange = Cmp & PromotedRange::InRangeFlag;
11570 if (
Other->refersToBitField() && InRange &&
Value == 0 &&
11571 Other->getType()->isUnsignedIntegerOrEnumerationType())
11572 TautologicalTypeCompare =
true;
11577 if (
const auto *DR = dyn_cast<DeclRefExpr>(Constant))
11578 ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
11582 llvm::raw_svector_ostream OS(PrettySourceValue);
11584 OS <<
'\'' << *ED <<
"' (" <<
Value <<
")";
11585 }
else if (
auto *BL = dyn_cast<ObjCBoolLiteralExpr>(
11587 OS << (BL->getValue() ?
"YES" :
"NO");
11592 if (!TautologicalTypeCompare) {
11594 << RhsConstant << OtherValueRange->Width << OtherValueRange->NonNegative
11600 if (IsObjCSignedCharBool) {
11602 S.
PDiag(diag::warn_tautological_compare_objc_bool)
11603 << OS.str() << *Result);
11610 if (!InRange ||
Other->isKnownToHaveBooleanValue()) {
11614 S.
PDiag(!InRange ? diag::warn_out_of_range_compare
11615 : diag::warn_tautological_bool_compare)
11617 << OtherIsBooleanDespiteType << *Result
11624 ? diag::warn_unsigned_enum_always_true_comparison
11625 : IsCharTy ? diag::warn_unsigned_char_always_true_comparison
11626 : diag::warn_unsigned_always_true_comparison)
11627 : diag::warn_tautological_constant_compare;
11630 << RhsConstant << OtherT << E->
getOpcodeStr() << OS.str() << *Result
11663 if (
T->isIntegralType(S.
Context)) {
11664 std::optional<llvm::APSInt> RHSValue =
11666 std::optional<llvm::APSInt> LHSValue =
11670 if (RHSValue && LHSValue)
11674 if ((
bool)RHSValue ^ (
bool)LHSValue) {
11676 const bool RhsConstant = (
bool)RHSValue;
11677 Expr *Const = RhsConstant ? RHS : LHS;
11679 const llvm::APSInt &
Value = RhsConstant ? *RHSValue : *LHSValue;
11688 if (!
T->hasUnsignedIntegerRepresentation()) {
11702 if (
const auto *TET = dyn_cast<TypeOfExprType>(LHS->
getType()))
11704 if (
const auto *TET = dyn_cast<TypeOfExprType>(RHS->
getType()))
11710 Expr *signedOperand, *unsignedOperand;
11713 "unsigned comparison between two signed integer expressions?");
11714 signedOperand = LHS;
11715 unsignedOperand = RHS;
11717 signedOperand = RHS;
11718 unsignedOperand = LHS;
11724 std::optional<IntRange> signedRange =
11736 if (signedRange->NonNegative)
11748 if (!unsignedRange)
11753 assert(unsignedRange->NonNegative &&
"unsigned range includes negative?");
11755 if (unsignedRange->Width < comparisonWidth)
11760 S.
PDiag(diag::warn_mixed_sign_comparison)
11779 if (
auto *BitfieldEnumDecl = BitfieldType->
getAsEnumDecl()) {
11784 !BitfieldEnumDecl->getIntegerTypeSourceInfo() &&
11785 BitfieldEnumDecl->getNumPositiveBits() > 0 &&
11786 BitfieldEnumDecl->getNumNegativeBits() == 0) {
11787 S.
Diag(InitLoc, diag::warn_no_underlying_type_specified_for_enum_bitfield)
11788 << BitfieldEnumDecl;
11795 Init->isValueDependent() ||
11796 Init->isTypeDependent())
11799 Expr *OriginalInit =
Init->IgnoreParenImpCasts();
11809 const PreferredTypeAttr *PTAttr =
nullptr;
11811 PTAttr = Bitfield->
getAttr<PreferredTypeAttr>();
11813 ED = PTAttr->getType()->getAsEnumDecl();
11821 bool SignedEnum = ED->getNumNegativeBits() > 0;
11828 unsigned DiagID = 0;
11829 if (SignedEnum && !SignedBitfield) {
11832 ? diag::warn_unsigned_bitfield_assigned_signed_enum
11834 warn_preferred_type_unsigned_bitfield_assigned_signed_enum;
11835 }
else if (SignedBitfield && !SignedEnum &&
11836 ED->getNumPositiveBits() == FieldWidth) {
11839 ? diag::warn_signed_bitfield_enum_conversion
11840 : diag::warn_preferred_type_signed_bitfield_enum_conversion;
11843 S.
Diag(InitLoc, DiagID) << Bitfield << ED;
11848 << SignedEnum << TypeRange;
11850 S.
Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
11857 unsigned BitsNeeded = SignedEnum ? std::max(ED->getNumPositiveBits() + 1,
11858 ED->getNumNegativeBits())
11859 : ED->getNumPositiveBits();
11862 if (BitsNeeded > FieldWidth) {
11866 ? diag::warn_bitfield_too_small_for_enum
11867 : diag::warn_preferred_type_bitfield_too_small_for_enum;
11868 S.
Diag(InitLoc, DiagID) << Bitfield << ED;
11872 S.
Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
11880 llvm::APSInt
Value = Result.Val.getInt();
11882 unsigned OriginalWidth =
Value.getBitWidth();
11888 bool OneAssignedToOneBitBitfield = FieldWidth == 1 &&
Value == 1;
11889 if (OneAssignedToOneBitBitfield && !S.
LangOpts.CPlusPlus) {
11896 if (!
Value.isSigned() ||
Value.isNegative())
11897 if (
UnaryOperator *UO = dyn_cast<UnaryOperator>(OriginalInit))
11898 if (UO->getOpcode() == UO_Minus || UO->getOpcode() == UO_Not)
11899 OriginalWidth =
Value.getSignificantBits();
11901 if (OriginalWidth <= FieldWidth)
11905 llvm::APSInt TruncatedValue =
Value.trunc(FieldWidth);
11909 TruncatedValue = TruncatedValue.extend(OriginalWidth);
11910 if (llvm::APSInt::isSameValue(
Value, TruncatedValue))
11914 std::string PrettyTrunc =
toString(TruncatedValue, 10);
11916 S.
Diag(InitLoc, OneAssignedToOneBitBitfield
11917 ? diag::warn_impcast_single_bit_bitield_precision_constant
11918 : diag::warn_impcast_bitfield_precision_constant)
11919 << PrettyValue << PrettyTrunc << OriginalInit->
getType()
11920 <<
Init->getSourceRange();
11952 bool PruneControlFlow =
false) {
11959 if (
T.hasAddressSpace())
11961 if (PruneControlFlow) {
11975 bool PruneControlFlow =
false) {
11982 bool IsBool =
T->isSpecificBuiltinType(BuiltinType::Bool);
11987 if (
const auto *UOp = dyn_cast<UnaryOperator>(InnerE))
11988 if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus)
11993 llvm::APFloat
Value(0.0);
11999 E, S.
Diag(CContext, diag::warn_impcast_float_to_objc_signed_char_bool)
12004 diag::warn_impcast_float_integer, PruneWarnings);
12007 bool isExact =
false;
12010 T->hasUnsignedIntegerRepresentation());
12011 llvm::APFloat::opStatus Result =
Value.convertToInteger(
12012 IntegerValue, llvm::APFloat::rmTowardZero, &isExact);
12020 unsigned precision = llvm::APFloat::semanticsPrecision(
Value.getSemantics());
12021 precision = (precision * 59 + 195) / 196;
12022 Value.toString(PrettySourceValue, precision);
12026 E, S.
Diag(CContext, diag::warn_impcast_constant_value_to_objc_bool)
12027 << PrettySourceValue);
12030 if (Result == llvm::APFloat::opOK && isExact) {
12031 if (IsLiteral)
return;
12032 return DiagnoseImpCast(S, E,
T, CContext, diag::warn_impcast_float_integer,
12038 if (!IsBool && Result == llvm::APFloat::opInvalidOp)
12041 IsLiteral ? diag::warn_impcast_literal_float_to_integer_out_of_range
12042 : diag::warn_impcast_float_to_integer_out_of_range,
12045 unsigned DiagID = 0;
12048 DiagID = diag::warn_impcast_literal_float_to_integer;
12049 }
else if (IntegerValue == 0) {
12050 if (
Value.isZero()) {
12052 diag::warn_impcast_float_integer, PruneWarnings);
12055 DiagID = diag::warn_impcast_float_to_integer_zero;
12057 if (IntegerValue.isUnsigned()) {
12058 if (!IntegerValue.isMaxValue()) {
12060 diag::warn_impcast_float_integer, PruneWarnings);
12063 if (!IntegerValue.isMaxSignedValue() &&
12064 !IntegerValue.isMinSignedValue()) {
12066 diag::warn_impcast_float_integer, PruneWarnings);
12070 DiagID = diag::warn_impcast_float_to_integer;
12075 PrettyTargetValue =
Value.isZero() ?
"false" :
"true";
12077 IntegerValue.toString(PrettyTargetValue);
12079 if (PruneWarnings) {
12082 << E->
getType() <<
T.getUnqualifiedType()
12083 << PrettySourceValue << PrettyTargetValue
12087 << E->
getType() <<
T.getUnqualifiedType() << PrettySourceValue
12096 "Must be compound assignment operation");
12107 ->getComputationResultType()
12114 if (ResultBT->isInteger())
12116 E->
getExprLoc(), diag::warn_impcast_float_integer);
12118 if (!ResultBT->isFloatingPoint())
12127 diag::warn_impcast_float_result_precision);
12132 if (!Range.Width)
return "0";
12134 llvm::APSInt ValueInRange =
Value;
12135 ValueInRange.setIsSigned(!Range.NonNegative);
12136 ValueInRange = ValueInRange.trunc(Range.Width);
12137 return toString(ValueInRange, 10);
12147 const Type *Source =
12149 if (
Target->isDependentType())
12152 const auto *FloatCandidateBT =
12153 dyn_cast<BuiltinType>(ToBool ? Source :
Target);
12154 const Type *BoolCandidateType = ToBool ?
Target : Source;
12157 FloatCandidateBT && (FloatCandidateBT->isFloatingPoint()));
12162 for (
unsigned I = 0, N = TheCall->
getNumArgs(); I < N; ++I) {
12168 S, TheCall->
getArg(I - 1),
false));
12170 S, TheCall->
getArg(I + 1),
false));
12175 diag::warn_impcast_floating_point_to_bool);
12190 if (!IsGNUNullExpr && !HasNullPtrType)
12194 if (
T->isAnyPointerType() ||
T->isBlockPointerType() ||
12195 T->isMemberPointerType() || !
T->isScalarType() ||
T->isNullPtrType())
12198 if (S.
Diags.
isIgnored(diag::warn_impcast_null_pointer_to_integer,
12211 if (IsGNUNullExpr && Loc.
isMacroID()) {
12214 if (MacroName ==
"NULL")
12222 S.
Diag(Loc, diag::warn_impcast_null_pointer_to_integer)
12236 const char FirstLiteralCharacter =
12238 if (FirstLiteralCharacter ==
'0')
12244 if (CC.
isValid() &&
T->isCharType()) {
12245 const char FirstContextCharacter =
12247 if (FirstContextCharacter ==
'{')
12255 const auto *IL = dyn_cast<IntegerLiteral>(E);
12257 if (
auto *UO = dyn_cast<UnaryOperator>(E)) {
12258 if (UO->getOpcode() == UO_Minus)
12259 return dyn_cast<IntegerLiteral>(UO->getSubExpr());
12270 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
12274 if (Opc == BO_Shl) {
12277 if (LHS && LHS->getValue() == 0)
12278 S.
Diag(ExprLoc, diag::warn_left_shift_always) << 0;
12280 RHS->getValue().isNonNegative() &&
12282 S.
Diag(ExprLoc, diag::warn_left_shift_always)
12283 << (Result.Val.getInt() != 0);
12285 S.
Diag(ExprLoc, diag::warn_left_shift_in_bool_context)
12292 if (
const auto *CO = dyn_cast<ConditionalOperator>(E)) {
12297 if ((LHS->getValue() == 0 || LHS->getValue() == 1) &&
12298 (RHS->getValue() == 0 || RHS->getValue() == 1))
12301 if (LHS->getValue() != 0 && RHS->getValue() != 0)
12302 S.
Diag(ExprLoc, diag::warn_integer_constants_in_conditional_always_true);
12310 assert(Source->isUnicodeCharacterType() &&
Target->isUnicodeCharacterType() &&
12316 if (Source->isChar16Type() &&
Target->isChar32Type())
12322 llvm::APSInt
Value(32);
12323 Value = Result.Val.getInt();
12324 bool IsASCII =
Value <= 0x7F;
12325 bool IsBMP =
Value <= 0xDFFF || (
Value >= 0xE000 &&
Value <= 0xFFFF);
12326 bool ConversionPreservesSemantics =
12327 IsASCII || (!Source->isChar8Type() && !
Target->isChar8Type() && IsBMP);
12329 if (!ConversionPreservesSemantics) {
12330 auto IsSingleCodeUnitCP = [](
const QualType &
T,
12331 const llvm::APSInt &
Value) {
12332 if (
T->isChar8Type())
12333 return llvm::IsSingleCodeUnitUTF8Codepoint(
Value.getExtValue());
12334 if (
T->isChar16Type())
12335 return llvm::IsSingleCodeUnitUTF16Codepoint(
Value.getExtValue());
12336 assert(
T->isChar32Type());
12337 return llvm::IsSingleCodeUnitUTF32Codepoint(
Value.getExtValue());
12340 S.
Diag(CC, diag::warn_impcast_unicode_char_type_constant)
12349 LosesPrecision ? diag::warn_impcast_unicode_precision
12350 : diag::warn_impcast_unicode_char_type);
12364 From = MaybePointee;
12371 if (FromFn->getCFIUncheckedCalleeAttr() &&
12372 !ToFn->getCFIUncheckedCalleeAttr())
12374 if (!FromFn->getCFIUncheckedCalleeAttr() &&
12375 ToFn->getCFIUncheckedCalleeAttr())
12383 From =
Context.getCanonicalType(From);
12384 To =
Context.getCanonicalType(To);
12385 return ::AdjustingCFIUncheckedCallee(From, To) ==
Discarding;
12389 From =
Context.getCanonicalType(From);
12390 To =
Context.getCanonicalType(To);
12391 return ::AdjustingCFIUncheckedCallee(From, To) ==
Adding;
12395 bool *ICContext,
bool IsListInit) {
12400 if (Source ==
Target)
return;
12401 if (
Target->isDependentType())
return;
12411 if (Source->isAtomicType())
12415 if (
Target->isSpecificBuiltinType(BuiltinType::Bool)) {
12421 diag::warn_impcast_string_literal_to_bool);
12427 diag::warn_impcast_objective_c_literal_to_bool);
12429 if (Source->isPointerType() || Source->canDecayToPointerType()) {
12439 if (
ObjC().isSignedCharBool(
T) && Source->isIntegralType(
Context)) {
12442 if (
Result.Val.getInt() != 1 &&
Result.Val.getInt() != 0) {
12444 E,
Diag(CC, diag::warn_impcast_constant_value_to_objc_bool)
12453 if (
auto *ArrayLiteral = dyn_cast<ObjCArrayLiteral>(E))
12455 else if (
auto *DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(E))
12460 if (
Target->isSveVLSBuiltinType() &&
12467 if (
Target->isRVVVLSBuiltinType() &&
12477 return DiagnoseImpCast(*
this, E,
T, CC, diag::warn_impcast_vector_scalar);
12484 diag::warn_hlsl_impcast_vector_truncation);
12496 if (
auto VecTy = dyn_cast<VectorType>(
Target))
12497 Target = VecTy->getElementType().getTypePtr();
12507 ? diag::err_impcast_complex_scalar
12508 : diag::warn_impcast_complex_scalar);
12515 const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
12521 const Type *OriginalTarget =
Context.getCanonicalType(
T).getTypePtr();
12524 if (
ARM().areCompatibleSveTypes(
QualType(OriginalTarget, 0),
12526 ARM().areLaxCompatibleSveTypes(
QualType(OriginalTarget, 0),
12568 else if (Order < 0) {
12578 if (TargetBT && TargetBT->
isInteger()) {
12605 diag::warn_impcast_floating_point_to_bool);
12613 if (Source->isFixedPointType()) {
12614 if (
Target->isUnsaturatedFixedPointType()) {
12618 llvm::APFixedPoint
Value =
Result.Val.getFixedPoint();
12619 llvm::APFixedPoint MaxVal =
Context.getFixedPointMax(
T);
12620 llvm::APFixedPoint MinVal =
Context.getFixedPointMin(
T);
12623 PDiag(diag::warn_impcast_fixed_point_range)
12624 <<
Value.toString() <<
T
12630 }
else if (
Target->isIntegerType()) {
12634 llvm::APFixedPoint FXResult =
Result.Val.getFixedPoint();
12637 llvm::APSInt IntResult = FXResult.convertToInt(
12638 Context.getIntWidth(
T),
Target->isSignedIntegerOrEnumerationType(),
12643 PDiag(diag::warn_impcast_fixed_point_range)
12644 << FXResult.toString() <<
T
12651 }
else if (
Target->isUnsaturatedFixedPointType()) {
12652 if (Source->isIntegerType()) {
12659 llvm::APFixedPoint IntResult = llvm::APFixedPoint::getFromIntValue(
12664 PDiag(diag::warn_impcast_fixed_point_range)
12685 unsigned int SourcePrecision =
SourceRange->Width;
12689 unsigned int TargetPrecision = llvm::APFloatBase::semanticsPrecision(
12692 if (SourcePrecision > 0 && TargetPrecision > 0 &&
12693 SourcePrecision > TargetPrecision) {
12695 if (std::optional<llvm::APSInt> SourceInt =
12700 llvm::APFloat TargetFloatValue(
12702 llvm::APFloat::opStatus ConversionStatus =
12703 TargetFloatValue.convertFromAPInt(
12705 llvm::APFloat::rmNearestTiesToEven);
12707 if (ConversionStatus != llvm::APFloat::opOK) {
12709 SourceInt->toString(PrettySourceValue, 10);
12711 TargetFloatValue.toString(PrettyTargetValue, TargetPrecision);
12715 PDiag(diag::warn_impcast_integer_float_precision_constant)
12716 << PrettySourceValue << PrettyTargetValue << E->
getType() <<
T
12722 diag::warn_impcast_integer_float_precision);
12731 if (Source->isUnicodeCharacterType() &&
Target->isUnicodeCharacterType()) {
12736 if (
Target->isBooleanType())
12740 Diag(CC, diag::warn_cast_discards_cfi_unchecked_callee)
12744 if (!Source->isIntegerType() || !
Target->isIntegerType())
12749 if (
Target->isSpecificBuiltinType(BuiltinType::Bool))
12752 if (
ObjC().isSignedCharBool(
T) && !Source->isCharType() &&
12755 E,
Diag(CC, diag::warn_impcast_int_to_objc_signed_char_bool)
12760 if (!LikelySourceRange)
12763 IntRange SourceTypeRange =
12764 IntRange::forTargetOfCanonicalType(
Context, Source);
12765 IntRange TargetRange = IntRange::forTargetOfCanonicalType(
Context,
Target);
12767 if (LikelySourceRange->Width > TargetRange.Width) {
12773 llvm::APSInt
Value(32);
12783 PDiag(diag::warn_impcast_integer_precision_constant)
12784 << PrettySourceValue << PrettyTargetValue
12794 if (
const auto *UO = dyn_cast<UnaryOperator>(E)) {
12795 if (UO->getOpcode() == UO_Minus)
12797 *
this, E,
T, CC, diag::warn_impcast_integer_precision_on_negation);
12800 if (TargetRange.Width == 32 &&
Context.getIntWidth(E->
getType()) == 64)
12804 diag::warn_impcast_integer_precision);
12807 if (TargetRange.Width > SourceTypeRange.Width) {
12808 if (
auto *UO = dyn_cast<UnaryOperator>(E))
12809 if (UO->getOpcode() == UO_Minus)
12810 if (Source->isUnsignedIntegerType()) {
12811 if (
Target->isUnsignedIntegerType())
12813 diag::warn_impcast_high_order_zero_bits);
12814 if (
Target->isSignedIntegerType())
12816 diag::warn_impcast_nonnegative_result);
12820 if (TargetRange.Width == LikelySourceRange->Width &&
12821 !TargetRange.NonNegative && LikelySourceRange->NonNegative &&
12822 Source->isSignedIntegerType()) {
12836 PDiag(diag::warn_impcast_integer_precision_constant)
12837 << PrettySourceValue << PrettyTargetValue << E->
getType() <<
T
12847 ((TargetRange.NonNegative && !LikelySourceRange->NonNegative) ||
12848 (!TargetRange.NonNegative && LikelySourceRange->NonNegative &&
12849 LikelySourceRange->Width == TargetRange.Width))) {
12853 if (SourceBT && SourceBT->
isInteger() && TargetBT &&
12855 Source->isSignedIntegerType() ==
Target->isSignedIntegerType()) {
12859 unsigned DiagID = diag::warn_impcast_integer_sign;
12867 DiagID = diag::warn_impcast_integer_sign_conditional;
12884 Source =
Context.getCanonicalType(SourceType).getTypePtr();
12886 if (
const EnumType *SourceEnum = Source->getAsCanonical<EnumType>())
12887 if (
const EnumType *TargetEnum =
Target->getAsCanonical<EnumType>())
12888 if (SourceEnum->getDecl()->hasNameForLinkage() &&
12889 TargetEnum->getDecl()->hasNameForLinkage() &&
12890 SourceEnum != TargetEnum) {
12895 diag::warn_impcast_different_enum_types);
12909 if (
auto *CO = dyn_cast<AbstractConditionalOperator>(E))
12922 if (
auto *BCO = dyn_cast<BinaryConditionalOperator>(E))
12923 TrueExpr = BCO->getCommon();
12925 bool Suspicious =
false;
12929 if (
T->isBooleanType())
12934 if (!Suspicious)
return;
12937 if (!S.
Diags.
isIgnored(diag::warn_impcast_integer_sign_conditional, CC))
12944 Suspicious =
false;
12949 E->
getType(), CC, &Suspicious);
12966struct AnalyzeImplicitConversionsWorkItem {
12975 bool ExtraCheckForImplicitConversion,
12978 WorkList.push_back({E, CC,
false});
12980 if (ExtraCheckForImplicitConversion && E->
getType() !=
T)
12987 Sema &S, AnalyzeImplicitConversionsWorkItem Item,
12989 Expr *OrigE = Item.E;
13008 Expr *SourceExpr = E;
13013 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(E))
13014 if (
auto *Src = OVE->getSourceExpr())
13017 if (
const auto *UO = dyn_cast<UnaryOperator>(SourceExpr))
13018 if (UO->getOpcode() == UO_Not &&
13019 UO->getSubExpr()->isKnownToHaveBooleanValue())
13020 S.
Diag(UO->getBeginLoc(), diag::warn_bitwise_negation_bool)
13024 if (
auto *BO = dyn_cast<BinaryOperator>(SourceExpr)) {
13025 if ((BO->getOpcode() == BO_And || BO->getOpcode() == BO_Or) &&
13026 BO->getLHS()->isKnownToHaveBooleanValue() &&
13027 BO->getRHS()->isKnownToHaveBooleanValue() &&
13028 BO->getLHS()->HasSideEffects(S.
Context) &&
13029 BO->getRHS()->HasSideEffects(S.
Context)) {
13040 if (SR.str() ==
"&" || SR.str() ==
"|") {
13042 S.
Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
13043 << (BO->getOpcode() == BO_And ?
"&" :
"|")
13046 BO->getOperatorLoc(),
13047 (BO->getOpcode() == BO_And ?
"&&" :
"||"));
13048 S.
Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
13050 }
else if (BO->isCommaOp() && !S.
getLangOpts().CPlusPlus) {
13068 if (
auto *CO = dyn_cast<AbstractConditionalOperator>(SourceExpr)) {
13074 if (
const auto *
Call = dyn_cast<CallExpr>(SourceExpr))
13089 for (
auto *SE : POE->semantics())
13090 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(SE))
13091 WorkList.push_back({OVE->getSourceExpr(), CC, IsListInit});
13095 if (
auto *CE = dyn_cast<ExplicitCastExpr>(E)) {
13096 E = CE->getSubExpr();
13102 if (
auto *InitListE = dyn_cast<InitListExpr>(E)) {
13103 if (InitListE->getNumInits() == 1) {
13104 E = InitListE->getInit(0);
13111 WorkList.push_back({E, CC, IsListInit});
13115 if (
auto *OutArgE = dyn_cast<HLSLOutArgExpr>(E)) {
13116 WorkList.push_back({OutArgE->getArgLValue(), CC, IsListInit});
13120 if (OutArgE->isInOut())
13121 WorkList.push_back(
13122 {OutArgE->getCastedTemporary()->getSourceExpr(), CC, IsListInit});
13123 WorkList.push_back({OutArgE->getWritebackCast(), CC, IsListInit});
13129 if (BO->isComparisonOp())
13133 if (BO->getOpcode() == BO_Assign)
13136 if (BO->isAssignmentOp())
13152 bool IsLogicalAndOperator = BO && BO->
getOpcode() == BO_LAnd;
13154 Expr *ChildExpr = dyn_cast_or_null<Expr>(SubStmt);
13158 if (
auto *CSE = dyn_cast<CoroutineSuspendExpr>(E))
13159 if (ChildExpr == CSE->getOperand())
13165 if (IsLogicalAndOperator &&
13170 WorkList.push_back({ChildExpr, CC, IsListInit});
13184 if (
U->getOpcode() == UO_LNot) {
13186 }
else if (
U->getOpcode() != UO_AddrOf) {
13187 if (
U->getSubExpr()->getType()->isAtomicType())
13188 S.
Diag(
U->getSubExpr()->getBeginLoc(),
13189 diag::warn_atomic_implicit_seq_cst);
13200 WorkList.push_back({OrigE, CC, IsListInit});
13201 while (!WorkList.empty())
13213 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
13216 }
else if (
const MemberExpr *M = dyn_cast<MemberExpr>(E)) {
13217 if (!M->getMemberDecl()->getType()->isReferenceType())
13219 }
else if (
const CallExpr *
Call = dyn_cast<CallExpr>(E)) {
13220 if (!
Call->getCallReturnType(SemaRef.
Context)->isReferenceType())
13222 FD =
Call->getDirectCallee();
13231 SemaRef.
Diag(FD->
getLocation(), diag::note_reference_is_return_value) << FD;
13245 if (
SM.isMacroBodyExpansion(Loc))
13247 Loc =
SM.getImmediateMacroCallerLoc(Loc);
13271 unsigned DiagID = IsCompare ? diag::warn_this_null_compare
13272 : diag::warn_this_bool_conversion;
13277 bool IsAddressOf =
false;
13279 if (
auto *UO = dyn_cast<UnaryOperator>(E->
IgnoreParens())) {
13280 if (UO->getOpcode() != UO_AddrOf)
13282 IsAddressOf =
true;
13283 E = UO->getSubExpr();
13287 unsigned DiagID = IsCompare
13288 ? diag::warn_address_of_reference_null_compare
13289 : diag::warn_address_of_reference_bool_conversion;
13297 auto ComplainAboutNonnullParamOrCall = [&](
const Attr *NonnullAttr) {
13300 llvm::raw_string_ostream S(Str);
13302 unsigned DiagID = IsCompare ? diag::warn_nonnull_expr_compare
13303 : diag::warn_cast_nonnull_to_bool;
13306 Diag(NonnullAttr->getLocation(), diag::note_declared_nonnull) << IsParam;
13311 if (
auto *Callee =
Call->getDirectCallee()) {
13312 if (
const Attr *A = Callee->getAttr<ReturnsNonNullAttr>()) {
13313 ComplainAboutNonnullParamOrCall(A);
13322 if (
const auto *MCallExpr = dyn_cast<CXXMemberCallExpr>(E)) {
13323 if (
const auto *MRecordDecl = MCallExpr->getRecordDecl();
13324 MRecordDecl && MRecordDecl->isLambda()) {
13327 << MRecordDecl->getSourceRange() << Range << IsEqual;
13337 }
else if (
MemberExpr *M = dyn_cast<MemberExpr>(E)) {
13338 D = M->getMemberDecl();
13346 if (
const auto* PV = dyn_cast<ParmVarDecl>(D)) {
13349 if (
const Attr *A = PV->getAttr<NonNullAttr>()) {
13350 ComplainAboutNonnullParamOrCall(A);
13354 if (
const auto *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
13358 auto ParamIter = llvm::find(FD->
parameters(), PV);
13360 unsigned ParamNo = std::distance(FD->
param_begin(), ParamIter);
13364 ComplainAboutNonnullParamOrCall(
NonNull);
13369 if (ArgNo.getASTIndex() == ParamNo) {
13370 ComplainAboutNonnullParamOrCall(
NonNull);
13380 const bool IsArray =
T->isArrayType();
13381 const bool IsFunction =
T->isFunctionType();
13384 if (IsAddressOf && IsFunction) {
13389 if (!IsAddressOf && !IsFunction && !IsArray)
13394 llvm::raw_string_ostream S(Str);
13397 unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare
13398 : diag::warn_impcast_pointer_to_bool;
13405 DiagType = AddressOf;
13406 else if (IsFunction)
13407 DiagType = FunctionPointer;
13409 DiagType = ArrayPointer;
13411 llvm_unreachable(
"Could not determine diagnostic.");
13413 << Range << IsEqual;
13426 if (ReturnType.
isNull())
13464 CheckArrayAccess(E);
13474void Sema::CheckForIntOverflow (
const Expr *E) {
13476 SmallVector<const Expr *, 2> Exprs(1, E);
13479 const Expr *OriginalE = Exprs.pop_back_val();
13487 if (
const auto *InitList = dyn_cast<InitListExpr>(OriginalE))
13488 Exprs.append(InitList->inits().begin(), InitList->inits().end());
13491 else if (
const auto *
Call = dyn_cast<CallExpr>(E))
13492 Exprs.append(
Call->arg_begin(),
Call->arg_end());
13493 else if (
const auto *Message = dyn_cast<ObjCMessageExpr>(E))
13495 else if (
const auto *Construct = dyn_cast<CXXConstructExpr>(E))
13496 Exprs.append(Construct->arg_begin(), Construct->arg_end());
13497 else if (
const auto *Temporary = dyn_cast<CXXBindTemporaryExpr>(E))
13498 Exprs.push_back(Temporary->getSubExpr());
13499 else if (
const auto *Array = dyn_cast<ArraySubscriptExpr>(E))
13500 Exprs.push_back(Array->getIdx());
13501 else if (
const auto *Compound = dyn_cast<CompoundLiteralExpr>(E))
13502 Exprs.push_back(Compound->getInitializer());
13503 else if (
const auto *
New = dyn_cast<CXXNewExpr>(E);
13504 New &&
New->isArray()) {
13505 if (
auto ArraySize =
New->getArraySize())
13506 Exprs.push_back(*ArraySize);
13507 }
else if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(OriginalE))
13508 Exprs.push_back(MTE->getSubExpr());
13509 }
while (!Exprs.empty());
13517 using Base = ConstEvaluatedExprVisitor<SequenceChecker>;
13524 class SequenceTree {
13526 explicit Value(
unsigned Parent) : Parent(Parent), Merged(
false) {}
13527 unsigned Parent : 31;
13528 LLVM_PREFERRED_TYPE(
bool)
13529 unsigned Merged : 1;
13531 SmallVector<Value, 8> Values;
13537 friend class SequenceTree;
13541 explicit Seq(
unsigned N) : Index(N) {}
13544 Seq() : Index(0) {}
13547 SequenceTree() { Values.push_back(
Value(0)); }
13548 Seq root()
const {
return Seq(0); }
13553 Seq allocate(
Seq Parent) {
13554 Values.push_back(
Value(Parent.Index));
13555 return Seq(Values.size() - 1);
13559 void merge(
Seq S) {
13560 Values[S.Index].Merged =
true;
13566 bool isUnsequenced(
Seq Cur,
Seq Old) {
13567 unsigned C = representative(Cur.Index);
13568 unsigned Target = representative(Old.Index);
13572 C = Values[
C].Parent;
13579 unsigned representative(
unsigned K) {
13580 if (Values[K].Merged)
13582 return Values[K].Parent = representative(Values[K].Parent);
13588 using Object =
const NamedDecl *;
13602 UK_ModAsSideEffect,
13604 UK_Count = UK_ModAsSideEffect + 1
13610 const Expr *UsageExpr =
nullptr;
13611 SequenceTree::Seq
Seq;
13617 Usage Uses[UK_Count];
13620 bool Diagnosed =
false;
13624 using UsageInfoMap = llvm::SmallDenseMap<Object, UsageInfo, 16>;
13632 UsageInfoMap UsageMap;
13635 SequenceTree::Seq Region;
13639 SmallVectorImpl<std::pair<Object, Usage>> *ModAsSideEffect =
nullptr;
13643 SmallVectorImpl<const Expr *> &WorkList;
13650 struct SequencedSubexpression {
13651 SequencedSubexpression(SequenceChecker &
Self)
13652 :
Self(
Self), OldModAsSideEffect(
Self.ModAsSideEffect) {
13653 Self.ModAsSideEffect = &ModAsSideEffect;
13656 ~SequencedSubexpression() {
13657 for (
const std::pair<Object, Usage> &M : llvm::reverse(ModAsSideEffect)) {
13661 UsageInfo &UI =
Self.UsageMap[M.first];
13662 auto &SideEffectUsage = UI.Uses[UK_ModAsSideEffect];
13663 Self.addUsage(M.first, UI, SideEffectUsage.UsageExpr, UK_ModAsValue);
13664 SideEffectUsage = M.second;
13666 Self.ModAsSideEffect = OldModAsSideEffect;
13669 SequenceChecker &
Self;
13670 SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect;
13671 SmallVectorImpl<std::pair<Object, Usage>> *OldModAsSideEffect;
13678 class EvaluationTracker {
13680 EvaluationTracker(SequenceChecker &
Self)
13682 Self.EvalTracker =
this;
13685 ~EvaluationTracker() {
13686 Self.EvalTracker = Prev;
13688 Prev->EvalOK &= EvalOK;
13691 bool evaluate(
const Expr *E,
bool &
Result) {
13696 Self.SemaRef.isConstantEvaluatedContext());
13701 SequenceChecker &
Self;
13702 EvaluationTracker *Prev;
13703 bool EvalOK =
true;
13704 } *EvalTracker =
nullptr;
13708 Object getObject(
const Expr *E,
bool Mod)
const {
13710 if (
const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
13711 if (Mod && (UO->getOpcode() == UO_PreInc || UO->getOpcode() == UO_PreDec))
13712 return getObject(UO->getSubExpr(), Mod);
13713 }
else if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
13714 if (BO->getOpcode() == BO_Comma)
13715 return getObject(BO->getRHS(), Mod);
13716 if (Mod && BO->isAssignmentOp())
13717 return getObject(BO->getLHS(), Mod);
13718 }
else if (
const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
13721 return ME->getMemberDecl();
13722 }
else if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
13731 void addUsage(Object O, UsageInfo &UI,
const Expr *UsageExpr, UsageKind UK) {
13733 Usage &U = UI.Uses[UK];
13734 if (!U.UsageExpr || !Tree.isUnsequenced(Region, U.Seq)) {
13738 if (UK == UK_ModAsSideEffect && ModAsSideEffect)
13739 ModAsSideEffect->push_back(std::make_pair(O, U));
13741 U.UsageExpr = UsageExpr;
13751 void checkUsage(Object O, UsageInfo &UI,
const Expr *UsageExpr,
13752 UsageKind OtherKind,
bool IsModMod) {
13756 const Usage &U = UI.Uses[OtherKind];
13757 if (!U.UsageExpr || !Tree.isUnsequenced(Region, U.Seq))
13760 const Expr *Mod = U.UsageExpr;
13761 const Expr *ModOrUse = UsageExpr;
13762 if (OtherKind == UK_Use)
13763 std::swap(Mod, ModOrUse);
13767 SemaRef.
PDiag(IsModMod ? diag::warn_unsequenced_mod_mod
13768 : diag::warn_unsequenced_mod_use)
13769 << O << SourceRange(ModOrUse->
getExprLoc()));
13770 UI.Diagnosed =
true;
13799 void notePreUse(Object O,
const Expr *UseExpr) {
13800 UsageInfo &UI = UsageMap[O];
13802 checkUsage(O, UI, UseExpr, UK_ModAsValue,
false);
13805 void notePostUse(Object O,
const Expr *UseExpr) {
13806 UsageInfo &UI = UsageMap[O];
13807 checkUsage(O, UI, UseExpr, UK_ModAsSideEffect,
13809 addUsage(O, UI, UseExpr, UK_Use);
13812 void notePreMod(Object O,
const Expr *ModExpr) {
13813 UsageInfo &UI = UsageMap[O];
13815 checkUsage(O, UI, ModExpr, UK_ModAsValue,
true);
13816 checkUsage(O, UI, ModExpr, UK_Use,
false);
13819 void notePostMod(Object O,
const Expr *ModExpr, UsageKind UK) {
13820 UsageInfo &UI = UsageMap[O];
13821 checkUsage(O, UI, ModExpr, UK_ModAsSideEffect,
13823 addUsage(O, UI, ModExpr, UK);
13827 SequenceChecker(Sema &S,
const Expr *E,
13828 SmallVectorImpl<const Expr *> &WorkList)
13829 :
Base(S.Context), SemaRef(S), Region(Tree.root()), WorkList(WorkList) {
13833 (void)this->WorkList;
13836 void VisitStmt(
const Stmt *S) {
13840 void VisitExpr(
const Expr *E) {
13842 Base::VisitStmt(E);
13845 void VisitCoroutineSuspendExpr(
const CoroutineSuspendExpr *CSE) {
13846 for (
auto *Sub : CSE->
children()) {
13847 const Expr *ChildExpr = dyn_cast_or_null<Expr>(Sub);
13862 void VisitCastExpr(
const CastExpr *E) {
13874 void VisitSequencedExpressions(
const Expr *SequencedBefore,
13875 const Expr *SequencedAfter) {
13876 SequenceTree::Seq BeforeRegion = Tree.allocate(Region);
13877 SequenceTree::Seq AfterRegion = Tree.allocate(Region);
13878 SequenceTree::Seq OldRegion = Region;
13881 SequencedSubexpression SeqBefore(*
this);
13882 Region = BeforeRegion;
13883 Visit(SequencedBefore);
13886 Region = AfterRegion;
13887 Visit(SequencedAfter);
13889 Region = OldRegion;
13891 Tree.merge(BeforeRegion);
13892 Tree.merge(AfterRegion);
13895 void VisitArraySubscriptExpr(
const ArraySubscriptExpr *ASE) {
13900 VisitSequencedExpressions(ASE->
getLHS(), ASE->
getRHS());
13907 void VisitBinPtrMemD(
const BinaryOperator *BO) { VisitBinPtrMem(BO); }
13908 void VisitBinPtrMemI(
const BinaryOperator *BO) { VisitBinPtrMem(BO); }
13909 void VisitBinPtrMem(
const BinaryOperator *BO) {
13914 VisitSequencedExpressions(BO->
getLHS(), BO->
getRHS());
13921 void VisitBinShl(
const BinaryOperator *BO) { VisitBinShlShr(BO); }
13922 void VisitBinShr(
const BinaryOperator *BO) { VisitBinShlShr(BO); }
13923 void VisitBinShlShr(
const BinaryOperator *BO) {
13927 VisitSequencedExpressions(BO->
getLHS(), BO->
getRHS());
13934 void VisitBinComma(
const BinaryOperator *BO) {
13939 VisitSequencedExpressions(BO->
getLHS(), BO->
getRHS());
13942 void VisitBinAssign(
const BinaryOperator *BO) {
13943 SequenceTree::Seq RHSRegion;
13944 SequenceTree::Seq LHSRegion;
13946 RHSRegion = Tree.allocate(Region);
13947 LHSRegion = Tree.allocate(Region);
13949 RHSRegion = Region;
13950 LHSRegion = Region;
13952 SequenceTree::Seq OldRegion = Region;
13968 SequencedSubexpression SeqBefore(*
this);
13969 Region = RHSRegion;
13973 Region = LHSRegion;
13977 notePostUse(O, BO);
13981 Region = LHSRegion;
13985 notePostUse(O, BO);
13987 Region = RHSRegion;
13995 Region = OldRegion;
13999 : UK_ModAsSideEffect);
14001 Tree.merge(RHSRegion);
14002 Tree.merge(LHSRegion);
14006 void VisitCompoundAssignOperator(
const CompoundAssignOperator *CAO) {
14007 VisitBinAssign(CAO);
14010 void VisitUnaryPreInc(
const UnaryOperator *UO) { VisitUnaryPreIncDec(UO); }
14011 void VisitUnaryPreDec(
const UnaryOperator *UO) { VisitUnaryPreIncDec(UO); }
14012 void VisitUnaryPreIncDec(
const UnaryOperator *UO) {
14015 return VisitExpr(UO);
14023 : UK_ModAsSideEffect);
14026 void VisitUnaryPostInc(
const UnaryOperator *UO) { VisitUnaryPostIncDec(UO); }
14027 void VisitUnaryPostDec(
const UnaryOperator *UO) { VisitUnaryPostIncDec(UO); }
14028 void VisitUnaryPostIncDec(
const UnaryOperator *UO) {
14031 return VisitExpr(UO);
14035 notePostMod(O, UO, UK_ModAsSideEffect);
14038 void VisitBinLOr(
const BinaryOperator *BO) {
14044 SequenceTree::Seq LHSRegion = Tree.allocate(Region);
14045 SequenceTree::Seq RHSRegion = Tree.allocate(Region);
14046 SequenceTree::Seq OldRegion = Region;
14048 EvaluationTracker Eval(*
this);
14050 SequencedSubexpression Sequenced(*
this);
14051 Region = LHSRegion;
14058 bool EvalResult =
false;
14059 bool EvalOK = Eval.evaluate(BO->
getLHS(), EvalResult);
14060 bool ShouldVisitRHS = !EvalOK || !EvalResult;
14061 if (ShouldVisitRHS) {
14062 Region = RHSRegion;
14066 Region = OldRegion;
14067 Tree.merge(LHSRegion);
14068 Tree.merge(RHSRegion);
14071 void VisitBinLAnd(
const BinaryOperator *BO) {
14077 SequenceTree::Seq LHSRegion = Tree.allocate(Region);
14078 SequenceTree::Seq RHSRegion = Tree.allocate(Region);
14079 SequenceTree::Seq OldRegion = Region;
14081 EvaluationTracker Eval(*
this);
14083 SequencedSubexpression Sequenced(*
this);
14084 Region = LHSRegion;
14090 bool EvalResult =
false;
14091 bool EvalOK = Eval.evaluate(BO->
getLHS(), EvalResult);
14092 bool ShouldVisitRHS = !EvalOK || EvalResult;
14093 if (ShouldVisitRHS) {
14094 Region = RHSRegion;
14098 Region = OldRegion;
14099 Tree.merge(LHSRegion);
14100 Tree.merge(RHSRegion);
14103 void VisitAbstractConditionalOperator(
const AbstractConditionalOperator *CO) {
14108 SequenceTree::Seq ConditionRegion = Tree.allocate(Region);
14124 SequenceTree::Seq TrueRegion = Tree.allocate(Region);
14125 SequenceTree::Seq FalseRegion = Tree.allocate(Region);
14126 SequenceTree::Seq OldRegion = Region;
14128 EvaluationTracker Eval(*
this);
14130 SequencedSubexpression Sequenced(*
this);
14131 Region = ConditionRegion;
14141 bool EvalResult =
false;
14142 bool EvalOK = Eval.evaluate(CO->
getCond(), EvalResult);
14143 bool ShouldVisitTrueExpr = !EvalOK || EvalResult;
14144 bool ShouldVisitFalseExpr = !EvalOK || !EvalResult;
14145 if (ShouldVisitTrueExpr) {
14146 Region = TrueRegion;
14149 if (ShouldVisitFalseExpr) {
14150 Region = FalseRegion;
14154 Region = OldRegion;
14155 Tree.merge(ConditionRegion);
14156 Tree.merge(TrueRegion);
14157 Tree.merge(FalseRegion);
14160 void VisitCallExpr(
const CallExpr *CE) {
14172 SequencedSubexpression Sequenced(*
this);
14177 SequenceTree::Seq CalleeRegion;
14178 SequenceTree::Seq OtherRegion;
14179 if (SemaRef.getLangOpts().CPlusPlus17) {
14180 CalleeRegion = Tree.allocate(Region);
14181 OtherRegion = Tree.allocate(Region);
14183 CalleeRegion = Region;
14184 OtherRegion = Region;
14186 SequenceTree::Seq OldRegion = Region;
14189 Region = CalleeRegion;
14191 SequencedSubexpression Sequenced(*this);
14192 Visit(CE->getCallee());
14194 Visit(CE->getCallee());
14198 Region = OtherRegion;
14202 Region = OldRegion;
14204 Tree.merge(CalleeRegion);
14205 Tree.merge(OtherRegion);
14223 return VisitCallExpr(CXXOCE);
14234 case OO_MinusEqual:
14236 case OO_SlashEqual:
14237 case OO_PercentEqual:
14238 case OO_CaretEqual:
14241 case OO_LessLessEqual:
14242 case OO_GreaterGreaterEqual:
14243 SequencingKind = RHSBeforeLHS;
14247 case OO_GreaterGreater:
14253 SequencingKind = LHSBeforeRHS;
14257 SequencingKind = LHSBeforeRest;
14261 SequencingKind = NoSequencing;
14265 if (SequencingKind == NoSequencing)
14266 return VisitCallExpr(CXXOCE);
14269 SequencedSubexpression Sequenced(*
this);
14272 assert(SemaRef.getLangOpts().CPlusPlus17 &&
14273 "Should only get there with C++17 and above!");
14274 assert((CXXOCE->getNumArgs() == 2 || CXXOCE->getOperator() == OO_Call) &&
14275 "Should only get there with an overloaded binary operator"
14276 " or an overloaded call operator!");
14278 if (SequencingKind == LHSBeforeRest) {
14279 assert(CXXOCE->getOperator() == OO_Call &&
14280 "We should only have an overloaded call operator here!");
14289 SequenceTree::Seq PostfixExprRegion = Tree.allocate(Region);
14290 SequenceTree::Seq ArgsRegion = Tree.allocate(Region);
14291 SequenceTree::Seq OldRegion = Region;
14293 assert(CXXOCE->getNumArgs() >= 1 &&
14294 "An overloaded call operator must have at least one argument"
14295 " for the postfix-expression!");
14296 const Expr *PostfixExpr = CXXOCE->getArgs()[0];
14297 llvm::ArrayRef<const Expr *> Args(CXXOCE->getArgs() + 1,
14298 CXXOCE->getNumArgs() - 1);
14302 Region = PostfixExprRegion;
14303 SequencedSubexpression Sequenced(*this);
14304 Visit(PostfixExpr);
14308 Region = ArgsRegion;
14309 for (const Expr *Arg : Args)
14312 Region = OldRegion;
14313 Tree.merge(PostfixExprRegion);
14314 Tree.merge(ArgsRegion);
14316 assert(CXXOCE->getNumArgs() == 2 &&
14317 "Should only have two arguments here!");
14318 assert((SequencingKind == LHSBeforeRHS ||
14319 SequencingKind == RHSBeforeLHS) &&
14320 "Unexpected sequencing kind!");
14324 const Expr *E1 = CXXOCE->getArg(0);
14325 const Expr *E2 = CXXOCE->getArg(1);
14326 if (SequencingKind == RHSBeforeLHS)
14329 return VisitSequencedExpressions(E1, E2);
14336 SequencedSubexpression Sequenced(*
this);
14339 return VisitExpr(CCE);
14342 SequenceExpressionsInOrder(
14348 return VisitExpr(ILE);
14351 SequenceExpressionsInOrder(ILE->
inits());
14363 SequenceTree::Seq Parent = Region;
14364 for (
const Expr *E : ExpressionList) {
14367 Region = Tree.allocate(Parent);
14368 Elts.push_back(Region);
14374 for (
unsigned I = 0; I < Elts.size(); ++I)
14375 Tree.merge(Elts[I]);
14379SequenceChecker::UsageInfo::UsageInfo() =
default;
14383void Sema::CheckUnsequencedOperations(
const Expr *E) {
14384 SmallVector<const Expr *, 8> WorkList;
14385 WorkList.push_back(E);
14386 while (!WorkList.empty()) {
14387 const Expr *Item = WorkList.pop_back_val();
14388 SequenceChecker(*
this, Item, WorkList);
14393 bool IsConstexpr) {
14396 CheckImplicitConversions(E, CheckLoc);
14398 CheckUnsequencedOperations(E);
14400 CheckForIntOverflow(E);
14413 if (
const auto *PointerTy = dyn_cast<PointerType>(PType)) {
14417 if (
const auto *ReferenceTy = dyn_cast<ReferenceType>(PType)) {
14421 if (
const auto *ParenTy = dyn_cast<ParenType>(PType)) {
14435 S.
Diag(Loc, diag::err_array_star_in_function_definition);
14439 bool CheckParameterNames) {
14440 bool HasInvalidParm =
false;
14442 assert(Param &&
"null in a parameter list");
14451 if (!Param->isInvalidDecl() &&
14453 diag::err_typecheck_decl_incomplete_type) ||
14455 diag::err_abstract_type_in_decl,
14457 Param->setInvalidDecl();
14458 HasInvalidParm =
true;
14463 if (CheckParameterNames && Param->getIdentifier() ==
nullptr &&
14467 Diag(Param->getLocation(), diag::ext_parameter_name_omitted_c23);
14475 QualType PType = Param->getOriginalType();
14483 if (!Param->isInvalidDecl()) {
14484 if (
CXXRecordDecl *ClassDecl = Param->getType()->getAsCXXRecordDecl()) {
14485 if (!ClassDecl->isInvalidDecl() &&
14486 !ClassDecl->hasIrrelevantDestructor() &&
14487 !ClassDecl->isDependentContext() &&
14488 ClassDecl->isParamDestroyedInCallee()) {
14500 if (
const auto *
Attr = Param->getAttr<PassObjectSizeAttr>())
14501 if (!Param->getType().isConstQualified())
14502 Diag(Param->getLocation(), diag::err_attribute_pointers_only)
14506 if (
LangOpts.CPlusPlus && !Param->isInvalidDecl()) {
14511 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC->
getParent()))
14512 CheckShadowInheritedFields(Param->getLocation(), Param->getDeclName(),
14517 if (!Param->isInvalidDecl() &&
14518 Param->getOriginalType()->isWebAssemblyTableType()) {
14519 Param->setInvalidDecl();
14520 HasInvalidParm =
true;
14521 Diag(Param->getLocation(), diag::err_wasm_table_as_function_parameter);
14525 return HasInvalidParm;
14528std::optional<std::pair<
14537static std::pair<CharUnits, CharUnits>
14545 if (
Base->isVirtual()) {
14552 BaseAlignment = std::min(BaseAlignment, NonVirtualAlignment);
14559 DerivedType =
Base->getType();
14562 return std::make_pair(BaseAlignment, Offset);
14566static std::optional<std::pair<CharUnits, CharUnits>>
14572 return std::nullopt;
14577 return std::nullopt;
14581 CharUnits Offset = EltSize * IdxRes->getExtValue();
14584 return std::make_pair(P->first, P->second + Offset);
14590 return std::make_pair(
14591 P->first.alignmentAtOffset(P->second).alignmentAtOffset(EltSize),
14597std::optional<std::pair<
14605 case Stmt::CStyleCastExprClass:
14606 case Stmt::CXXStaticCastExprClass:
14607 case Stmt::ImplicitCastExprClass: {
14609 const Expr *From = CE->getSubExpr();
14610 switch (CE->getCastKind()) {
14615 case CK_UncheckedDerivedToBase:
14616 case CK_DerivedToBase: {
14626 case Stmt::ArraySubscriptExprClass: {
14631 case Stmt::DeclRefExprClass: {
14635 if (!VD->getType()->isReferenceType()) {
14637 if (VD->hasDependentAlignment())
14646 case Stmt::MemberExprClass: {
14648 auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
14652 std::optional<std::pair<CharUnits, CharUnits>> P;
14661 return std::make_pair(P->first,
14664 case Stmt::UnaryOperatorClass: {
14674 case Stmt::BinaryOperatorClass: {
14686 return std::nullopt;
14691std::optional<std::pair<
14700 case Stmt::CStyleCastExprClass:
14701 case Stmt::CXXStaticCastExprClass:
14702 case Stmt::ImplicitCastExprClass: {
14704 const Expr *From = CE->getSubExpr();
14705 switch (CE->getCastKind()) {
14710 case CK_ArrayToPointerDecay:
14712 case CK_UncheckedDerivedToBase:
14713 case CK_DerivedToBase: {
14723 case Stmt::CXXThisExprClass: {
14728 case Stmt::UnaryOperatorClass: {
14734 case Stmt::BinaryOperatorClass: {
14743 if (Opcode == BO_Add && !RHS->getType()->isIntegralOrEnumerationType())
14744 std::swap(LHS, RHS);
14754 return std::nullopt;
14759 std::optional<std::pair<CharUnits, CharUnits>> P =
14763 return P->first.alignmentAtOffset(P->second);
14781 if (!DestPtr)
return;
14787 if (DestAlign.
isOne())
return;
14791 if (!SrcPtr)
return;
14802 if (SrcAlign >= DestAlign)
return;
14807 <<
static_cast<unsigned>(DestAlign.
getQuantity())
14811void Sema::CheckArrayAccess(
const Expr *BaseExpr,
const Expr *IndexExpr,
14813 bool AllowOnePastEnd,
bool IndexNegated) {
14822 const Type *EffectiveType =
14826 Context.getAsConstantArrayType(BaseExpr->
getType());
14829 StrictFlexArraysLevel =
getLangOpts().getStrictFlexArraysLevel();
14831 const Type *BaseType =
14833 bool IsUnboundedArray =
14835 Context, StrictFlexArraysLevel,
14838 (!IsUnboundedArray && BaseType->isDependentType()))
14846 if (IndexNegated) {
14847 index.setIsUnsigned(
false);
14851 if (IsUnboundedArray) {
14854 if (
index.isUnsigned() || !
index.isNegative()) {
14856 unsigned AddrBits = ASTC.getTargetInfo().getPointerWidth(
14858 if (
index.getBitWidth() < AddrBits)
14860 std::optional<CharUnits> ElemCharUnits =
14861 ASTC.getTypeSizeInCharsIfKnown(EffectiveType);
14864 if (!ElemCharUnits || ElemCharUnits->isZero())
14866 llvm::APInt ElemBytes(
index.getBitWidth(), ElemCharUnits->getQuantity());
14871 if (
index.getActiveBits() <= AddrBits) {
14873 llvm::APInt Product(
index);
14875 Product = Product.umul_ov(ElemBytes, Overflow);
14876 if (!Overflow && Product.getActiveBits() <= AddrBits)
14882 llvm::APInt MaxElems = llvm::APInt::getMaxValue(AddrBits);
14883 MaxElems = MaxElems.zext(std::max(AddrBits + 1, ElemBytes.getBitWidth()));
14885 ElemBytes = ElemBytes.zextOrTrunc(MaxElems.getBitWidth());
14886 MaxElems = MaxElems.udiv(ElemBytes);
14889 ASE ? diag::warn_array_index_exceeds_max_addressable_bounds
14890 : diag::warn_ptr_arith_exceeds_max_addressable_bounds;
14895 PDiag(DiagID) << index << AddrBits
14896 << (
unsigned)ASTC.toBits(*ElemCharUnits)
14897 << ElemBytes << MaxElems
14898 << MaxElems.getZExtValue()
14901 const NamedDecl *ND =
nullptr;
14903 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
14905 if (
const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
14907 if (
const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
14908 ND = ME->getMemberDecl();
14912 PDiag(diag::note_array_declared_here) << ND);
14917 if (index.isUnsigned() || !index.isNegative()) {
14927 llvm::APInt size = ArrayTy->
getSize();
14929 if (BaseType != EffectiveType) {
14937 if (!ptrarith_typesize)
14938 ptrarith_typesize =
Context.getCharWidth();
14940 if (ptrarith_typesize != array_typesize) {
14942 uint64_t ratio = array_typesize / ptrarith_typesize;
14946 if (ptrarith_typesize * ratio == array_typesize)
14947 size *= llvm::APInt(size.getBitWidth(), ratio);
14951 if (size.getBitWidth() > index.getBitWidth())
14952 index = index.zext(size.getBitWidth());
14953 else if (size.getBitWidth() < index.getBitWidth())
14954 size = size.zext(index.getBitWidth());
14960 if (AllowOnePastEnd ? index.ule(size) : index.ult(size))
14967 SourceLocation RBracketLoc =
SourceMgr.getSpellingLoc(
14969 if (
SourceMgr.isInSystemHeader(RBracketLoc)) {
14970 SourceLocation IndexLoc =
14972 if (
SourceMgr.isWrittenInSameFile(RBracketLoc, IndexLoc))
14977 unsigned DiagID = ASE ? diag::warn_array_index_exceeds_bounds
14978 : diag::warn_ptr_arith_exceeds_bounds;
14979 unsigned CastMsg = (!ASE || BaseType == EffectiveType) ? 0 : 1;
14980 QualType CastMsgTy = ASE ? ASE->
getLHS()->
getType() : QualType();
14984 << index << ArrayTy->
desugar() << CastMsg
14987 unsigned DiagID = diag::warn_array_index_precedes_bounds;
14989 DiagID = diag::warn_ptr_arith_precedes_bounds;
14990 if (index.isNegative()) index = -index;
14997 const NamedDecl *ND =
nullptr;
14999 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
15001 if (
const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
15003 if (
const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
15004 ND = ME->getMemberDecl();
15008 PDiag(diag::note_array_declared_here) << ND);
15011void Sema::CheckArrayAccess(
const Expr *
expr) {
15012 int AllowOnePastEnd = 0;
15014 expr =
expr->IgnoreParenImpCasts();
15015 switch (
expr->getStmtClass()) {
15016 case Stmt::ArraySubscriptExprClass: {
15019 AllowOnePastEnd > 0);
15023 case Stmt::MemberExprClass: {
15027 case Stmt::ArraySectionExprClass: {
15033 nullptr, AllowOnePastEnd > 0);
15036 case Stmt::UnaryOperatorClass: {
15052 case Stmt::ConditionalOperatorClass: {
15054 if (
const Expr *lhs = cond->
getLHS())
15055 CheckArrayAccess(lhs);
15056 if (
const Expr *rhs = cond->
getRHS())
15057 CheckArrayAccess(rhs);
15060 case Stmt::CXXOperatorCallExprClass: {
15062 for (
const auto *Arg : OCE->arguments())
15063 CheckArrayAccess(Arg);
15073 Expr *RHS,
bool isProperty) {
15085 S.
Diag(Loc, diag::warn_arc_literal_assign)
15087 << (isProperty ? 0 : 1)
15095 Expr *RHS,
bool isProperty) {
15098 if (
cast->getCastKind() == CK_ARCConsumeObject) {
15099 S.
Diag(Loc, diag::warn_arc_retained_assign)
15101 << (isProperty ? 0 : 1)
15105 RHS =
cast->getSubExpr();
15147 if (!
Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
15176 if (
cast->getCastKind() == CK_ARCConsumeObject) {
15177 Diag(Loc, diag::warn_arc_retained_property_assign)
15181 RHS =
cast->getSubExpr();
15204 bool StmtLineInvalid;
15205 unsigned StmtLine = SourceMgr.getPresumedLineNumber(StmtLoc,
15207 if (StmtLineInvalid)
15210 bool BodyLineInvalid;
15211 unsigned BodyLine = SourceMgr.getSpellingLineNumber(Body->
getSemiLoc(),
15213 if (BodyLineInvalid)
15217 if (StmtLine != BodyLine)
15232 const NullStmt *NBody = dyn_cast<NullStmt>(Body);
15241 Diag(NBody->
getSemiLoc(), diag::note_empty_body_on_separate_line);
15245 const Stmt *PossibleBody) {
15251 if (
const ForStmt *FS = dyn_cast<ForStmt>(S)) {
15252 StmtLoc = FS->getRParenLoc();
15253 Body = FS->getBody();
15254 DiagID = diag::warn_empty_for_body;
15255 }
else if (
const WhileStmt *WS = dyn_cast<WhileStmt>(S)) {
15256 StmtLoc = WS->getRParenLoc();
15257 Body = WS->getBody();
15258 DiagID = diag::warn_empty_while_body;
15263 const NullStmt *NBody = dyn_cast<NullStmt>(Body);
15287 if (!ProbableTypo) {
15288 bool BodyColInvalid;
15289 unsigned BodyCol =
SourceMgr.getPresumedColumnNumber(
15291 if (BodyColInvalid)
15294 bool StmtColInvalid;
15297 if (StmtColInvalid)
15300 if (BodyCol > StmtCol)
15301 ProbableTypo =
true;
15304 if (ProbableTypo) {
15306 Diag(NBody->
getSemiLoc(), diag::note_empty_body_on_separate_line);
15314 if (
Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess, OpLoc))
15326 if (
const auto *CE = dyn_cast<CallExpr>(RHSExpr);
15328 RHSExpr = CE->
getArg(0);
15329 else if (
const auto *CXXSCE = dyn_cast<CXXStaticCastExpr>(RHSExpr);
15330 CXXSCE && CXXSCE->isXValue())
15331 RHSExpr = CXXSCE->getSubExpr();
15335 const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
15336 const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);
15339 if (LHSDeclRef && RHSDeclRef) {
15346 auto D =
Diag(OpLoc, diag::warn_self_move)
15362 const Expr *LHSBase = LHSExpr;
15363 const Expr *RHSBase = RHSExpr;
15364 const MemberExpr *LHSME = dyn_cast<MemberExpr>(LHSExpr);
15365 const MemberExpr *RHSME = dyn_cast<MemberExpr>(RHSExpr);
15366 if (!LHSME || !RHSME)
15369 while (LHSME && RHSME) {
15376 LHSME = dyn_cast<MemberExpr>(LHSBase);
15377 RHSME = dyn_cast<MemberExpr>(RHSBase);
15380 LHSDeclRef = dyn_cast<DeclRefExpr>(LHSBase);
15381 RHSDeclRef = dyn_cast<DeclRefExpr>(RHSBase);
15382 if (LHSDeclRef && RHSDeclRef) {
15389 Diag(OpLoc, diag::warn_self_move)
15396 Diag(OpLoc, diag::warn_self_move)
15420 bool AreUnionMembers =
false) {
15424 assert(((Field1Parent->isStructureOrClassType() &&
15425 Field2Parent->isStructureOrClassType()) ||
15426 (Field1Parent->isUnionType() && Field2Parent->isUnionType())) &&
15427 "Can't evaluate layout compatibility between a struct field and a "
15429 assert(((!AreUnionMembers && Field1Parent->isStructureOrClassType()) ||
15430 (AreUnionMembers && Field1Parent->isUnionType())) &&
15431 "AreUnionMembers should be 'true' for union fields (only).");
15445 if (Bits1 != Bits2)
15449 if (Field1->
hasAttr<clang::NoUniqueAddressAttr>() ||
15450 Field2->
hasAttr<clang::NoUniqueAddressAttr>())
15453 if (!AreUnionMembers &&
15465 if (
const CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(RD1))
15466 RD1 = D1CXX->getStandardLayoutBaseWithFields();
15468 if (
const CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(RD2))
15469 RD2 = D2CXX->getStandardLayoutBaseWithFields();
15474 return isLayoutCompatible(C, F1, F2);
15485 for (
auto *Field1 : RD1->
fields()) {
15486 auto I = UnmatchedFields.begin();
15487 auto E = UnmatchedFields.end();
15489 for ( ; I != E; ++I) {
15491 bool Result = UnmatchedFields.erase(*I);
15501 return UnmatchedFields.empty();
15527 if (
C.hasSameType(T1, T2))
15536 if (TC1 == Type::Enum)
15538 if (TC1 == Type::Record) {
15557 QualType BaseT =
Base->getType()->getCanonicalTypeUnqualified();
15588 const ValueDecl **VD, uint64_t *MagicValue,
15589 bool isConstantEvaluated) {
15597 case Stmt::UnaryOperatorClass: {
15606 case Stmt::DeclRefExprClass: {
15612 case Stmt::IntegerLiteralClass: {
15614 llvm::APInt MagicValueAPInt = IL->
getValue();
15615 if (MagicValueAPInt.getActiveBits() <= 64) {
15616 *MagicValue = MagicValueAPInt.getZExtValue();
15622 case Stmt::BinaryConditionalOperatorClass:
15623 case Stmt::ConditionalOperatorClass: {
15628 isConstantEvaluated)) {
15638 case Stmt::BinaryOperatorClass: {
15641 TypeExpr = BO->
getRHS();
15671 const llvm::DenseMap<Sema::TypeTagMagicValue, Sema::TypeTagData>
15674 bool isConstantEvaluated) {
15675 FoundWrongKind =
false;
15680 uint64_t MagicValue;
15682 if (!
FindTypeTagExpr(TypeExpr, Ctx, &VD, &MagicValue, isConstantEvaluated))
15686 if (TypeTagForDatatypeAttr *I = VD->
getAttr<TypeTagForDatatypeAttr>()) {
15687 if (I->getArgumentKind() != ArgumentKind) {
15688 FoundWrongKind =
true;
15691 TypeInfo.Type = I->getMatchingCType();
15692 TypeInfo.LayoutCompatible = I->getLayoutCompatible();
15693 TypeInfo.MustBeNull = I->getMustBeNull();
15704 MagicValues->find(std::make_pair(ArgumentKind, MagicValue));
15705 if (I == MagicValues->end())
15714 bool LayoutCompatible,
15716 if (!TypeTagForDatatypeMagicValues)
15717 TypeTagForDatatypeMagicValues.reset(
15718 new llvm::DenseMap<TypeTagMagicValue, TypeTagData>);
15721 (*TypeTagForDatatypeMagicValues)[Magic] =
15737 return (T1Kind == BuiltinType::SChar && T2Kind == BuiltinType::Char_S) ||
15738 (T1Kind == BuiltinType::UChar && T2Kind == BuiltinType::Char_U) ||
15739 (T1Kind == BuiltinType::Char_U && T2Kind == BuiltinType::UChar) ||
15740 (T1Kind == BuiltinType::Char_S && T2Kind == BuiltinType::SChar);
15743void Sema::CheckArgumentWithTypeTag(
const ArgumentWithTypeTagAttr *
Attr,
15746 const IdentifierInfo *ArgumentKind = Attr->getArgumentKind();
15747 bool IsPointerAttr = Attr->getIsPointer();
15750 unsigned TypeTagIdxAST = Attr->getTypeTagIdx().getASTIndex();
15751 if (TypeTagIdxAST >= ExprArgs.size()) {
15752 Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
15753 << 0 << Attr->getTypeTagIdx().getSourceIndex();
15756 const Expr *TypeTagExpr = ExprArgs[TypeTagIdxAST];
15757 bool FoundWrongKind;
15760 TypeTagForDatatypeMagicValues.get(), FoundWrongKind,
15762 if (FoundWrongKind)
15764 diag::warn_type_tag_for_datatype_wrong_kind)
15770 unsigned ArgumentIdxAST = Attr->getArgumentIdx().getASTIndex();
15771 if (ArgumentIdxAST >= ExprArgs.size()) {
15772 Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
15773 << 1 << Attr->getArgumentIdx().getSourceIndex();
15776 const Expr *ArgumentExpr = ExprArgs[ArgumentIdxAST];
15777 if (IsPointerAttr) {
15779 if (
const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgumentExpr))
15780 if (ICE->getType()->isVoidPointerType() &&
15781 ICE->getCastKind() == CK_BitCast)
15782 ArgumentExpr = ICE->getSubExpr();
15784 QualType ArgumentType = ArgumentExpr->
getType();
15790 if (TypeInfo.MustBeNull) {
15795 diag::warn_type_safety_null_pointer_required)
15803 QualType RequiredType = TypeInfo.Type;
15805 RequiredType =
Context.getPointerType(RequiredType);
15807 bool mismatch =
false;
15808 if (!TypeInfo.LayoutCompatible) {
15809 mismatch = !
Context.hasSameType(ArgumentType, RequiredType);
15830 Diag(ArgumentExpr->
getExprLoc(), diag::warn_type_safety_type_mismatch)
15831 << ArgumentType << ArgumentKind
15832 << TypeInfo.LayoutCompatible << RequiredType
15850 Diag(m.E->getBeginLoc(), diag::warn_taking_address_of_packed_member)
15858 if (!
T->isPointerType() && !
T->isIntegerType() && !
T->isDependentType())
15864 auto &MisalignedMembersForExpr =
15866 auto *MA = llvm::find(MisalignedMembersForExpr, MisalignedMember(Op));
15867 if (MA != MisalignedMembersForExpr.end() &&
15868 (
T->isDependentType() ||
T->isIntegerType() ||
15869 (
T->isPointerType() && (
T->getPointeeType()->isIncompleteType() ||
15871 T->getPointeeType()) <= MA->Alignment))))
15872 MisalignedMembersForExpr.erase(MA);
15881 const auto *ME = dyn_cast<MemberExpr>(E);
15893 bool AnyIsPacked =
false;
15895 QualType BaseType = ME->getBase()->getType();
15896 if (BaseType->isDependentType())
15900 auto *RD = BaseType->castAsRecordDecl();
15905 auto *FD = dyn_cast<FieldDecl>(MD);
15911 AnyIsPacked || (RD->
hasAttr<PackedAttr>() || MD->
hasAttr<PackedAttr>());
15912 ReverseMemberChain.push_back(FD);
15915 ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParens());
15917 assert(TopME &&
"We did not compute a topmost MemberExpr!");
15924 const auto *DRE = dyn_cast<DeclRefExpr>(TopBase);
15935 if (ExpectedAlignment.
isOne())
15940 for (
const FieldDecl *FD : llvm::reverse(ReverseMemberChain))
15941 Offset +=
Context.toCharUnitsFromBits(
Context.getFieldOffset(FD));
15945 Context.getCanonicalTagType(ReverseMemberChain.back()->getParent()));
15949 if (DRE && !TopME->
isArrow()) {
15952 CompleteObjectAlignment =
15953 std::max(CompleteObjectAlignment,
Context.getDeclAlign(VD));
15957 if (!Offset.isMultipleOf(ExpectedAlignment) ||
15960 CompleteObjectAlignment < ExpectedAlignment) {
15971 for (
FieldDecl *FDI : ReverseMemberChain) {
15972 if (FDI->hasAttr<PackedAttr>() ||
15973 FDI->getParent()->hasAttr<PackedAttr>()) {
15975 Alignment = std::min(
Context.getTypeAlignInChars(FD->
getType()),
15981 assert(FD &&
"We did not find a packed FieldDecl!");
15982 Action(E, FD->
getParent(), FD, Alignment);
15986void Sema::CheckAddressOfPackedMember(
Expr *rhs) {
15987 using namespace std::placeholders;
15990 rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*
this), _1,
16026bool Sema::BuiltinElementwiseMath(
CallExpr *TheCall,
16027 EltwiseBuiltinArgTyRestriction ArgTyRestr) {
16040 if (
auto *VecTy0 = (*Res)->getAs<
VectorType>())
16041 TheCall->
setType(VecTy0->getElementType());
16054 return S.
Diag(Loc, diag::err_conv_mixed_enum_types)
16071 assert(!Args.empty() &&
"Should have at least one argument.");
16073 Expr *Arg0 = Args.front();
16076 auto EmitError = [&](
Expr *ArgI) {
16078 diag::err_typecheck_call_different_arg_types)
16079 << Arg0->
getType() << ArgI->getType();
16084 for (
Expr *ArgI : Args.drop_front())
16095 for (
Expr *ArgI : Args.drop_front()) {
16096 const auto *VecI = ArgI->getType()->getAs<
VectorType>();
16099 VecI->getElementType()) ||
16100 Vec0->getNumElements() != VecI->getNumElements()) {
16109std::optional<QualType>
16113 return std::nullopt;
16117 return std::nullopt;
16120 for (
int I = 0; I < 2; ++I) {
16124 return std::nullopt;
16125 Args[I] = Converted.
get();
16132 return std::nullopt;
16135 return std::nullopt;
16137 TheCall->
setArg(0, Args[0]);
16138 TheCall->
setArg(1, Args[1]);
16149 TheCall->
getArg(1), Loc) ||
16151 TheCall->
getArg(2), Loc))
16155 for (
int I = 0; I < 3; ++I) {
16160 Args[I] = Converted.
get();
16163 int ArgOrdinal = 1;
16164 for (
Expr *Arg : Args) {
16166 ArgTyRestr, ArgOrdinal++))
16173 for (
int I = 0; I < 3; ++I)
16174 TheCall->
setArg(I, Args[I]);
16180bool Sema::PrepareBuiltinReduceMathOneArgCall(
CallExpr *TheCall) {
16192bool Sema::BuiltinNonDeterministicValue(
CallExpr *TheCall) {
16201 diag::err_builtin_invalid_arg_type)
16202 << 1 << 2 << 1 << 1 << TyArg;
16216 Expr *Matrix = MatrixArg.
get();
16218 auto *MType = Matrix->
getType()->
getAs<ConstantMatrixType>();
16221 << 1 << 3 << 0 << 0
16228 QualType ResultType =
Context.getConstantMatrixType(
16229 MType->getElementType(), MType->getNumColumns(), MType->getNumRows());
16232 TheCall->
setType(ResultType);
16235 TheCall->
setArg(0, Matrix);
16240static std::optional<unsigned>
16248 uint64_t
Dim =
Value->getZExtValue();
16267 unsigned PtrArgIdx = 0;
16268 Expr *PtrExpr = TheCall->
getArg(PtrArgIdx);
16269 Expr *RowsExpr = TheCall->
getArg(1);
16270 Expr *ColumnsExpr = TheCall->
getArg(2);
16271 Expr *StrideExpr = TheCall->
getArg(3);
16273 bool ArgError =
false;
16280 PtrExpr = PtrConv.
get();
16281 TheCall->
setArg(0, PtrExpr);
16288 auto *PtrTy = PtrExpr->
getType()->
getAs<PointerType>();
16289 QualType ElementTy;
16292 << PtrArgIdx + 1 << 0 << 5 << 0
16296 ElementTy = PtrTy->getPointeeType().getUnqualifiedType();
16300 << PtrArgIdx + 1 << 0 << 5
16307 auto ApplyArgumentConversions = [
this](Expr *E) {
16316 ExprResult RowsConv = ApplyArgumentConversions(RowsExpr);
16318 RowsExpr = RowsConv.
get();
16319 TheCall->
setArg(1, RowsExpr);
16321 RowsExpr =
nullptr;
16323 ExprResult ColumnsConv = ApplyArgumentConversions(ColumnsExpr);
16325 ColumnsExpr = ColumnsConv.
get();
16326 TheCall->
setArg(2, ColumnsExpr);
16328 ColumnsExpr =
nullptr;
16339 std::optional<unsigned> MaybeRows;
16343 std::optional<unsigned> MaybeColumns;
16348 ExprResult StrideConv = ApplyArgumentConversions(StrideExpr);
16351 StrideExpr = StrideConv.
get();
16352 TheCall->
setArg(3, StrideExpr);
16355 if (std::optional<llvm::APSInt>
Value =
16358 if (Stride < *MaybeRows) {
16360 diag::err_builtin_matrix_stride_too_small);
16366 if (ArgError || !MaybeRows || !MaybeColumns)
16370 Context.getConstantMatrixType(ElementTy, *MaybeRows, *MaybeColumns));
16379 unsigned PtrArgIdx = 1;
16380 Expr *MatrixExpr = TheCall->
getArg(0);
16381 Expr *PtrExpr = TheCall->
getArg(PtrArgIdx);
16382 Expr *StrideExpr = TheCall->
getArg(2);
16384 bool ArgError =
false;
16390 MatrixExpr = MatrixConv.
get();
16391 TheCall->
setArg(0, MatrixExpr);
16398 auto *MatrixTy = MatrixExpr->
getType()->
getAs<ConstantMatrixType>();
16401 << 1 << 3 << 0 << 0 << MatrixExpr->
getType();
16409 PtrExpr = PtrConv.
get();
16410 TheCall->
setArg(1, PtrExpr);
16418 auto *PtrTy = PtrExpr->
getType()->
getAs<PointerType>();
16421 << PtrArgIdx + 1 << 0 << 5 << 0
16425 QualType ElementTy = PtrTy->getPointeeType();
16427 Diag(PtrExpr->
getBeginLoc(), diag::err_builtin_matrix_store_to_const);
16432 !
Context.hasSameType(ElementTy, MatrixTy->getElementType())) {
16434 diag::err_builtin_matrix_pointer_arg_mismatch)
16435 << ElementTy << MatrixTy->getElementType();
16450 StrideExpr = StrideConv.
get();
16451 TheCall->
setArg(2, StrideExpr);
16456 if (std::optional<llvm::APSInt>
Value =
16459 if (Stride < MatrixTy->getNumRows()) {
16461 diag::err_builtin_matrix_stride_too_small);
16481 if (!Caller || !Caller->
hasAttr<EnforceTCBAttr>())
16486 llvm::StringSet<> CalleeTCBs;
16487 for (
const auto *A : Callee->specific_attrs<EnforceTCBAttr>())
16488 CalleeTCBs.insert(A->getTCBName());
16489 for (
const auto *A : Callee->specific_attrs<EnforceTCBLeafAttr>())
16490 CalleeTCBs.insert(A->getTCBName());
16494 for (
const auto *A : Caller->
specific_attrs<EnforceTCBAttr>()) {
16495 StringRef CallerTCB = A->getTCBName();
16496 if (CalleeTCBs.count(CallerTCB) == 0) {
16497 this->
Diag(CallExprLoc, diag::warn_tcb_enforcement_violation)
16498 << 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
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
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
const LangOptions & getLangOpts() const
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
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.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
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.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
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 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.