diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp | 423 |
1 files changed, 328 insertions, 95 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 1a8ab6e..59d51f7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/Analysis/Analyses/FormatString.h" @@ -111,6 +112,39 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) { return false; } +static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) { + if (checkArgCount(S, TheCall, 3)) + return true; + + // First two arguments should be integers. + for (unsigned I = 0; I < 2; ++I) { + Expr *Arg = TheCall->getArg(I); + QualType Ty = Arg->getType(); + if (!Ty->isIntegerType()) { + S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_int) + << Ty << Arg->getSourceRange(); + return true; + } + } + + // Third argument should be a pointer to a non-const integer. + // IRGen correctly handles volatile, restrict, and address spaces, and + // the other qualifiers aren't possible. + { + Expr *Arg = TheCall->getArg(2); + QualType Ty = Arg->getType(); + const auto *PtrTy = Ty->getAs<PointerType>(); + if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() && + !PtrTy->getPointeeType().isConstQualified())) { + S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_ptr_int) + << Ty << Arg->getSourceRange(); + return true; + } + } + + return false; +} + static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl, CallExpr *TheCall, unsigned SizeIdx, unsigned DstSizeIdx) { @@ -440,6 +474,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__sync_swap_8: case Builtin::BI__sync_swap_16: return SemaBuiltinAtomicOverloaded(TheCallResult); + case Builtin::BI__builtin_nontemporal_load: + case Builtin::BI__builtin_nontemporal_store: + return SemaBuiltinNontemporalOverloaded(TheCallResult); #define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ case Builtin::BI##ID: \ @@ -453,6 +490,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinAddressof(*this, TheCall)) return ExprError(); break; + case Builtin::BI__builtin_add_overflow: + case Builtin::BI__builtin_sub_overflow: + case Builtin::BI__builtin_mul_overflow: + if (SemaBuiltinOverflow(*this, TheCall)) + return ExprError(); + break; case Builtin::BI__builtin_operator_new: case Builtin::BI__builtin_operator_delete: if (!getLangOpts().CPlusPlus) { @@ -525,7 +568,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, // Since the target specific builtins for each arch overlap, only check those // of the arch we are compiling for. - if (BuiltinID >= Builtin::FirstTSBuiltin) { + if (Context.BuiltinInfo.isTSBuiltin(BuiltinID)) { switch (Context.getTargetInfo().getTriple().getArch()) { case llvm::Triple::arm: case llvm::Triple::armeb: @@ -1027,12 +1070,34 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, return SemaBuiltinConstantArgRange(TheCall, i, l, u); } +/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *). +/// This checks that the target supports __builtin_cpu_supports and +/// that the string argument is constant and valid. +static bool SemaBuiltinCpuSupports(Sema &S, CallExpr *TheCall) { + Expr *Arg = TheCall->getArg(0); + + // Check if the argument is a string literal. + if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) + return S.Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal) + << Arg->getSourceRange(); + + // Check the contents of the string. + StringRef Feature = + cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); + if (!S.Context.getTargetInfo().validateCpuSupports(Feature)) + return S.Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports) + << Arg->getSourceRange(); + return false; +} + bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { unsigned i = 0, l = 0, u = 0; switch (BuiltinID) { default: return false; case X86::BI__builtin_cpu_supports: - return SemaBuiltinCpuSupports(TheCall); + return SemaBuiltinCpuSupports(*this, TheCall); + case X86::BI__builtin_ms_va_start: + return SemaBuiltinMSVAStart(TheCall); case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break; case X86::BI__builtin_ia32_sha1rnds4: i = 2, l = 0; u = 3; break; case X86::BI__builtin_ia32_vpermil2pd: @@ -1115,8 +1180,7 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, /// Checks if a the given expression evaluates to null. /// /// \brief Returns true if the value evaluates to null. -static bool CheckNonNullExpr(Sema &S, - const Expr *Expr) { +static bool CheckNonNullExpr(Sema &S, const Expr *Expr) { // If the expression has non-null type, it doesn't evaluate to null. if (auto nullability = Expr->IgnoreImplicit()->getType()->getNullability(S.Context)) { @@ -1145,7 +1209,8 @@ static void CheckNonNullArgument(Sema &S, const Expr *ArgExpr, SourceLocation CallSiteLoc) { if (CheckNonNullExpr(S, ArgExpr)) - S.Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); + S.DiagRuntimeBehavior(CallSiteLoc, ArgExpr, + S.PDiag(diag::warn_null_arg) << ArgExpr->getSourceRange()); } bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) { @@ -1638,6 +1703,12 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, return ExprError(); } ValType = AtomTy->getAs<AtomicType>()->getValueType(); + } else if (Form != Load && Op != AtomicExpr::AO__atomic_load) { + if (ValType.isConstQualified()) { + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_pointer) + << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } } // For an arithmetic operation, the implied arithmetic must be well-formed. @@ -1675,9 +1746,6 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, return ExprError(); } - // FIXME: For any builtin other than a load, the ValType must not be - // const-qualified. - switch (ValType.getObjCLifetime()) { case Qualifiers::OCL_None: case Qualifiers::OCL_ExplicitNone: @@ -1710,6 +1778,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, if (!IsC11 && !IsN) ByValType = Ptr->getType(); + // FIXME: __atomic_load allows the first argument to be a a pointer to const + // but not the second argument. We need to manually remove possible const + // qualifiers. + // The first argument --- the pointer --- has a fixed type; we // deduce the types of the rest of the arguments accordingly. Walk // the remaining arguments, converting them to the deduced value type. @@ -1729,8 +1801,17 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, Ty = ByValType; else if (Form == Arithmetic) Ty = Context.getPointerDiffType(); - else - Ty = Context.getPointerType(ValType.getUnqualifiedType()); + else { + Expr *ValArg = TheCall->getArg(i); + unsigned AS = 0; + // Keep address space of non-atomic pointer type. + if (const PointerType *PtrTy = + ValArg->getType()->getAs<PointerType>()) { + AS = PtrTy->getPointeeType().getAddressSpace(); + } + Ty = Context.getPointerType( + Context.getAddrSpaceQualType(ValType.getUnqualifiedType(), AS)); + } break; case 2: // The third argument to compare_exchange / GNU exchange is a @@ -2142,7 +2223,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // Get the decl for the concrete builtin from this, we can tell what the // concrete integer type we should convert to is. unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex]; - const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID); + const char *NewBuiltinName = Context.BuiltinInfo.getName(NewBuiltinID); FunctionDecl *NewBuiltinDecl; if (NewBuiltinID == BuiltinID) NewBuiltinDecl = FDecl; @@ -2209,6 +2290,78 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { return TheCallResult; } +/// SemaBuiltinNontemporalOverloaded - We have a call to +/// __builtin_nontemporal_store or __builtin_nontemporal_load, which is an +/// overloaded function based on the pointer type of its last argument. +/// +/// This function goes through and does final semantic checking for these +/// builtins. +ExprResult Sema::SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult) { + CallExpr *TheCall = (CallExpr *)TheCallResult.get(); + DeclRefExpr *DRE = + cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); + FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl()); + unsigned BuiltinID = FDecl->getBuiltinID(); + assert((BuiltinID == Builtin::BI__builtin_nontemporal_store || + BuiltinID == Builtin::BI__builtin_nontemporal_load) && + "Unexpected nontemporal load/store builtin!"); + bool isStore = BuiltinID == Builtin::BI__builtin_nontemporal_store; + unsigned numArgs = isStore ? 2 : 1; + + // Ensure that we have the proper number of arguments. + if (checkArgCount(*this, TheCall, numArgs)) + return ExprError(); + + // Inspect the last argument of the nontemporal builtin. This should always + // be a pointer type, from which we imply the type of the memory access. + // Because it is a pointer type, we don't have to worry about any implicit + // casts here. + Expr *PointerArg = TheCall->getArg(numArgs - 1); + ExprResult PointerArgResult = + DefaultFunctionArrayLvalueConversion(PointerArg); + + if (PointerArgResult.isInvalid()) + return ExprError(); + PointerArg = PointerArgResult.get(); + TheCall->setArg(numArgs - 1, PointerArg); + + const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>(); + if (!pointerType) { + Diag(DRE->getLocStart(), diag::err_nontemporal_builtin_must_be_pointer) + << PointerArg->getType() << PointerArg->getSourceRange(); + return ExprError(); + } + + QualType ValType = pointerType->getPointeeType(); + + // Strip any qualifiers off ValType. + ValType = ValType.getUnqualifiedType(); + if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && + !ValType->isBlockPointerType() && !ValType->isFloatingType() && + !ValType->isVectorType()) { + Diag(DRE->getLocStart(), + diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector) + << PointerArg->getType() << PointerArg->getSourceRange(); + return ExprError(); + } + + if (!isStore) { + TheCall->setType(ValType); + return TheCallResult; + } + + ExprResult ValArg = TheCall->getArg(0); + InitializedEntity Entity = InitializedEntity::InitializeParameter( + Context, ValType, /*consume*/ false); + ValArg = PerformCopyInitialization(Entity, SourceLocation(), ValArg); + if (ValArg.isInvalid()) + return ExprError(); + + TheCall->setArg(0, ValArg.get()); + TheCall->setType(Context.VoidTy); + return TheCallResult; +} + /// CheckObjCString - Checks that the argument to the builtin /// CFString constructor is correct /// Note: It might also make sense to do the UTF-16 conversion here (would @@ -2241,9 +2394,10 @@ bool Sema::CheckObjCString(Expr *Arg) { return false; } -/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity. -/// Emit an error and return true on failure, return false on success. -bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { +/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' +/// for validity. Emit an error and return true on failure; return false +/// on success. +bool Sema::SemaBuiltinVAStartImpl(CallExpr *TheCall) { Expr *Fn = TheCall->getCallee(); if (TheCall->getNumArgs() > 2) { Diag(TheCall->getArg(2)->getLocStart(), @@ -2321,6 +2475,48 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { return false; } +/// Check the arguments to '__builtin_va_start' for validity, and that +/// it was called from a function of the native ABI. +/// Emit an error and return true on failure; return false on success. +bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { + // On x86-64 Unix, don't allow this in Win64 ABI functions. + // On x64 Windows, don't allow this in System V ABI functions. + // (Yes, that means there's no corresponding way to support variadic + // System V ABI functions on Windows.) + if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64) { + unsigned OS = Context.getTargetInfo().getTriple().getOS(); + clang::CallingConv CC = CC_C; + if (const FunctionDecl *FD = getCurFunctionDecl()) + CC = FD->getType()->getAs<FunctionType>()->getCallConv(); + if ((OS == llvm::Triple::Win32 && CC == CC_X86_64SysV) || + (OS != llvm::Triple::Win32 && CC == CC_X86_64Win64)) + return Diag(TheCall->getCallee()->getLocStart(), + diag::err_va_start_used_in_wrong_abi_function) + << (OS != llvm::Triple::Win32); + } + return SemaBuiltinVAStartImpl(TheCall); +} + +/// Check the arguments to '__builtin_ms_va_start' for validity, and that +/// it was called from a Win64 ABI function. +/// Emit an error and return true on failure; return false on success. +bool Sema::SemaBuiltinMSVAStart(CallExpr *TheCall) { + // This only makes sense for x86-64. + const llvm::Triple &TT = Context.getTargetInfo().getTriple(); + Expr *Callee = TheCall->getCallee(); + if (TT.getArch() != llvm::Triple::x86_64) + return Diag(Callee->getLocStart(), diag::err_x86_builtin_32_bit_tgt); + // Don't allow this in System V ABI functions. + clang::CallingConv CC = CC_C; + if (const FunctionDecl *FD = getCurFunctionDecl()) + CC = FD->getType()->getAs<FunctionType>()->getCallConv(); + if (CC == CC_X86_64SysV || + (TT.getOS() != llvm::Triple::Win32 && CC != CC_X86_64Win64)) + return Diag(Callee->getLocStart(), + diag::err_ms_va_start_used_in_sysv_function); + return SemaBuiltinVAStartImpl(TheCall); +} + bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) { // void __va_start(va_list *ap, const char *named_addr, size_t slot_size, // const char *named_addr); @@ -2784,26 +2980,6 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, return false; } -/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *). -/// This checks that the target supports __builtin_cpu_supports and -/// that the string argument is constant and valid. -bool Sema::SemaBuiltinCpuSupports(CallExpr *TheCall) { - Expr *Arg = TheCall->getArg(0); - - // Check if the argument is a string literal. - if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) - return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal) - << Arg->getSourceRange(); - - // Check the contents of the string. - StringRef Feature = - cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); - if (!Context.getTargetInfo().validateCpuSupports(Feature)) - return Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports) - << Arg->getSourceRange(); - return false; -} - /// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val). /// This checks that the target supports __builtin_longjmp and /// that val is a constant 1. @@ -4833,7 +5009,7 @@ static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range, } } } else { - FunctionName = S.Context.BuiltinInfo.GetName(AbsKind); + FunctionName = S.Context.BuiltinInfo.getName(AbsKind); HeaderName = S.Context.BuiltinInfo.getHeaderName(AbsKind); if (HeaderName) { @@ -4909,7 +5085,7 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call, // function call. if (ArgType->isUnsignedIntegerType()) { const char *FunctionName = - IsStdAbs ? "std::abs" : Context.BuiltinInfo.GetName(AbsKind); + IsStdAbs ? "std::abs" : Context.BuiltinInfo.getName(AbsKind); Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType; Diag(Call->getExprLoc(), diag::note_remove_abs) << FunctionName @@ -4917,6 +5093,19 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call, return; } + // Taking the absolute value of a pointer is very suspicious, they probably + // wanted to index into an array, dereference a pointer, call a function, etc. + if (ArgType->isPointerType() || ArgType->canDecayToPointerType()) { + unsigned DiagType = 0; + if (ArgType->isFunctionType()) + DiagType = 1; + else if (ArgType->isArrayType()) + DiagType = 2; + + Diag(Call->getExprLoc(), diag::warn_pointer_abs) << DiagType << ArgType; + return; + } + // std::abs has overloads which prevent most of the absolute value problems // from occurring. if (IsStdAbs) @@ -5465,17 +5654,15 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, } if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var. - S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref - : diag::warn_ret_stack_addr) + S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType() << DR->getDecl()->getDeclName() << diagRange; } else if (isa<BlockExpr>(stackE)) { // local block. S.Diag(diagLoc, diag::err_ret_local_block) << diagRange; } else if (isa<AddrLabelExpr>(stackE)) { // address of label. S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange; } else { // local temporary. - S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref - : diag::warn_ret_local_temp_addr) - << diagRange; + S.Diag(diagLoc, diag::warn_ret_local_temp_addr_ref) + << lhsType->isReferenceType() << diagRange; } // Display the "trail" of reference variables that we followed until we @@ -5750,6 +5937,11 @@ do { return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl); } + case Stmt::OMPArraySectionExprClass: { + return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars, + ParentDecl); + } + case Stmt::ConditionalOperatorClass: { // For conditional operators we need to see if either the LHS or RHS are // non-NULL Expr's. If one is non-NULL, we return it. @@ -7083,6 +7275,14 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision); + + } + // ... or possibly if we're increasing rank, too + else if (TargetBT->getKind() > SourceBT->getKind()) { + if (S.SourceMgr.isInSystemMacro(CC)) + return; + + DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_double_promotion); } return; } @@ -7105,20 +7305,24 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } } - // If the target is bool, warn if expr is a function or method call. - if (Target->isSpecificBuiltinType(BuiltinType::Bool) && - isa<CallExpr>(E)) { + // Detect the case where a call result is converted from floating-point to + // to bool, and the final argument to the call is converted from bool, to + // discover this typo: + // + // bool b = fabs(x < 1.0); // should be "bool b = fabs(x) < 1.0;" + // + // FIXME: This is an incredibly special case; is there some more general + // way to detect this class of misplaced-parentheses bug? + if (Target->isBooleanType() && isa<CallExpr>(E)) { // Check last argument of function call to see if it is an // implicit cast from a type matching the type the result // is being cast to. CallExpr *CEx = cast<CallExpr>(E); - unsigned NumArgs = CEx->getNumArgs(); - if (NumArgs > 0) { + if (unsigned NumArgs = CEx->getNumArgs()) { Expr *LastA = CEx->getArg(NumArgs - 1); Expr *InnerE = LastA->IgnoreParenImpCasts(); - const Type *InnerType = - S.Context.getCanonicalType(InnerE->getType()).getTypePtr(); - if (isa<ImplicitCastExpr>(LastA) && (InnerType == Target)) { + if (isa<ImplicitCastExpr>(LastA) && + InnerE->getType()->isBooleanType()) { // Warn on this floating-point to bool conversion DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_floating_point_to_bool); @@ -7301,18 +7505,16 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { CheckImplicitConversion(S, E, T, CC); // Now continue drilling into this expression. - - if (PseudoObjectExpr * POE = dyn_cast<PseudoObjectExpr>(E)) { - if (POE->getResultExpr()) - E = POE->getResultExpr(); - } - - if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) { - if (OVE->getSourceExpr()) - AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC); - return; + + if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) { + // The bound subexpressions in a PseudoObjectExpr are not reachable + // as transitive children. + // FIXME: Use a more uniform representation for this. + for (auto *SE : POE->semantics()) + if (auto *OVE = dyn_cast<OpaqueValueExpr>(SE)) + AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC); } - + // Skip past explicit casts. if (isa<ExplicitCastExpr>(E)) { E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts(); @@ -7372,12 +7574,6 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { } // end anonymous namespace -enum { - AddressOf, - FunctionPointer, - ArrayPointer -}; - // Helper function for Sema::DiagnoseAlwaysNonNullPointer. // Returns true when emitting a warning about taking the address of a reference. static bool CheckForReference(Sema &SemaRef, const Expr *E, @@ -7476,6 +7672,26 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, } } + auto ComplainAboutNonnullParamOrCall = [&](bool IsParam) { + std::string Str; + llvm::raw_string_ostream S(Str); + E->printPretty(S, nullptr, getPrintingPolicy()); + unsigned DiagID = IsCompare ? diag::warn_nonnull_expr_compare + : diag::warn_cast_nonnull_to_bool; + Diag(E->getExprLoc(), DiagID) << IsParam << S.str() + << E->getSourceRange() << Range << IsEqual; + }; + + // If we have a CallExpr that is tagged with returns_nonnull, we can complain. + if (auto *Call = dyn_cast<CallExpr>(E->IgnoreParenImpCasts())) { + if (auto *Callee = Call->getDirectCallee()) { + if (Callee->hasAttr<ReturnsNonNullAttr>()) { + ComplainAboutNonnullParamOrCall(false); + return; + } + } + } + // Expect to find a single Decl. Skip anything more complicated. ValueDecl *D = nullptr; if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) { @@ -7487,40 +7703,38 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, // Weak Decls can be null. if (!D || D->isWeak()) return; - + // Check for parameter decl with nonnull attribute - if (const ParmVarDecl* PV = dyn_cast<ParmVarDecl>(D)) { - if (getCurFunction() && !getCurFunction()->ModifiedNonNullParams.count(PV)) - if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) { - unsigned NumArgs = FD->getNumParams(); - llvm::SmallBitVector AttrNonNull(NumArgs); + if (const auto* PV = dyn_cast<ParmVarDecl>(D)) { + if (getCurFunction() && + !getCurFunction()->ModifiedNonNullParams.count(PV)) { + if (PV->hasAttr<NonNullAttr>()) { + ComplainAboutNonnullParamOrCall(true); + return; + } + + if (const auto *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) { + auto ParamIter = std::find(FD->param_begin(), FD->param_end(), PV); + assert(ParamIter != FD->param_end()); + unsigned ParamNo = std::distance(FD->param_begin(), ParamIter); + for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) { if (!NonNull->args_size()) { - AttrNonNull.set(0, NumArgs); - break; - } - for (unsigned Val : NonNull->args()) { - if (Val >= NumArgs) - continue; - AttrNonNull.set(Val); + ComplainAboutNonnullParamOrCall(true); + return; } - } - if (!AttrNonNull.empty()) - for (unsigned i = 0; i < NumArgs; ++i) - if (FD->getParamDecl(i) == PV && - (AttrNonNull[i] || PV->hasAttr<NonNullAttr>())) { - std::string Str; - llvm::raw_string_ostream S(Str); - E->printPretty(S, nullptr, getPrintingPolicy()); - unsigned DiagID = IsCompare ? diag::warn_nonnull_parameter_compare - : diag::warn_cast_nonnull_to_bool; - Diag(E->getExprLoc(), DiagID) << S.str() << E->getSourceRange() - << Range << IsEqual; + + for (unsigned ArgNo : NonNull->args()) { + if (ArgNo == ParamNo) { + ComplainAboutNonnullParamOrCall(true); return; } + } + } } } - + } + QualType T = D->getType(); const bool IsArray = T->isArrayType(); const bool IsFunction = T->isFunctionType(); @@ -7541,7 +7755,11 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare : diag::warn_impcast_pointer_to_bool; - unsigned DiagType; + enum { + AddressOf, + FunctionPointer, + ArrayPointer + } DiagType; if (IsAddressOf) DiagType = AddressOf; else if (IsFunction) @@ -8229,6 +8447,15 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P, } } } + + // Parameters with the pass_object_size attribute only need to be marked + // constant at function definitions. Because we lack information about + // whether we're on a declaration or definition when we're instantiating the + // attribute, we need to check for constness here. + if (const auto *Attr = Param->getAttr<PassObjectSizeAttr>()) + if (!Param->getType().isConstQualified()) + Diag(Param->getLocation(), diag::err_attribute_pointers_only) + << Attr->getSpelling() << 1; } return HasInvalidParm; @@ -8348,7 +8575,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, return; llvm::APSInt index; - if (!IndexExpr->EvaluateAsInt(index, Context)) + if (!IndexExpr->EvaluateAsInt(index, Context, Expr::SE_AllowSideEffects)) return; if (IndexNegated) index = -index; @@ -8462,6 +8689,13 @@ void Sema::CheckArrayAccess(const Expr *expr) { AllowOnePastEnd > 0); return; } + case Stmt::OMPArraySectionExprClass: { + const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr); + if (ASE->getLowerBound()) + CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(), + /*ASE=*/nullptr, AllowOnePastEnd > 0); + return; + } case Stmt::UnaryOperatorClass: { // Only unwrap the * and & unary operators const UnaryOperator *UO = cast<UnaryOperator>(expr); @@ -9672,4 +9906,3 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, << ArgumentExpr->getSourceRange() << TypeTagExpr->getSourceRange(); } - |