diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/AST/ASTContext.h | 4 | ||||
-rw-r--r-- | clang/include/clang/Basic/Builtins.def | 60 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 44 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 90 | ||||
-rw-r--r-- | clang/test/CodeGen/function-attributes.c | 14 | ||||
-rw-r--r-- | clang/test/CodeGen/nonnull.c | 84 |
6 files changed, 77 insertions, 219 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 2a6709104ae..5fa515d02db 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1864,9 +1864,7 @@ public: /// arguments to the builtin that are required to be integer constant /// expressions. QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, - unsigned *IntegerConstantArgs = nullptr, - bool *OverrideNonnullReturn = nullptr, - unsigned *OverrideNonnullArgs = nullptr) const; + unsigned *IntegerConstantArgs = nullptr) const; private: CanQualType getFromTargetType(unsigned Type) const; diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 6a83c1a3b7d..d1eafdc5668 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -55,12 +55,6 @@ // S -> signed // U -> unsigned // I -> Required to constant fold to an integer constant expression. -// N -> Do not assume non-null for optimizations even if attributed nonnull. -// This can be used when a relevant standard requires arguments or -// returns to be non-null and they are attributed accordingly but in -// practice are not used in this way. This typically used when a size -// parameter is also provided and when zero it would be reasonable to -// give an invalid pointer. // // Types may be postfixed with the following modifiers: // * -> pointer (optionally followed by an address space number, if no address @@ -792,27 +786,27 @@ LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(malloc, "v*z", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h", ALL_LANGUAGES) // C99 string.h -LIBBUILTIN(memcpy, "Nv*Nv*NvC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(memcmp, "iNvC*NvC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(memmove, "Nv*Nv*NvC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strncpy, "Nc*Nc*NcC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strcmp, "icC*cC*", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strncmp, "iNcC*NcC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strncat, "c*c*NcC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strxfrm, "zc*cC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(memchr, "Nv*NvC*iz", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strcspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strpbrk, "c*cC*cC*", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strrchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strstr, "c*cC*cC*", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strtok, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(memset, "Nv*Nv*iz", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strerror, "c*i", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strlen, "zcC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memcmp, "ivC*vC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strcmp, "icC*cC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strncmp, "icC*cC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strxfrm, "zc*cC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memchr, "v*vC*iz", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strcspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strpbrk, "c*cC*cC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strrchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strstr, "c*cC*cC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strtok, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memset, "v*v*iz", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strerror, "c*i", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strlen, "zcC*", "f", "string.h", ALL_LANGUAGES) // C99 stdio.h LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES) @@ -846,12 +840,12 @@ LIBBUILTIN(toupper, "ii", "fnU", "ctype.h", ALL_LANGUAGES) // C99 wchar.h // FIXME: This list is incomplete. We should cover at least the functions that // take format strings. -LIBBUILTIN(wcschr, "w*wC*w", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wcscmp, "iwC*wC*", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wcslen, "zwC*", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wcsncmp, "iNwC*NwC*z", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wmemchr, "Nw*NwC*wz", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wmemcmp, "iNwC*NwC*z", "f", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wcschr, "w*wC*w", "f", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wcscmp, "iwC*wC*", "f", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wcslen, "zwC*", "f", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wcsncmp, "iwC*wC*z", "f", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wmemchr, "w*wC*wz", "f", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wmemcmp, "iwC*wC*z", "f", "wchar.h", ALL_LANGUAGES) // C99 // In some systems setjmp is a macro that expands to _setjmp. We undefine diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 1c1f78ad266..071537a051c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -8499,14 +8499,13 @@ void ASTMutationListener::DeducedReturnType(const FunctionDecl *FD, /// to be an Integer Constant Expression. static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, ASTContext::GetBuiltinTypeError &Error, - bool &RequiresICE, bool &OverrideNonnull, + bool &RequiresICE, bool AllowTypeModifiers) { // Modifiers. int HowLong = 0; bool Signed = false, Unsigned = false; RequiresICE = false; - OverrideNonnull = false; - + // Read the prefixed modifiers first. bool Done = false; while (!Done) { @@ -8515,9 +8514,6 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, case 'I': RequiresICE = true; break; - case 'N': - OverrideNonnull = true; - break; case 'S': assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!"); assert(!Signed && "Can't use 'S' modifier multiple times!"); @@ -8652,8 +8648,8 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, assert(End != Str && "Missing vector size"); Str = End; - QualType ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE, - OverrideNonnull, false); + QualType ElementType = DecodeTypeFromStr(Str, Context, Error, + RequiresICE, false); assert(!RequiresICE && "Can't require vector ICE"); // TODO: No way to make AltiVec vectors in builtins yet. @@ -8668,15 +8664,15 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, assert(End != Str && "Missing vector size"); Str = End; - + QualType ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE, - OverrideNonnull, false); + false); Type = Context.getExtVectorType(ElementType, NumElements); break; } case 'X': { QualType ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE, - OverrideNonnull, false); + false); assert(!RequiresICE && "Can't require complex ICE"); Type = Context.getComplexType(ElementType); break; @@ -8758,37 +8754,27 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, } /// GetBuiltinType - Return the type for the specified builtin. -QualType ASTContext::GetBuiltinType(unsigned Id, GetBuiltinTypeError &Error, - unsigned *IntegerConstantArgs, - bool *OverrideNonnullReturn, - unsigned *OverrideNonnullArgs) const { +QualType ASTContext::GetBuiltinType(unsigned Id, + GetBuiltinTypeError &Error, + unsigned *IntegerConstantArgs) const { const char *TypeStr = BuiltinInfo.getTypeString(Id); SmallVector<QualType, 8> ArgTypes; bool RequiresICE = false; - bool OverrideNonnull = false; Error = GE_None; - QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error, RequiresICE, - OverrideNonnull, true); + QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error, + RequiresICE, true); if (Error != GE_None) return QualType(); - - if (OverrideNonnullReturn) - *OverrideNonnullReturn = OverrideNonnull; + assert(!RequiresICE && "Result of intrinsic cannot be required to be an ICE"); - + while (TypeStr[0] && TypeStr[0] != '.') { - QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error, RequiresICE, - OverrideNonnull, true); + QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error, RequiresICE, true); if (Error != GE_None) return QualType(); - // If this argument should have any nonnull annotations overriden, fill in - // the bitmask. - if (OverrideNonnull && OverrideNonnullArgs) - *OverrideNonnullArgs |= 1 << ArgTypes.size(); - // If this argument is required to be an IntegerConstantExpression and the // caller cares, fill in the bitmask we return. if (RequiresICE && IntegerConstantArgs) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 7e8d5161808..55191b223d0 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1759,34 +1759,6 @@ void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) { F.addAttributes(llvm::AttributeList::FunctionIndex, AS); } -/// Returns the attribute (either parameter attribute, or function -/// attribute), which declares argument ArgNo to be non-null. -static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD, - QualType ArgType, unsigned ArgNo) { - // FIXME: __attribute__((nonnull)) can also be applied to: - // - references to pointers, where the pointee is known to be - // nonnull (apparently a Clang extension) - // - transparent unions containing pointers - // In the former case, LLVM IR cannot represent the constraint. In - // the latter case, we have no guarantee that the transparent union - // is in fact passed as a pointer. - if (!ArgType->isAnyPointerType() && !ArgType->isBlockPointerType()) - return nullptr; - // First, check attribute on parameter itself. - if (PVD) { - if (auto ParmNNAttr = PVD->getAttr<NonNullAttr>()) - return ParmNNAttr; - } - // Check function attributes. - if (!FD) - return nullptr; - for (const auto *NNAttr : FD->specific_attrs<NonNullAttr>()) { - if (NNAttr->isNonNull(ArgNo)) - return NNAttr; - } - return nullptr; -} - void CodeGenModule::ConstructAttributeList( StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo, AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite) { @@ -1803,22 +1775,6 @@ void CodeGenModule::ConstructAttributeList( CalleeInfo.getCalleeFunctionProtoType()); const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); - const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl); - - // Check if this is a builtin function that might override some attributes. - unsigned BuiltinID = FD ? FD->getBuiltinID() : 0; - bool OverrideNonnullReturn = false; - unsigned OverrideNonnullArgs = 0; - if (BuiltinID) { - ASTContext::GetBuiltinTypeError Error; - getContext().GetBuiltinType(BuiltinID, Error, nullptr, - &OverrideNonnullReturn, &OverrideNonnullArgs); - // Note that we can't check the 'Error' here as there may be errors that - // have been diagnosed and reported to the programmer as warnings but - // repaired in the AST such as for implicit declarations of builtin - // functions. None of those impact our usage of this to analyze attributes - // for the builtins. - } bool HasOptnone = false; // FIXME: handle sseregparm someday... @@ -1834,13 +1790,13 @@ void CodeGenModule::ConstructAttributeList( if (TargetDecl->hasAttr<ConvergentAttr>()) FuncAttrs.addAttribute(llvm::Attribute::Convergent); - if (FD) { + if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { AddAttributesFromFunctionProtoType( - getContext(), FuncAttrs, FD->getType()->getAs<FunctionProtoType>()); + getContext(), FuncAttrs, Fn->getType()->getAs<FunctionProtoType>()); // Don't use [[noreturn]] or _Noreturn for a call to a virtual function. // These attributes are not inherited by overloads. - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); - if (FD->isNoReturn() && !(AttrOnCallSite && MD && MD->isVirtual())) + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn); + if (Fn->isNoReturn() && !(AttrOnCallSite && MD && MD->isVirtual())) FuncAttrs.addAttribute(llvm::Attribute::NoReturn); } @@ -1857,7 +1813,7 @@ void CodeGenModule::ConstructAttributeList( } if (TargetDecl->hasAttr<RestrictAttr>()) RetAttrs.addAttribute(llvm::Attribute::NoAlias); - if (TargetDecl->hasAttr<ReturnsNonNullAttr>() && !OverrideNonnullReturn) + if (TargetDecl->hasAttr<ReturnsNonNullAttr>()) RetAttrs.addAttribute(llvm::Attribute::NonNull); HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>(); @@ -1889,6 +1845,7 @@ void CodeGenModule::ConstructAttributeList( // we have a decl for the function and it has a target attribute then // parse that and add it to the feature set. StringRef TargetCPU = getTarget().getTargetOpts().CPU; + const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl); if (FD && FD->hasAttr<TargetAttr>()) { llvm::StringMap<bool> FeatureMap; getFunctionFeatureMap(FeatureMap, FD); @@ -2080,13 +2037,6 @@ void CodeGenModule::ConstructAttributeList( continue; } - if (FD && ArgNo < FD->param_size() && ParamType->isPointerType()) { - auto *PVD = FD->getParamDecl(ArgNo); - if (getNonNullAttr(FD, PVD, ParamType, PVD->getFunctionScopeIndex()) && - (!BuiltinID || (OverrideNonnullArgs & (1 << ArgNo)) == 0)) - Attrs.addAttribute(llvm::Attribute::NonNull); - } - if (const auto *RefTy = ParamType->getAs<ReferenceType>()) { QualType PTy = RefTy->getPointeeType(); if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) @@ -2166,6 +2116,34 @@ static llvm::Value *emitArgumentDemotion(CodeGenFunction &CGF, return CGF.Builder.CreateFPCast(value, varType, "arg.unpromote"); } +/// Returns the attribute (either parameter attribute, or function +/// attribute), which declares argument ArgNo to be non-null. +static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD, + QualType ArgType, unsigned ArgNo) { + // FIXME: __attribute__((nonnull)) can also be applied to: + // - references to pointers, where the pointee is known to be + // nonnull (apparently a Clang extension) + // - transparent unions containing pointers + // In the former case, LLVM IR cannot represent the constraint. In + // the latter case, we have no guarantee that the transparent union + // is in fact passed as a pointer. + if (!ArgType->isAnyPointerType() && !ArgType->isBlockPointerType()) + return nullptr; + // First, check attribute on parameter itself. + if (PVD) { + if (auto ParmNNAttr = PVD->getAttr<NonNullAttr>()) + return ParmNNAttr; + } + // Check function attributes. + if (!FD) + return nullptr; + for (const auto *NNAttr : FD->specific_attrs<NonNullAttr>()) { + if (NNAttr->isNonNull(ArgNo)) + return NNAttr; + } + return nullptr; +} + namespace { struct CopyBackSwiftError final : EHScopeStack::Cleanup { Address Temp; diff --git a/clang/test/CodeGen/function-attributes.c b/clang/test/CodeGen/function-attributes.c index 49f47bf74d4..2139f6fe654 100644 --- a/clang/test/CodeGen/function-attributes.c +++ b/clang/test/CodeGen/function-attributes.c @@ -108,20 +108,6 @@ void f20(void) { _setjmp(0); } -// Bogus declarations that will end up with bad types when detecting builtins, -// but that we will still process when considering whether to add attributes. -struct __jmp_buf_tag; -extern int __sigsetjmp(struct __jmp_buf_tag *__env, int __savemask); - -// CHECK-LABEL: define void @f21() -// CHECK: { -// CHECK: call i32 @__sigsetjmp(%{{.*}}* null, i32 0) -// CHECK: [[RT_CALL]] -// CHECK: ret void -void f21(void) { - __sigsetjmp(0, 0); -} - // CHECK: attributes [[NUW]] = { nounwind optsize{{.*}} } // CHECK: attributes [[AI]] = { alwaysinline nounwind optsize{{.*}} } // CHECK: attributes [[NUW_OS_RN]] = { nounwind optsize readnone{{.*}} } diff --git a/clang/test/CodeGen/nonnull.c b/clang/test/CodeGen/nonnull.c index 63d8b90b349..7c33e6329fd 100644 --- a/clang/test/CodeGen/nonnull.c +++ b/clang/test/CodeGen/nonnull.c @@ -49,87 +49,3 @@ __attribute__((nonnull(2))) {} // CHECK: define void @bar8(i32* nonnull %a, i32* nonnull %b) void bar8(int *a, int *b) __attribute__((nonnull)) __attribute__((nonnull(1))) {} - -// CHECK: declare void @foo_decl(i32* nonnull) -void foo_decl(int *__attribute__((nonnull))); - -// CHECK: declare void @bar_decl(i32* nonnull) -void bar_decl(int *) __attribute__((nonnull(1))); - -// CHECK: declare void @bar2_decl(i32*, i32* nonnull) -void bar2_decl(int *, int *) __attribute__((nonnull(2))); - -// CHECK: declare nonnull i32* @bar3_decl() -int *bar3_decl(void) __attribute__((returns_nonnull)); - -// CHECK: declare i32 @bar4_decl(i32, i32* nonnull) -int bar4_decl(int, int *) __attribute__((nonnull)); - -// CHECK: declare i32 @bar5_decl(i32, i32* nonnull) -int bar5_decl(int, int *) __attribute__((nonnull(1, 2))); - -// CHECK: declare i32 @bar6_decl(i64) -int bar6_decl(TransparentUnion) __attribute__((nonnull(1))); - -// CHECK: declare void @bar7_decl(i32* nonnull, i32* nonnull) -void bar7_decl(int *, int *) - __attribute__((nonnull(1))) __attribute__((nonnull(2))); - -// CHECK: declare void @bar8_decl(i32* nonnull, i32* nonnull) -void bar8_decl(int *, int *) - __attribute__((nonnull)) __attribute__((nonnull(1))); - -// Clang specially disables nonnull attributes on some library builtin -// functions to work around the fact that the standard and some vendors mark -// them as nonnull even though they are frequently called in practice with null -// arguments if a corresponding size argument is zero. - -// CHECK: declare i8* @memcpy(i8*, i8*, i64) -void *memcpy(void *, const void *, unsigned long) - __attribute__((nonnull(1, 2))) __attribute__((returns_nonnull)); - -// CHECK: declare i32 @memcmp(i8*, i8*, i64) -int memcmp(const void *, const void *, unsigned long) __attribute__((nonnull(1, 2))); - -// CHECK: declare i8* @memmove(i8*, i8*, i64) -void *memmove(void *, const void *, unsigned long) - __attribute__((nonnull(1, 2))) __attribute__((returns_nonnull)); - -// CHECK: declare i8* @strncpy(i8*, i8*, i64) -char *strncpy(char *, const char *, unsigned long) - __attribute__((nonnull(1, 2))) __attribute__((returns_nonnull)); - -// CHECK: declare i32 @strncmp(i8*, i8*, i64) -int strncmp(const char *, const char *, unsigned long) __attribute__((nonnull(1, 2))); - -// CHECK: declare nonnull i8* @strncat(i8* nonnull, i8*, i64) -char *strncat(char *, const char *, unsigned long) - __attribute__((nonnull(1, 2))) __attribute__((returns_nonnull)); - -// CHECK: declare i8* @memchr(i8*, i32, i64) -void *memchr(const void *__attribute__((nonnull)), int, unsigned long) - __attribute__((returns_nonnull)); - -// CHECK: declare i8* @memset(i8*, i32, i64) -void *memset(void *__attribute__((nonnull)), int, unsigned long) - __attribute__((returns_nonnull)); - -void use_declarations(int *p, void *volatile *sink) { - foo_decl(p); - bar_decl(p); - bar2_decl(p, p); - (void)bar3_decl(); - bar4_decl(42, p); - bar5_decl(42, p); - bar6_decl(p); - bar7_decl(p, p); - bar8_decl(p, p); - *sink = (void *)&memcpy; - *sink = (void *)&memcmp; - *sink = (void *)&memmove; - *sink = (void *)&strncpy; - *sink = (void *)&strncmp; - *sink = (void *)&strncat; - *sink = (void *)&memchr; - *sink = (void *)&memset; -} |