diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 3c78833a3f069..d18dc1b4a13f5 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1218,6 +1218,11 @@ class ASTContext : public RefCountedBase { #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 . + 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 &&'. @@ -1941,7 +1946,7 @@ class ASTContext : public RefCountedBase { /// . /// /// 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. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2836d68b05ff6..4f1c837c8b49d 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6666,11 +6666,50 @@ QualType ASTContext::getTagDeclType(const TagDecl *Decl) const { return getTypeDeclType(const_cast(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(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(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 . -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 @@ -6714,7 +6753,16 @@ QualType ASTContext::getUIntPtrType() const { /// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17) /// defined in . 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" diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 8cb27420dd911..307c8ae2a5039 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -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, diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 0fc488e98aaf0..8d8807135b921 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -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)); diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 1c23a8b4db918..6710f9b62ae8e 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -285,7 +285,7 @@ class ObjCCommonTypesHelper { SmallVector 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( diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 01a021443c94f..f3f2f5a928903 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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; @@ -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(); } } diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index ba91b3632abbf..bdae5474fe450 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -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(); diff --git a/clang/test/Analysis/std-c-library-functions-arg-constraints.c b/clang/test/Analysis/std-c-library-functions-arg-constraints.c index 0b817dda98c72..5bb179d897c89 100644 --- a/clang/test/Analysis/std-c-library-functions-arg-constraints.c +++ b/clang/test/Analysis/std-c-library-functions-arg-constraints.c @@ -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 *);