summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgit apple-llvm automerger <am@git-apple-llvm>2020-12-14 17:46:25 -0800
committergit apple-llvm automerger <am@git-apple-llvm>2020-12-14 19:43:12 -0500
commit1c923ddfd25552bdfdd5330c45cfb85ce1106ca5 (patch)
treebfc55290ab3c63f7db3bc345293b4d314fadc8b5
parent2ddc39c42d6223fb8f2fd0bd89ee6c1dc40005c8 (diff)
parentadf845300c9cc023d386d97b6ebeb1e82bd97763 (diff)
downloadllvm-1c923ddfd25552bdfdd5330c45cfb85ce1106ca5.tar.gz
Merge commit 'adf845300c9c' from llvm.org/release/11.x into apple/stable/20200714
-rw-r--r--clang/include/clang/Basic/Attr.td8
-rw-r--r--clang/include/clang/Basic/Builtins.def1
-rw-r--r--clang/include/clang/Basic/IdentifierTable.h12
-rw-r--r--clang/include/clang/Sema/Sema.h2
-rw-r--r--clang/lib/AST/Decl.cpp28
-rw-r--r--clang/lib/Headers/intrin.h145
-rw-r--r--clang/lib/Sema/SemaDecl.cpp119
-rw-r--r--clang/lib/Sema/SemaExpr.cpp1
-rw-r--r--clang/lib/Sema/SemaLookup.cpp7
-rw-r--r--clang/lib/Serialization/ASTReader.cpp12
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp6
-rw-r--r--clang/test/AST/ast-dump-attr.cpp1
-rw-r--r--clang/test/CodeGen/builtin-redeclaration.c16
-rw-r--r--clang/test/CodeGen/callback_pthread_create.c7
-rw-r--r--clang/test/CodeGenCXX/builtins.cpp14
-rw-r--r--clang/test/Sema/implicit-builtin-decl.c5
-rw-r--r--clang/test/Sema/warn-fortify-source.c19
-rw-r--r--clang/test/SemaCXX/cxx11-compat.cpp2
-rw-r--r--clang/test/SemaCXX/warn-unused-local-typedef.cpp4
19 files changed, 193 insertions, 216 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index ba4358d51f59..2e5e33c26af3 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3594,3 +3594,11 @@ def ReleaseHandle : InheritableParamAttr {
let Subjects = SubjectList<[ParmVar]>;
let Documentation = [ReleaseHandleDocs];
}
+
+def Builtin : InheritableAttr {
+ let Spellings = [];
+ let Args = [UnsignedArgument<"ID">];
+ let Subjects = SubjectList<[Function]>;
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index 5043b07b85f5..f7c281a06276 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -1017,6 +1017,7 @@ LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_GNU_LANGUAGES)
LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_GNU_LANGUAGES)
LIBBUILTIN(vfork, "p", "fj", "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 5e6452a97c7b..df514f2c9c4c 100644
--- a/clang/include/clang/Basic/IdentifierTable.h
+++ b/clang/include/clang/Basic/IdentifierTable.h
@@ -221,18 +221,6 @@ 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 98a87a5062a0..0aff22aff2f6 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3990,6 +3990,8 @@ 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 9815f0648ad7..0ee1399d42df 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3163,44 +3163,24 @@ 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;
+ unsigned BuiltinID = 0;
if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
- } else {
- if (!getIdentifier())
- return 0;
-
- BuiltinID = getIdentifier()->getBuiltinID();
+ } else if (const auto *A = getAttr<BuiltinAttr>()) {
+ BuiltinID = A->getID();
}
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>())
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 871b47ca8267..e7b76a3bb2ed 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -57,16 +57,11 @@ 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);
@@ -82,13 +77,9 @@ 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);
@@ -105,23 +96,16 @@ 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);
@@ -136,7 +120,6 @@ 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);
@@ -146,11 +129,8 @@ 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);
@@ -169,12 +149,10 @@ long _InterlockedExchangeAdd_HLEAcquire(long volatile *, long);
long _InterlockedExchangeAdd_HLERelease(long volatile *, long);
__int64 _InterlockedExchangeAdd64_HLEAcquire(__int64 volatile *, __int64);
__int64 _InterlockedExchangeAdd64_HLERelease(__int64 volatile *, __int64);
-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);
+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);
unsigned int _rorx_u32(unsigned int, const unsigned int);
int _sarx_i32(int, unsigned int);
#if __STDC_HOSTED__
@@ -185,9 +163,8 @@ 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 *);
-static __inline__ void
-__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
-_WriteBarrier(void);
+void __attribute__((__deprecated__(
+ "use other intrinsics or C++11 atomics instead"))) _WriteBarrier(void);
unsigned __int32 xbegin(void);
void _xend(void);
@@ -197,19 +174,14 @@ 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,
@@ -218,7 +190,6 @@ 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 *);
@@ -269,13 +240,9 @@ 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*);
@@ -284,29 +251,19 @@ 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
@@ -475,40 +432,56 @@ __int64 _InterlockedCompareExchange64_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");
}
@@ -518,26 +491,25 @@ __stosq(unsigned __int64 *__dst, unsigned __int64 __x, size_t __n) {
|* Misc
\*----------------------------------------------------------------------------*/
#if defined(__i386__) || defined(__x86_64__)
-static __inline__ void __DEFAULT_FN_ATTRS
-__cpuid(int __info[4], int __level) {
- __asm__ ("cpuid" : "=a"(__info[0]), "=b" (__info[1]), "=c"(__info[2]), "=d"(__info[3])
- : "a"(__level), "c"(0));
+static __inline__ void __DEFAULT_FN_ATTRS __cpuid(int __info[4], int __level) {
+ __asm__("cpuid"
+ : "=a"(__info[0]), "=b"(__info[1]), "=c"(__info[2]), "=d"(__info[3])
+ : "a"(__level), "c"(0));
}
-static __inline__ void __DEFAULT_FN_ATTRS
-__cpuidex(int __info[4], int __level, int __ecx) {
- __asm__ ("cpuid" : "=a"(__info[0]), "=b" (__info[1]), "=c"(__info[2]), "=d"(__info[3])
- : "a"(__level), "c"(__ecx));
+static __inline__ void __DEFAULT_FN_ATTRS __cpuidex(int __info[4], int __level,
+ int __ecx) {
+ __asm__("cpuid"
+ : "=a"(__info[0]), "=b"(__info[1]), "=c"(__info[2]), "=d"(__info[3])
+ : "a"(__level), "c"(__ecx));
}
-static __inline__ void __DEFAULT_FN_ATTRS
-__halt(void) {
- __asm__ volatile ("hlt");
+static __inline__ void __DEFAULT_FN_ATTRS __halt(void) {
+ __asm__ volatile("hlt");
}
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
-static __inline__ void __DEFAULT_FN_ATTRS
-__nop(void) {
- __asm__ volatile ("nop");
+static __inline__ void __DEFAULT_FN_ATTRS __nop(void) {
+ __asm__ volatile("nop");
}
#endif
@@ -574,8 +546,7 @@ __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 05fd8209fd38..0383a07bc906 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2054,6 +2054,42 @@ 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
@@ -2105,40 +2141,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
if (R.isNull())
return nullptr;
- 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);
+ FunctionDecl *New = CreateBuiltin(II, R, ID, Loc);
RegisterLocallyScopedExternCDecl(New, S);
// TUScope is the translation-unit scope to insert this function into.
@@ -2146,7 +2149,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 = Parent;
+ CurContext = New->getDeclContext();
PushOnScopeChains(New, TUScope);
CurContext = SavedContext;
return New;
@@ -3353,7 +3356,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
// there but not here.
NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
RequiresAdjustment = true;
- } else if (New->getBuiltinID()) {
+ } 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.
+
// 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.
@@ -3786,18 +3792,6 @@ 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;
}
@@ -9641,6 +9635,35 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
+ // In C builtins get merged with implicitly lazily created declarations.
+ // In C++ we need to check if it's a builtin and add the BuiltinAttr here.
+ if (getLangOpts().CPlusPlus) {
+ if (IdentifierInfo *II = Previous.getLookupName().getAsIdentifierInfo()) {
+ if (unsigned BuiltinID = II->getBuiltinID()) {
+ if (NewFD->getLanguageLinkage() == CLanguageLinkage) {
+ // Declarations for builtins with custom typechecking by definition
+ // don't make sense. Don't attempt typechecking and simply add the
+ // attribute.
+ if (Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) {
+ NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
+ } else {
+ ASTContext::GetBuiltinTypeError Error;
+ 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 e0521e0d16b4..fa3cd0ea62a5 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6170,6 +6170,7 @@ 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 5757eaf3fac0..bcbecd545398 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -894,10 +894,9 @@ bool Sema::LookupBuiltin(LookupResult &R) {
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return false;
- if (NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II,
- BuiltinID, TUScope,
- R.isForRedeclaration(),
- R.getNameLoc())) {
+ if (NamedDecl *D =
+ LazilyCreateBuiltin(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 529ffdf9d404..52d63247b98b 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -908,9 +908,8 @@ 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.hasRevertedBuiltin() : II.getObjCOrBuiltinID()) ||
+ return II.hadMacroDefinition() || II.isPoisoned() ||
+ (!IsModule && II.getObjCOrBuiltinID()) ||
II.hasRevertedTokenIDToIdentifier() ||
(!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) &&
II.getFETokenInfo());
@@ -970,7 +969,6 @@ 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);
@@ -984,12 +982,6 @@ 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 f490d2814aa6..d79c6e255b23 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -3273,9 +3273,8 @@ 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->hasRevertedBuiltin() : II->getObjCOrBuiltinID()) ||
+ if (MacroOffset || II->isPoisoned() ||
+ (!IsModule && II->getObjCOrBuiltinID()) ||
II->hasRevertedTokenIDToIdentifier() ||
(NeedDecls && II->getFETokenInfo()))
return true;
@@ -3380,7 +3379,6 @@ 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 95491a02f8b2..c2bd768dc2ad 100644
--- a/clang/test/AST/ast-dump-attr.cpp
+++ b/clang/test/AST/ast-dump-attr.cpp
@@ -119,6 +119,7 @@ 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
new file mode 100644
index 000000000000..582907184ea5
--- /dev/null
+++ b/clang/test/CodeGen/builtin-redeclaration.c
@@ -0,0 +1,16 @@
+// 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 785440030b32..b9eb6e18bbd7 100644
--- a/clang/test/CodeGen/callback_pthread_create.c
+++ b/clang/test/CodeGen/callback_pthread_create.c
@@ -1,5 +1,8 @@
-// RUN: %clang_cc1 -O1 %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -O1 %s -S -emit-llvm -o - | opt -ipconstprop -S | FileCheck --check-prefix=IPCP %s
+// 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
// CHECK: ![[cid]] = !{![[cidb:[0-9]+]]}
diff --git a/clang/test/CodeGenCXX/builtins.cpp b/clang/test/CodeGenCXX/builtins.cpp
index 242cba7bc14a..b0378322f97e 100644
--- a/clang/test/CodeGenCXX/builtins.cpp
+++ b/clang/test/CodeGenCXX/builtins.cpp
@@ -1,5 +1,19 @@
// 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 3a3dfa935ac1..b25e86bc03a3 100644
--- a/clang/test/Sema/implicit-builtin-decl.c
+++ b/clang/test/Sema/implicit-builtin-decl.c
@@ -1,5 +1,4 @@
// 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}} \
@@ -63,9 +62,5 @@ extern float fmaxf(float, float);
struct __jmp_buf_tag {};
void sigsetjmp(struct __jmp_buf_tag[1], int); // expected-warning{{declaration of built-in function 'sigsetjmp' requires the declaration of the 'jmp_buf' type, commonly provided in the header <setjmp.h>.}}
-// 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 0f93a687f007..5ad2979bc29c 100644
--- a/clang/test/Sema/warn-fortify-source.c
+++ b/clang/test/Sema/warn-fortify-source.c
@@ -1,8 +1,6 @@
// 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;
@@ -13,13 +11,7 @@ extern "C" {
extern int sprintf(char *str, const char *format, ...);
-#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)
+#if defined(USE_BUILTINS)
#define memcpy(x,y,z) __builtin_memcpy(x,y,z)
#else
void *memcpy(void *dst, const void *src, size_t c);
@@ -45,14 +37,7 @@ void call_memcpy_type() {
};
struct pair p;
char buf[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
+ memcpy(&p.first, buf, 20); // expected-warning {{memcpy' will always overflow; destination buffer has size 8, but size argument is 20}}
}
void call_strncat() {
diff --git a/clang/test/SemaCXX/cxx11-compat.cpp b/clang/test/SemaCXX/cxx11-compat.cpp
index 07cd6b1fcf93..f17c900201f7 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 "uS"
+#define PRIuS "zu"
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 7e893ba506a5..554ea37eeb28 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("%f", (superint) 42);
+ printf("%ld", (superint)42);
typedef signed long int superint2; // no diag
- printf("%f", static_cast<superint2>(42));
+ printf("%ld", static_cast<superint2>(42));
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-local-typedef"