Skip to content

[Clang] Make the result type of sizeof/pointer subtraction/size_t lit… #136542

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
Closed
7 changes: 6 additions & 1 deletion clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
#include "clang/Basic/HLSLIntangibleTypes.def"

// Cache size_t and ptrdiff_t typedefs
// (C99 7.17), defined in <stddef.h>.
mutable QualType PtrDiffTy;
mutable QualType UnsignedSizeTy;

// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
mutable QualType AutoDeductTy; // Deduction against 'auto'.
mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'.
Expand Down Expand Up @@ -1941,7 +1946,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// <stddef.h>.
///
/// The sizeof operator requires this (C99 6.5.3.4p4).
CanQualType getSizeType() const;
QualType getSizeType() const;

/// Return the unique signed counterpart of
/// the integer type corresponding to size_t.
Expand Down
54 changes: 51 additions & 3 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6666,11 +6666,50 @@ QualType ASTContext::getTagDeclType(const TagDecl *Decl) const {
return getTypeDeclType(const_cast<TagDecl*>(Decl));
}

static QualType LookupCGlobalCXXStdNSTypedef(const ASTContext &Ctx,
StringRef DefName,
CanQualType const &CanType) {
DeclContextLookupResult Lookup;
if (Ctx.getLangOpts().C99) {
Lookup = Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get(DefName));
} else if (Ctx.getLangOpts().CPlusPlus) {
const NamespaceDecl *StdNS = nullptr;
auto LookupStdNS =
Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get("std"));
if (!LookupStdNS.empty()) {
StdNS = dyn_cast<NamespaceDecl>(LookupStdNS.front());
}
if (StdNS) {
Lookup = StdNS->lookup(&Ctx.Idents.get(DefName));
} else {
Lookup = Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get(DefName));
}
}
if (!Lookup.empty()) {
if (auto *TD = dyn_cast<TypedefNameDecl>(Lookup.front())) {
auto Result = Ctx.getTypeDeclType(TD);
if (!Result.isNull() && Ctx.hasSameType(Result, CanType) &&
Ctx.getTypeAlign(Result) == Ctx.getTypeAlign(CanType)) {
return Result;
}
}
}
return QualType();
}

/// getSizeType - Return the unique type for "size_t" (C99 7.17), the result
/// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and
/// needs to agree with the definition in <stddef.h>.
CanQualType ASTContext::getSizeType() const {
return getFromTargetType(Target->getSizeType());
QualType ASTContext::getSizeType() const {
if (UnsignedSizeTy.isNull()) {
auto CanType = getFromTargetType(Target->getSizeType());
if (auto TypeDef = LookupCGlobalCXXStdNSTypedef(*this, "size_t", CanType);
TypeDef.isNull())
return CanType;
else
UnsignedSizeTy = TypeDef;
}
return UnsignedSizeTy;
}

/// Return the unique signed counterpart of the integer type
Expand Down Expand Up @@ -6714,7 +6753,16 @@ QualType ASTContext::getUIntPtrType() const {
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType ASTContext::getPointerDiffType() const {
return getFromTargetType(Target->getPtrDiffType(LangAS::Default));
if (PtrDiffTy.isNull()) {
auto CanType = getFromTargetType(Target->getPtrDiffType(LangAS::Default));
if (auto TypeDef =
LookupCGlobalCXXStdNSTypedef(*this, "ptrdiff_t", CanType);
TypeDef.isNull())
return CanType;
else
PtrDiffTy = TypeDef;
}
return PtrDiffTy;
}

/// Return the unique unsigned counterpart of "ptrdiff_t"
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,10 @@ static void appendParameterTypes(const CodeGenTypes &CGT,
assert(ExtInfos.size() == FPT->getNumParams());
for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) {
prefix.push_back(FPT->getParamType(I));
if (ExtInfos[I].hasPassObjectSize())
prefix.push_back(CGT.getContext().getSizeType());
if (ExtInfos[I].hasPassObjectSize()) {
auto &Ctx = CGT.getContext();
prefix.push_back(Ctx.getCanonicalType(Ctx.getSizeType()));
}
}

addExtParameterInfosForCall(paramInfos, FPT.getTypePtr(), PrefixSize,
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGCoroutine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1002,14 +1002,14 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
}
case llvm::Intrinsic::coro_size: {
auto &Context = getContext();
CanQualType SizeTy = Context.getSizeType();
CanQualType SizeTy = Context.getCanonicalType(Context.getSizeType());
llvm::IntegerType *T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_size, T);
return RValue::get(Builder.CreateCall(F));
}
case llvm::Intrinsic::coro_align: {
auto &Context = getContext();
CanQualType SizeTy = Context.getSizeType();
CanQualType SizeTy = Context.getCanonicalType(Context.getSizeType());
llvm::IntegerType *T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_align, T);
return RValue::get(Builder.CreateCall(F));
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGObjCMac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ class ObjCCommonTypesHelper {
SmallVector<CanQualType, 5> Params;
Params.push_back(Ctx.VoidPtrTy);
Params.push_back(Ctx.VoidPtrTy);
Params.push_back(Ctx.getSizeType());
Params.push_back(Ctx.getCanonicalType(Ctx.getSizeType()));
Params.push_back(Ctx.BoolTy);
Params.push_back(Ctx.BoolTy);
llvm::FunctionType *FTy = Types.GetFunctionType(
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4025,9 +4025,10 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {

// Does it fit in size_t?
if (ResultVal.isIntN(SizeTSize)) {
// Does it fit in ssize_t?
// Does it fit in signed size_t?
if (!Literal.isUnsigned && ResultVal[SizeTSize - 1] == 0)
Ty = Context.getSignedSizeType();
// treat it as ptrdiff_t to distinguish it from long/long long
Ty = Context.getPointerDiffType();
else if (AllowUnsigned)
Ty = Context.getSizeType();
Width = SizeTSize;
Expand Down Expand Up @@ -11353,7 +11354,8 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
}
}

if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
if (CompLHSTy)
*CompLHSTy = LHS.get()->getType();
return Context.getPointerDiffType();
}
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ ProgramStateRef VLASizeChecker::checkVLA(CheckerContext &C,

ASTContext &Ctx = C.getASTContext();
SValBuilder &SVB = C.getSValBuilder();
CanQualType SizeTy = Ctx.getSizeType();
CanQualType SizeTy = Ctx.getCanonicalType(Ctx.getSizeType());
uint64_t SizeMax =
SVB.getBasicValueFactory().getMaxValue(SizeTy)->getZExtValue();

Expand Down
16 changes: 0 additions & 16 deletions clang/test/Analysis/std-c-library-functions-arg-constraints.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,22 +320,6 @@ void test_buf_size_concrete_with_multiplication(void) {
// bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 2)}} \
// bugpath-note{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 2)}}
}
void test_buf_size_symbolic_with_multiplication(size_t s) {
short buf[3];
__buf_size_arg_constraint_mul(buf, s, sizeof(short));
clang_analyzer_eval(s * sizeof(short) <= 6); // \
// report-warning{{TRUE}} \
// bugpath-warning{{TRUE}} \
// bugpath-note{{TRUE}}
}
void test_buf_size_symbolic_and_offset_with_multiplication(size_t s) {
short buf[3];
__buf_size_arg_constraint_mul(buf + 1, s, sizeof(short));
clang_analyzer_eval(s * sizeof(short) <= 4); // \
// report-warning{{TRUE}} \
// bugpath-warning{{TRUE}} \
// bugpath-note{{TRUE}}
}

// The minimum buffer size for this function is set to 10.
int __buf_size_arg_constraint_concrete(const void *);
Expand Down