| From c3cecb51bd66712f2a00a5d516061b372f7b7c06 Mon Sep 17 00:00:00 2001 |
| From: Chih-Hung Hsieh <chh@google.com> |
| Date: Mon, 22 Feb 2021 15:40:47 -0800 |
| Subject: [PATCH] Revert "[Sema] Introduce BuiltinAttr, per-declaration |
| builtin-ness" |
| |
| This reverts commit e09107ab80dced55414fa458cf78e6cdfe90da6e. |
| |
| Change-Id: Idc61b29dba6e2948cb2f62b78350dfbfb5c82cd6 |
| --- |
| clang/include/clang/Basic/Attr.td | 8 -- |
| clang/include/clang/Basic/Builtins.def | 1 - |
| clang/include/clang/Basic/IdentifierTable.h | 12 ++ |
| clang/include/clang/Sema/Sema.h | 2 - |
| clang/lib/AST/Decl.cpp | 29 ++++- |
| clang/lib/Headers/intrin.h | 118 ++++++++++------- |
| clang/lib/Sema/SemaDecl.cpp | 120 +++++++----------- |
| clang/lib/Sema/SemaExpr.cpp | 1 - |
| clang/lib/Sema/SemaLookup.cpp | 7 +- |
| clang/lib/Serialization/ASTReader.cpp | 12 +- |
| clang/lib/Serialization/ASTWriter.cpp | 6 +- |
| clang/test/AST/ast-dump-attr.cpp | 1 - |
| clang/test/CodeGen/builtin-redeclaration.c | 16 --- |
| clang/test/CodeGen/callback_pthread_create.c | 4 - |
| clang/test/CodeGenCXX/builtins.cpp | 14 -- |
| clang/test/Sema/implicit-builtin-decl.c | 5 + |
| clang/test/Sema/warn-fortify-source.c | 19 ++- |
| clang/test/SemaCXX/cxx11-compat.cpp | 2 +- |
| .../SemaCXX/warn-unused-local-typedef.cpp | 4 +- |
| 19 files changed, 200 insertions(+), 181 deletions(-) |
| delete mode 100644 clang/test/CodeGen/builtin-redeclaration.c |
| |
| diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td |
| index 5bfcec732907..58666a5a7974 100644 |
| --- a/clang/include/clang/Basic/Attr.td |
| +++ b/clang/include/clang/Basic/Attr.td |
| @@ -3774,14 +3774,6 @@ def ReleaseHandle : InheritableParamAttr { |
| let Documentation = [ReleaseHandleDocs]; |
| } |
| |
| -def Builtin : InheritableAttr { |
| - let Spellings = []; |
| - let Args = [UnsignedArgument<"ID">]; |
| - let Subjects = SubjectList<[Function]>; |
| - let SemaHandler = 0; |
| - let Documentation = [Undocumented]; |
| -} |
| - |
| def EnforceTCB : InheritableAttr { |
| let Spellings = [Clang<"enforce_tcb">]; |
| let Subjects = SubjectList<[Function]>; |
| diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def |
| index 5a9d0a001829..88f80abe677c 100644 |
| --- a/clang/include/clang/Basic/Builtins.def |
| +++ b/clang/include/clang/Basic/Builtins.def |
| @@ -1087,7 +1087,6 @@ LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_GNU_LANGUAGES) |
| LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_GNU_LANGUAGES) |
| LIBBUILTIN(vfork, "p", "fjT", "unistd.h", ALL_LANGUAGES) |
| // POSIX pthread.h |
| -// FIXME: Should specify argument types. |
| LIBBUILTIN(pthread_create, "", "fC<2,3>", "pthread.h", ALL_GNU_LANGUAGES) |
| |
| // POSIX setjmp.h |
| diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h |
| index e074a7d3254c..3ea65ef65142 100644 |
| --- a/clang/include/clang/Basic/IdentifierTable.h |
| +++ b/clang/include/clang/Basic/IdentifierTable.h |
| @@ -233,6 +233,18 @@ public: |
| } |
| void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; } |
| |
| + /// True if setNotBuiltin() was called. |
| + bool hasRevertedBuiltin() const { |
| + return ObjCOrBuiltinID == tok::NUM_OBJC_KEYWORDS; |
| + } |
| + |
| + /// Revert the identifier to a non-builtin identifier. We do this if |
| + /// the name of a known builtin library function is used to declare that |
| + /// function, but an unexpected type is specified. |
| + void revertBuiltin() { |
| + setBuiltinID(0); |
| + } |
| + |
| /// Return a value indicating whether this is a builtin function. |
| /// |
| /// 0 is not-built-in. 1+ are specific builtin functions. |
| diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h |
| index 07518b37eb98..05d47fd2ab92 100644 |
| --- a/clang/include/clang/Sema/Sema.h |
| +++ b/clang/include/clang/Sema/Sema.h |
| @@ -4247,8 +4247,6 @@ public: |
| ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id, |
| SourceLocation IdLoc, |
| bool TypoCorrection = false); |
| - FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID, |
| - SourceLocation Loc); |
| NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, |
| Scope *S, bool ForRedeclaration, |
| SourceLocation Loc); |
| diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp |
| index c5c8f473dda9..3b7d6f3387bd 100644 |
| --- a/clang/lib/AST/Decl.cpp |
| +++ b/clang/lib/AST/Decl.cpp |
| @@ -3284,26 +3284,45 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); } |
| /// functions as their wrapped builtins. This shouldn't be done in general, but |
| /// it's useful in Sema to diagnose calls to wrappers based on their semantics. |
| unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const { |
| - unsigned BuiltinID = 0; |
| + unsigned BuiltinID; |
| |
| if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) { |
| BuiltinID = ABAA->getBuiltinName()->getBuiltinID(); |
| } else if (const auto *BAA = getAttr<BuiltinAliasAttr>()) { |
| BuiltinID = BAA->getBuiltinName()->getBuiltinID(); |
| - } else if (const auto *A = getAttr<BuiltinAttr>()) { |
| - BuiltinID = A->getID(); |
| - } |
| + } else { |
| + if (!getIdentifier()) |
| + return 0; |
| |
| + BuiltinID = getIdentifier()->getBuiltinID(); |
| + } |
| if (!BuiltinID) |
| return 0; |
| |
| + ASTContext &Context = getASTContext(); |
| + if (Context.getLangOpts().CPlusPlus) { |
| + const auto *LinkageDecl = |
| + dyn_cast<LinkageSpecDecl>(getFirstDecl()->getDeclContext()); |
| + // In C++, the first declaration of a builtin is always inside an implicit |
| + // extern "C". |
| + // FIXME: A recognised library function may not be directly in an extern "C" |
| + // declaration, for instance "extern "C" { namespace std { decl } }". |
| + if (!LinkageDecl) { |
| + if (BuiltinID == Builtin::BI__GetExceptionInfo && |
| + Context.getTargetInfo().getCXXABI().isMicrosoft()) |
| + return Builtin::BI__GetExceptionInfo; |
| + return 0; |
| + } |
| + if (LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c) |
| + return 0; |
| + } |
| + |
| // If the function is marked "overloadable", it has a different mangled name |
| // and is not the C library function. |
| if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() && |
| (!hasAttr<ArmBuiltinAliasAttr>() && !hasAttr<BuiltinAliasAttr>())) |
| return 0; |
| |
| - ASTContext &Context = getASTContext(); |
| if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) |
| return BuiltinID; |
| |
| diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h |
| index 2b4e1b75e404..a42a1ee5e300 100644 |
| --- a/clang/lib/Headers/intrin.h |
| +++ b/clang/lib/Headers/intrin.h |
| @@ -57,11 +57,16 @@ void __addfsbyte(unsigned long, unsigned char); |
| void __addfsdword(unsigned long, unsigned long); |
| void __addfsword(unsigned long, unsigned short); |
| void __code_seg(const char *); |
| +static __inline__ |
| void __cpuid(int[4], int); |
| +static __inline__ |
| void __cpuidex(int[4], int, int); |
| +static __inline__ |
| __int64 __emul(int, int); |
| +static __inline__ |
| unsigned __int64 __emulu(unsigned int, unsigned int); |
| unsigned int __getcallerseflags(void); |
| +static __inline__ |
| void __halt(void); |
| unsigned char __inbyte(unsigned short); |
| void __inbytestring(unsigned short, unsigned char *, unsigned long); |
| @@ -77,9 +82,13 @@ void __inwordstring(unsigned short, unsigned short *, unsigned long); |
| void __lidt(void *); |
| unsigned __int64 __ll_lshift(unsigned __int64, int); |
| __int64 __ll_rshift(__int64, int); |
| +static __inline__ |
| void __movsb(unsigned char *, unsigned char const *, size_t); |
| +static __inline__ |
| void __movsd(unsigned long *, unsigned long const *, size_t); |
| +static __inline__ |
| void __movsw(unsigned short *, unsigned short const *, size_t); |
| +static __inline__ |
| void __nop(void); |
| void __nvreg_restore_fence(void); |
| void __nvreg_save_fence(void); |
| @@ -96,16 +105,23 @@ unsigned long __readcr4(void); |
| unsigned long __readcr8(void); |
| unsigned int __readdr(unsigned int); |
| #ifdef __i386__ |
| +static __inline__ |
| unsigned char __readfsbyte(unsigned long); |
| +static __inline__ |
| unsigned __int64 __readfsqword(unsigned long); |
| +static __inline__ |
| unsigned short __readfsword(unsigned long); |
| #endif |
| +static __inline__ |
| unsigned __int64 __readmsr(unsigned long); |
| unsigned __int64 __readpmc(unsigned long); |
| unsigned long __segmentlimit(unsigned long); |
| void __sidt(void *); |
| +static __inline__ |
| void __stosb(unsigned char *, unsigned char, size_t); |
| +static __inline__ |
| void __stosd(unsigned long *, unsigned long, size_t); |
| +static __inline__ |
| void __stosw(unsigned short *, unsigned short, size_t); |
| void __svm_clgi(void); |
| void __svm_invlpga(void *, int); |
| @@ -120,6 +136,7 @@ void __vmx_off(void); |
| void __vmx_vmptrst(unsigned __int64 *); |
| void __wbinvd(void); |
| void __writecr0(unsigned int); |
| +static __inline__ |
| void __writecr3(unsigned __INTPTR_TYPE__); |
| void __writecr4(unsigned int); |
| void __writecr8(unsigned int); |
| @@ -129,8 +146,11 @@ void __writefsdword(unsigned long, unsigned long); |
| void __writefsqword(unsigned long, unsigned __int64); |
| void __writefsword(unsigned long, unsigned short); |
| void __writemsr(unsigned long, unsigned __int64); |
| +static __inline__ |
| void *_AddressOfReturnAddress(void); |
| +static __inline__ |
| unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask); |
| +static __inline__ |
| unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask); |
| unsigned char _bittest(long const *, long); |
| unsigned char _bittestandcomplement(long *, long); |
| @@ -149,10 +169,12 @@ long _InterlockedExchangeAdd_HLEAcquire(long volatile *, long); |
| long _InterlockedExchangeAdd_HLERelease(long volatile *, long); |
| __int64 _InterlockedExchangeAdd64_HLEAcquire(__int64 volatile *, __int64); |
| __int64 _InterlockedExchangeAdd64_HLERelease(__int64 volatile *, __int64); |
| -void __attribute__((__deprecated__( |
| - "use other intrinsics or C++11 atomics instead"))) _ReadBarrier(void); |
| -void __attribute__((__deprecated__( |
| - "use other intrinsics or C++11 atomics instead"))) _ReadWriteBarrier(void); |
| +static __inline__ void |
| +__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead"))) |
| +_ReadBarrier(void); |
| +static __inline__ void |
| +__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead"))) |
| +_ReadWriteBarrier(void); |
| unsigned int _rorx_u32(unsigned int, const unsigned int); |
| int _sarx_i32(int, unsigned int); |
| #if __STDC_HOSTED__ |
| @@ -163,8 +185,9 @@ unsigned int _shrx_u32(unsigned int, unsigned int); |
| void _Store_HLERelease(long volatile *, long); |
| void _Store64_HLERelease(__int64 volatile *, __int64); |
| void _StorePointer_HLERelease(void *volatile *, void *); |
| -void __attribute__((__deprecated__( |
| - "use other intrinsics or C++11 atomics instead"))) _WriteBarrier(void); |
| +static __inline__ void |
| +__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead"))) |
| +_WriteBarrier(void); |
| unsigned __int32 xbegin(void); |
| void _xend(void); |
| |
| @@ -174,14 +197,19 @@ void __addgsbyte(unsigned long, unsigned char); |
| void __addgsdword(unsigned long, unsigned long); |
| void __addgsqword(unsigned long, unsigned __int64); |
| void __addgsword(unsigned long, unsigned short); |
| +static __inline__ |
| void __faststorefence(void); |
| void __incgsbyte(unsigned long); |
| void __incgsdword(unsigned long); |
| void __incgsqword(unsigned long); |
| void __incgsword(unsigned long); |
| +static __inline__ |
| void __movsq(unsigned long long *, unsigned long long const *, size_t); |
| +static __inline__ |
| unsigned char __readgsbyte(unsigned long); |
| +static __inline__ |
| unsigned long __readgsdword(unsigned long); |
| +static __inline__ |
| unsigned __int64 __readgsqword(unsigned long); |
| unsigned short __readgsword(unsigned long); |
| unsigned __int64 __shiftleft128(unsigned __int64 _LowPart, |
| @@ -190,6 +218,7 @@ unsigned __int64 __shiftleft128(unsigned __int64 _LowPart, |
| unsigned __int64 __shiftright128(unsigned __int64 _LowPart, |
| unsigned __int64 _HighPart, |
| unsigned char _Shift); |
| +static __inline__ |
| void __stosq(unsigned __int64 *, unsigned __int64, size_t); |
| unsigned char __vmx_on(unsigned __int64 *); |
| unsigned char __vmx_vmclear(unsigned __int64 *); |
| @@ -236,9 +265,13 @@ unsigned __int64 _rorx_u64(unsigned __int64, const unsigned int); |
| __int64 _sarx_i64(__int64, unsigned int); |
| unsigned __int64 _shlx_u64(unsigned __int64, unsigned int); |
| unsigned __int64 _shrx_u64(unsigned __int64, unsigned int); |
| +static __inline__ |
| __int64 __mulh(__int64, __int64); |
| +static __inline__ |
| unsigned __int64 __umulh(unsigned __int64, unsigned __int64); |
| +static __inline__ |
| __int64 _mul128(__int64, __int64, __int64*); |
| +static __inline__ |
| unsigned __int64 _umul128(unsigned __int64, |
| unsigned __int64, |
| unsigned __int64*); |
| @@ -247,19 +280,29 @@ unsigned __int64 _umul128(unsigned __int64, |
| |
| #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) |
| |
| +static __inline__ |
| unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); |
| +static __inline__ |
| unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); |
| |
| #endif |
| |
| #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) |
| +static __inline__ |
| __int64 _InterlockedDecrement64(__int64 volatile *_Addend); |
| +static __inline__ |
| __int64 _InterlockedExchange64(__int64 volatile *_Target, __int64 _Value); |
| +static __inline__ |
| __int64 _InterlockedExchangeAdd64(__int64 volatile *_Addend, __int64 _Value); |
| +static __inline__ |
| __int64 _InterlockedExchangeSub64(__int64 volatile *_Subend, __int64 _Value); |
| +static __inline__ |
| __int64 _InterlockedIncrement64(__int64 volatile *_Addend); |
| +static __inline__ |
| __int64 _InterlockedOr64(__int64 volatile *_Value, __int64 _Mask); |
| +static __inline__ |
| __int64 _InterlockedXor64(__int64 volatile *_Value, __int64 _Mask); |
| +static __inline__ |
| __int64 _InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask); |
| |
| #endif |
| @@ -448,56 +491,40 @@ unsigned char _InterlockedCompareExchange128_rel(__int64 volatile *_Destination, |
| |* movs, stos |
| \*----------------------------------------------------------------------------*/ |
| #if defined(__i386__) || defined(__x86_64__) |
| -static __inline__ void __DEFAULT_FN_ATTRS __movsb(unsigned char *__dst, |
| - unsigned char const *__src, |
| - size_t __n) { |
| +static __inline__ void __DEFAULT_FN_ATTRS |
| +__movsb(unsigned char *__dst, unsigned char const *__src, size_t __n) { |
| __asm__ __volatile__("rep movsb" : "+D"(__dst), "+S"(__src), "+c"(__n) |
| : : "memory"); |
| } |
| -static __inline__ void __DEFAULT_FN_ATTRS __movsd(unsigned long *__dst, |
| - unsigned long const *__src, |
| - size_t __n) { |
| - __asm__ __volatile__("rep movsl" |
| - : "+D"(__dst), "+S"(__src), "+c"(__n) |
| - : |
| - : "memory"); |
| +static __inline__ void __DEFAULT_FN_ATTRS |
| +__movsd(unsigned long *__dst, unsigned long const *__src, size_t __n) { |
| + __asm__ __volatile__("rep movsl" : "+D"(__dst), "+S"(__src), "+c"(__n) |
| + : : "memory"); |
| } |
| -static __inline__ void __DEFAULT_FN_ATTRS __movsw(unsigned short *__dst, |
| - unsigned short const *__src, |
| - size_t __n) { |
| - __asm__ __volatile__("rep movsw" |
| - : "+D"(__dst), "+S"(__src), "+c"(__n) |
| - : |
| - : "memory"); |
| +static __inline__ void __DEFAULT_FN_ATTRS |
| +__movsw(unsigned short *__dst, unsigned short const *__src, size_t __n) { |
| + __asm__ __volatile__("rep movsw" : "+D"(__dst), "+S"(__src), "+c"(__n) |
| + : : "memory"); |
| } |
| -static __inline__ void __DEFAULT_FN_ATTRS __stosd(unsigned long *__dst, |
| - unsigned long __x, |
| - size_t __n) { |
| - __asm__ __volatile__("rep stosl" |
| - : "+D"(__dst), "+c"(__n) |
| - : "a"(__x) |
| +static __inline__ void __DEFAULT_FN_ATTRS |
| +__stosd(unsigned long *__dst, unsigned long __x, size_t __n) { |
| + __asm__ __volatile__("rep stosl" : "+D"(__dst), "+c"(__n) : "a"(__x) |
| : "memory"); |
| } |
| -static __inline__ void __DEFAULT_FN_ATTRS __stosw(unsigned short *__dst, |
| - unsigned short __x, |
| - size_t __n) { |
| - __asm__ __volatile__("rep stosw" |
| - : "+D"(__dst), "+c"(__n) |
| - : "a"(__x) |
| +static __inline__ void __DEFAULT_FN_ATTRS |
| +__stosw(unsigned short *__dst, unsigned short __x, size_t __n) { |
| + __asm__ __volatile__("rep stosw" : "+D"(__dst), "+c"(__n) : "a"(__x) |
| : "memory"); |
| } |
| #endif |
| #ifdef __x86_64__ |
| -static __inline__ void __DEFAULT_FN_ATTRS __movsq( |
| - unsigned long long *__dst, unsigned long long const *__src, size_t __n) { |
| - __asm__ __volatile__("rep movsq" |
| - : "+D"(__dst), "+S"(__src), "+c"(__n) |
| - : |
| - : "memory"); |
| +static __inline__ void __DEFAULT_FN_ATTRS |
| +__movsq(unsigned long long *__dst, unsigned long long const *__src, size_t __n) { |
| + __asm__ __volatile__("rep movsq" : "+D"(__dst), "+S"(__src), "+c"(__n) |
| + : : "memory"); |
| } |
| -static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst, |
| - unsigned __int64 __x, |
| - size_t __n) { |
| +static __inline__ void __DEFAULT_FN_ATTRS |
| +__stosq(unsigned __int64 *__dst, unsigned __int64 __x, size_t __n) { |
| __asm__ __volatile__("rep stosq" : "+D"(__dst), "+c"(__n) : "a"(__x) |
| : "memory"); |
| } |
| @@ -572,7 +599,8 @@ __readmsr(unsigned long __register) { |
| } |
| #endif |
| |
| -static __inline__ unsigned __LPTRINT_TYPE__ __DEFAULT_FN_ATTRS __readcr3(void) { |
| +static __inline__ unsigned __LPTRINT_TYPE__ __DEFAULT_FN_ATTRS |
| +__readcr3(void) { |
| unsigned __LPTRINT_TYPE__ __cr3_val; |
| __asm__ __volatile__ ("mov %%cr3, %0" : "=r"(__cr3_val) : : "memory"); |
| return __cr3_val; |
| diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp |
| index e08e8d8346c0..93479aed36ff 100644 |
| --- a/clang/lib/Sema/SemaDecl.cpp |
| +++ b/clang/lib/Sema/SemaDecl.cpp |
| @@ -2048,42 +2048,6 @@ static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID, |
| llvm_unreachable("unhandled error kind"); |
| } |
| |
| -FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type, |
| - unsigned ID, SourceLocation Loc) { |
| - DeclContext *Parent = Context.getTranslationUnitDecl(); |
| - |
| - if (getLangOpts().CPlusPlus) { |
| - LinkageSpecDecl *CLinkageDecl = LinkageSpecDecl::Create( |
| - Context, Parent, Loc, Loc, LinkageSpecDecl::lang_c, false); |
| - CLinkageDecl->setImplicit(); |
| - Parent->addDecl(CLinkageDecl); |
| - Parent = CLinkageDecl; |
| - } |
| - |
| - FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type, |
| - /*TInfo=*/nullptr, SC_Extern, false, |
| - Type->isFunctionProtoType()); |
| - New->setImplicit(); |
| - New->addAttr(BuiltinAttr::CreateImplicit(Context, ID)); |
| - |
| - // Create Decl objects for each parameter, adding them to the |
| - // FunctionDecl. |
| - if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(Type)) { |
| - SmallVector<ParmVarDecl *, 16> Params; |
| - for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { |
| - ParmVarDecl *parm = ParmVarDecl::Create( |
| - Context, New, SourceLocation(), SourceLocation(), nullptr, |
| - FT->getParamType(i), /*TInfo=*/nullptr, SC_None, nullptr); |
| - parm->setScopeInfo(0, i); |
| - Params.push_back(parm); |
| - } |
| - New->setParams(Params); |
| - } |
| - |
| - AddKnownFunctionAttributes(New); |
| - return New; |
| -} |
| - |
| /// LazilyCreateBuiltin - The specified Builtin-ID was first used at |
| /// file scope. lazily create a decl for it. ForRedeclaration is true |
| /// if we're creating this built-in in anticipation of redeclaring the |
| @@ -2134,7 +2098,40 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, |
| if (R.isNull()) |
| return nullptr; |
| |
| - FunctionDecl *New = CreateBuiltin(II, R, ID, Loc); |
| + DeclContext *Parent = Context.getTranslationUnitDecl(); |
| + if (getLangOpts().CPlusPlus) { |
| + LinkageSpecDecl *CLinkageDecl = |
| + LinkageSpecDecl::Create(Context, Parent, Loc, Loc, |
| + LinkageSpecDecl::lang_c, false); |
| + CLinkageDecl->setImplicit(); |
| + Parent->addDecl(CLinkageDecl); |
| + Parent = CLinkageDecl; |
| + } |
| + |
| + FunctionDecl *New = FunctionDecl::Create(Context, |
| + Parent, |
| + Loc, Loc, II, R, /*TInfo=*/nullptr, |
| + SC_Extern, |
| + false, |
| + R->isFunctionProtoType()); |
| + New->setImplicit(); |
| + |
| + // Create Decl objects for each parameter, adding them to the |
| + // FunctionDecl. |
| + if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) { |
| + SmallVector<ParmVarDecl*, 16> Params; |
| + for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { |
| + ParmVarDecl *parm = |
| + ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(), |
| + nullptr, FT->getParamType(i), /*TInfo=*/nullptr, |
| + SC_None, nullptr); |
| + parm->setScopeInfo(0, i); |
| + Params.push_back(parm); |
| + } |
| + New->setParams(Params); |
| + } |
| + |
| + AddKnownFunctionAttributes(New); |
| RegisterLocallyScopedExternCDecl(New, S); |
| |
| // TUScope is the translation-unit scope to insert this function into. |
| @@ -2142,7 +2139,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, |
| // relate Scopes to DeclContexts, and probably eliminate CurContext |
| // entirely, but we're not there yet. |
| DeclContext *SavedContext = CurContext; |
| - CurContext = New->getDeclContext(); |
| + CurContext = Parent; |
| PushOnScopeChains(New, TUScope); |
| CurContext = SavedContext; |
| return New; |
| @@ -3367,10 +3364,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, |
| // there but not here. |
| NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); |
| RequiresAdjustment = true; |
| - } else if (Old->getBuiltinID()) { |
| - // Builtin attribute isn't propagated to the new one yet at this point, |
| - // so we check if the old one is a builtin. |
| - |
| + } else if (New->getBuiltinID()) { |
| // Calling Conventions on a Builtin aren't really useful and setting a |
| // default calling convention and cdecl'ing some builtin redeclarations is |
| // common, so warn and ignore the calling convention on the redeclaration. |
| @@ -3803,6 +3797,18 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, |
| Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New; |
| Diag(OldLocation, diag::note_previous_builtin_declaration) |
| << Old << Old->getType(); |
| + |
| + // If this is a global redeclaration, just forget hereafter |
| + // about the "builtin-ness" of the function. |
| + // |
| + // Doing this for local extern declarations is problematic. If |
| + // the builtin declaration remains visible, a second invalid |
| + // local declaration will produce a hard error; if it doesn't |
| + // remain visible, a single bogus local redeclaration (which is |
| + // actually only a warning) could break all the downstream code. |
| + if (!New->getLexicalDeclContext()->isFunctionOrMethod()) |
| + New->getIdentifier()->revertBuiltin(); |
| + |
| return false; |
| } |
| |
| @@ -9784,36 +9790,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, |
| } |
| } |
| |
| - // If this is the first declaration of a library builtin function, add |
| - // attributes as appropriate. |
| - if (!D.isRedeclaration() && |
| - NewFD->getDeclContext()->getRedeclContext()->isFileContext()) { |
| - if (IdentifierInfo *II = Previous.getLookupName().getAsIdentifierInfo()) { |
| - if (unsigned BuiltinID = II->getBuiltinID()) { |
| - if (NewFD->getLanguageLinkage() == CLanguageLinkage) { |
| - // Validate the type matches unless this builtin is specified as |
| - // matching regardless of its declared type. |
| - if (Context.BuiltinInfo.allowTypeMismatch(BuiltinID)) { |
| - NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID)); |
| - } else { |
| - ASTContext::GetBuiltinTypeError Error; |
| - LookupNecessaryTypesForBuiltin(S, BuiltinID); |
| - QualType BuiltinType = Context.GetBuiltinType(BuiltinID, Error); |
| - |
| - if (!Error && !BuiltinType.isNull() && |
| - Context.hasSameFunctionTypeIgnoringExceptionSpec( |
| - NewFD->getType(), BuiltinType)) |
| - NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID)); |
| - } |
| - } else if (BuiltinID == Builtin::BI__GetExceptionInfo && |
| - Context.getTargetInfo().getCXXABI().isMicrosoft()) { |
| - // FIXME: We should consider this a builtin only in the std namespace. |
| - NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID)); |
| - } |
| - } |
| - } |
| - } |
| - |
| ProcessPragmaWeak(S, NewFD); |
| checkAttributesAfterMerging(*this, *NewFD); |
| |
| diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp |
| index 02421cbc4317..c33417fd8198 100644 |
| --- a/clang/lib/Sema/SemaExpr.cpp |
| +++ b/clang/lib/Sema/SemaExpr.cpp |
| @@ -6252,7 +6252,6 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context, |
| Params.push_back(Parm); |
| } |
| OverloadDecl->setParams(Params); |
| - Sema->mergeDeclAttributes(OverloadDecl, FDecl); |
| return OverloadDecl; |
| } |
| |
| diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp |
| index db6a01543d76..b66c33de83ab 100644 |
| --- a/clang/lib/Sema/SemaLookup.cpp |
| +++ b/clang/lib/Sema/SemaLookup.cpp |
| @@ -935,9 +935,10 @@ bool Sema::LookupBuiltin(LookupResult &R) { |
| Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) |
| return false; |
| |
| - if (NamedDecl *D = |
| - LazilyCreateBuiltin(II, BuiltinID, TUScope, |
| - R.isForRedeclaration(), R.getNameLoc())) { |
| + if (NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, |
| + BuiltinID, TUScope, |
| + R.isForRedeclaration(), |
| + R.getNameLoc())) { |
| R.addDecl(D); |
| return true; |
| } |
| diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp |
| index c8290ac5c31b..341d68fbb7cb 100644 |
| --- a/clang/lib/Serialization/ASTReader.cpp |
| +++ b/clang/lib/Serialization/ASTReader.cpp |
| @@ -928,8 +928,9 @@ ASTIdentifierLookupTraitBase::ReadKey(const unsigned char* d, unsigned n) { |
| /// Whether the given identifier is "interesting". |
| static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II, |
| bool IsModule) { |
| - return II.hadMacroDefinition() || II.isPoisoned() || |
| - (!IsModule && II.getObjCOrBuiltinID()) || |
| + return II.hadMacroDefinition() || |
| + II.isPoisoned() || |
| + (IsModule ? II.hasRevertedBuiltin() : II.getObjCOrBuiltinID()) || |
| II.hasRevertedTokenIDToIdentifier() || |
| (!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) && |
| II.getFETokenInfo()); |
| @@ -989,6 +990,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, |
| unsigned Bits = endian::readNext<uint16_t, little, unaligned>(d); |
| bool CPlusPlusOperatorKeyword = readBit(Bits); |
| bool HasRevertedTokenIDToIdentifier = readBit(Bits); |
| + bool HasRevertedBuiltin = readBit(Bits); |
| bool Poisoned = readBit(Bits); |
| bool ExtensionToken = readBit(Bits); |
| bool HadMacroDefinition = readBit(Bits); |
| @@ -1002,6 +1004,12 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, |
| II->revertTokenIDToIdentifier(); |
| if (!F.isModule()) |
| II->setObjCOrBuiltinID(ObjCOrBuiltinID); |
| + else if (HasRevertedBuiltin && II->getBuiltinID()) { |
| + II->revertBuiltin(); |
| + assert((II->hasRevertedBuiltin() || |
| + II->getObjCOrBuiltinID() == ObjCOrBuiltinID) && |
| + "Incorrect ObjC keyword or builtin ID"); |
| + } |
| assert(II->isExtensionToken() == ExtensionToken && |
| "Incorrect extension token flag"); |
| (void)ExtensionToken; |
| diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp |
| index 5f038b318e26..2cd5049d2800 100644 |
| --- a/clang/lib/Serialization/ASTWriter.cpp |
| +++ b/clang/lib/Serialization/ASTWriter.cpp |
| @@ -3277,8 +3277,9 @@ class ASTIdentifierTableTrait { |
| /// doesn't check whether the name has macros defined; use PublicMacroIterator |
| /// to check that. |
| bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) { |
| - if (MacroOffset || II->isPoisoned() || |
| - (!IsModule && II->getObjCOrBuiltinID()) || |
| + if (MacroOffset || |
| + II->isPoisoned() || |
| + (IsModule ? II->hasRevertedBuiltin() : II->getObjCOrBuiltinID()) || |
| II->hasRevertedTokenIDToIdentifier() || |
| (NeedDecls && II->getFETokenInfo())) |
| return true; |
| @@ -3374,6 +3375,7 @@ public: |
| Bits = (Bits << 1) | unsigned(HadMacroDefinition); |
| Bits = (Bits << 1) | unsigned(II->isExtensionToken()); |
| Bits = (Bits << 1) | unsigned(II->isPoisoned()); |
| + Bits = (Bits << 1) | unsigned(II->hasRevertedBuiltin()); |
| Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); |
| Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); |
| LE.write<uint16_t>(Bits); |
| diff --git a/clang/test/AST/ast-dump-attr.cpp b/clang/test/AST/ast-dump-attr.cpp |
| index c2bd768dc2ad..95491a02f8b2 100644 |
| --- a/clang/test/AST/ast-dump-attr.cpp |
| +++ b/clang/test/AST/ast-dump-attr.cpp |
| @@ -119,7 +119,6 @@ namespace Test { |
| extern "C" int printf(const char *format, ...);
|
| // CHECK: FunctionDecl{{.*}}printf
|
| // CHECK-NEXT: ParmVarDecl{{.*}}format{{.*}}'const char *'
|
| -// CHECK-NEXT: BuiltinAttr{{.*}}Implicit
|
| // CHECK-NEXT: FormatAttr{{.*}}Implicit printf 1 2
|
|
|
| alignas(8) extern int x;
|
| diff --git a/clang/test/CodeGen/builtin-redeclaration.c b/clang/test/CodeGen/builtin-redeclaration.c |
| deleted file mode 100644 |
| index 582907184ea5..000000000000 |
| --- a/clang/test/CodeGen/builtin-redeclaration.c |
| +++ /dev/null |
| @@ -1,16 +0,0 @@ |
| -// RUN: %clang_cc1 -emit-llvm-only %s |
| - |
| -// PR45410 |
| -// Ensure we mark local extern redeclarations with a different type as non-builtin. |
| -void non_builtin() { |
| - extern float exp(); |
| - exp(); // Will crash due to wrong number of arguments if this calls the builtin. |
| -} |
| - |
| -// PR45410 |
| -// We mark exp() builtin as const with -fno-math-errno (default). |
| -// We mustn't do that for extern redeclarations of builtins where the type differs. |
| -float attribute() { |
| - extern float exp(); |
| - return exp(1); |
| -} |
| diff --git a/clang/test/CodeGen/callback_pthread_create.c b/clang/test/CodeGen/callback_pthread_create.c |
| index 80457cb3ade3..d1b01b91eac3 100644 |
| --- a/clang/test/CodeGen/callback_pthread_create.c |
| +++ b/clang/test/CodeGen/callback_pthread_create.c |
| @@ -1,7 +1,3 @@ |
| -// FIXME: pthread_create() definition in Builtins.def doesn't match the real one, so it doesn't get recognized as a builtin and attributes aren't added. |
| -// RUN: false |
| -// XFAIL: * |
| - |
| // RUN: %clang_cc1 %s -S -emit-llvm -o - -disable-llvm-optzns | FileCheck %s |
| |
| // CHECK: declare !callback ![[cid:[0-9]+]] {{.*}}i32 @pthread_create |
| diff --git a/clang/test/CodeGenCXX/builtins.cpp b/clang/test/CodeGenCXX/builtins.cpp |
| index 5a95786beed5..242cba7bc14a 100644 |
| --- a/clang/test/CodeGenCXX/builtins.cpp |
| +++ b/clang/test/CodeGenCXX/builtins.cpp |
| @@ -1,19 +1,5 @@ |
| // RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s |
| |
| -// Builtins inside a namespace inside an extern "C" must be considered builtins. |
| -extern "C" { |
| -namespace X { |
| -double __builtin_fabs(double); |
| -float __builtin_fabsf(float) noexcept; |
| -} // namespace X |
| -} |
| - |
| -int o = X::__builtin_fabs(-2.0); |
| -// CHECK: @o ={{.*}} global i32 2, align 4 |
| - |
| -long p = X::__builtin_fabsf(-3.0f); |
| -// CHECK: @p ={{.*}} global i64 3, align 8 |
| - |
| // PR8839 |
| extern "C" char memmove(); |
| |
| diff --git a/clang/test/Sema/implicit-builtin-decl.c b/clang/test/Sema/implicit-builtin-decl.c |
| index 9434b507a3af..5ef13cf91df7 100644 |
| --- a/clang/test/Sema/implicit-builtin-decl.c |
| +++ b/clang/test/Sema/implicit-builtin-decl.c |
| @@ -1,4 +1,5 @@ |
| // RUN: %clang_cc1 -fsyntax-only -verify %s |
| +// RUN: not %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s |
| |
| void f() { |
| int *ptr = malloc(sizeof(int) * 10); // expected-warning{{implicitly declaring library function 'malloc' with type}} \ |
| @@ -61,5 +62,9 @@ extern float fmaxf(float, float); |
| struct __jmp_buf_tag {}; |
| void sigsetjmp(struct __jmp_buf_tag[1], int); |
| |
| +// CHECK: FunctionDecl {{.*}} <line:[[@LINE-2]]:1, col:44> col:6 sigsetjmp ' |
| +// CHECK-NOT: FunctionDecl |
| +// CHECK: ReturnsTwiceAttr {{.*}} <{{.*}}> Implicit |
| + |
| // PR40692 |
| void pthread_create(); // no warning expected |
| diff --git a/clang/test/Sema/warn-fortify-source.c b/clang/test/Sema/warn-fortify-source.c |
| index 5ad2979bc29c..0f93a687f007 100644 |
| --- a/clang/test/Sema/warn-fortify-source.c |
| +++ b/clang/test/Sema/warn-fortify-source.c |
| @@ -1,6 +1,8 @@ |
| // RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify |
| +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_PASS_OBJECT_SIZE |
| // RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS |
| // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify |
| +// RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_PASS_OBJECT_SIZE |
| // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS |
| |
| typedef unsigned long size_t; |
| @@ -11,7 +13,13 @@ extern "C" { |
| |
| extern int sprintf(char *str, const char *format, ...); |
| |
| -#if defined(USE_BUILTINS) |
| +#if defined(USE_PASS_OBJECT_SIZE) |
| +void *memcpy(void *dst, const void *src, size_t c); |
| +static void *memcpy(void *dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) __asm__("merp"); |
| +static void *memcpy(void *const dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) { |
| + return 0; |
| +} |
| +#elif defined(USE_BUILTINS) |
| #define memcpy(x,y,z) __builtin_memcpy(x,y,z) |
| #else |
| void *memcpy(void *dst, const void *src, size_t c); |
| @@ -37,7 +45,14 @@ void call_memcpy_type() { |
| }; |
| struct pair p; |
| char buf[20]; |
| - memcpy(&p.first, buf, 20); // expected-warning {{memcpy' will always overflow; destination buffer has size 8, but size argument is 20}} |
| + memcpy(&p.first, buf, 20); |
| +#ifdef USE_PASS_OBJECT_SIZE |
| + // Use the more strict checking mode on the pass_object_size attribute: |
| + // expected-warning@-3 {{memcpy' will always overflow; destination buffer has size 4, but size argument is 20}} |
| +#else |
| + // Or just fallback to type 0: |
| + // expected-warning@-6 {{memcpy' will always overflow; destination buffer has size 8, but size argument is 20}} |
| +#endif |
| } |
| |
| void call_strncat() { |
| diff --git a/clang/test/SemaCXX/cxx11-compat.cpp b/clang/test/SemaCXX/cxx11-compat.cpp |
| index f17c900201f7..07cd6b1fcf93 100644 |
| --- a/clang/test/SemaCXX/cxx11-compat.cpp |
| +++ b/clang/test/SemaCXX/cxx11-compat.cpp |
| @@ -31,7 +31,7 @@ struct S { |
| s = { n }, // expected-warning {{non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list in C++11}} expected-note {{explicit cast}} |
| t = { 1234 }; // expected-warning {{constant expression evaluates to 1234 which cannot be narrowed to type 'char' in C++11}} expected-warning {{changes value}} expected-note {{explicit cast}} |
| |
| -#define PRIuS "zu" |
| +#define PRIuS "uS" |
| int printf(const char *, ...); |
| typedef __typeof(sizeof(int)) size_t; |
| void h(size_t foo, size_t bar) { |
| diff --git a/clang/test/SemaCXX/warn-unused-local-typedef.cpp b/clang/test/SemaCXX/warn-unused-local-typedef.cpp |
| index 554ea37eeb28..7e893ba506a5 100644 |
| --- a/clang/test/SemaCXX/warn-unused-local-typedef.cpp |
| +++ b/clang/test/SemaCXX/warn-unused-local-typedef.cpp |
| @@ -67,10 +67,10 @@ int printf(char const *, ...); |
| |
| void test() { |
| typedef signed long int superint; // no diag |
| - printf("%ld", (superint)42); |
| + printf("%f", (superint) 42); |
| |
| typedef signed long int superint2; // no diag |
| - printf("%ld", static_cast<superint2>(42)); |
| + printf("%f", static_cast<superint2>(42)); |
| |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wunused-local-typedef" |
| -- |
| 2.32.0.272.g935e593368-goog |
| |