145 changes: 58 additions & 87 deletions clang/lib/Headers/intrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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__
Expand All @@ -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);

Expand All @@ -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,
Expand All @@ -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 *);
Expand Down Expand Up @@ -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*);
Expand All @@ -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
Expand Down Expand Up @@ -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");
}
Expand All @@ -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

Expand Down Expand Up @@ -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;
Expand Down
5 changes: 0 additions & 5 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1573,11 +1573,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (SemaBuiltinSetjmp(TheCall))
return ExprError();
break;
case Builtin::BI_setjmp:
case Builtin::BI_setjmpex:
if (checkArgCount(*this, TheCall, 1))
return true;
break;
case Builtin::BI__builtin_classify_type:
if (checkArgCount(*this, TheCall, 1)) return true;
TheCall->setType(Context.IntTy);
Expand Down
129 changes: 76 additions & 53 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -2071,7 +2107,8 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,

// If we have a builtin without an associated type we should not emit a
// warning when we were not able to find a type for it.
if (Error == ASTContext::GE_Missing_type)
if (Error == ASTContext::GE_Missing_type ||
Context.BuiltinInfo.allowTypeMismatch(ID))
return nullptr;

// If we could not find a type for setjmp it is because the jmp_buf type was
Expand All @@ -2095,58 +2132,23 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Context.BuiltinInfo.isHeaderDependentFunction(ID))) {
Diag(Loc, diag::ext_implicit_lib_function_decl)
<< Context.BuiltinInfo.getName(ID) << R;
if (Context.BuiltinInfo.getHeaderName(ID) &&
!Diags.isIgnored(diag::ext_implicit_lib_function_decl, Loc))
if (const char *Header = Context.BuiltinInfo.getHeaderName(ID))
Diag(Loc, diag::note_include_header_or_declare)
<< Context.BuiltinInfo.getHeaderName(ID)
<< Context.BuiltinInfo.getName(ID);
<< Header << Context.BuiltinInfo.getName(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.
// FIXME: This is hideous. We need to teach PushOnScopeChains to
// 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;
Expand Down Expand Up @@ -3348,7 +3350,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.
Expand Down Expand Up @@ -3781,18 +3786,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;
}

Expand Down Expand Up @@ -9636,6 +9629,36 @@ 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;
LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
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);

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6158,6 +6158,7 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
Params.push_back(Parm);
}
OverloadDecl->setParams(Params);
Sema->mergeDeclAttributes(OverloadDecl, FDecl);
return OverloadDecl;
}

Expand Down
7 changes: 3 additions & 4 deletions clang/lib/Sema/SemaLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
12 changes: 2 additions & 10 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3276,9 +3276,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;
Expand Down Expand Up @@ -3385,7 +3384,6 @@ class ASTIdentifierTableTrait {
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);
Expand Down
1 change: 1 addition & 0 deletions clang/test/AST/ast-dump-attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions clang/test/CodeGen/builtin-redeclaration.c
Original file line number Diff line number Diff line change
@@ -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);
}
7 changes: 5 additions & 2 deletions clang/test/CodeGen/callback_pthread_create.c
Original file line number Diff line number Diff line change
@@ -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]+]]}
Expand Down
44 changes: 44 additions & 0 deletions clang/test/CodeGen/setjmp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: %clang_cc1 -x c %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -x c++ %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s

#ifdef __cplusplus
extern "C" {
#endif

struct __jmp_buf_tag { int n; };
int setjmp(struct __jmp_buf_tag*);
int sigsetjmp(struct __jmp_buf_tag*, int);
int _setjmp(struct __jmp_buf_tag*);
int __sigsetjmp(struct __jmp_buf_tag*, int);

typedef struct __jmp_buf_tag jmp_buf[1];
typedef struct __jmp_buf_tag sigjmp_buf[1];

#ifdef __cplusplus
}
#endif

void f() {
jmp_buf jb;
// CHECK: call {{.*}}@setjmp(
setjmp(jb);
// CHECK: call {{.*}}@sigsetjmp(
sigsetjmp(jb, 0);
// CHECK: call {{.*}}@_setjmp(
_setjmp(jb);
// CHECK: call {{.*}}@__sigsetjmp(
__sigsetjmp(jb, 0);
}

// CHECK: ; Function Attrs: returns_twice
// CHECK-NEXT: declare {{.*}} @setjmp(

// CHECK: ; Function Attrs: returns_twice
// CHECK-NEXT: declare {{.*}} @sigsetjmp(

// CHECK: ; Function Attrs: returns_twice
// CHECK-NEXT: declare {{.*}} @_setjmp(

// CHECK: ; Function Attrs: returns_twice
// CHECK-NEXT: declare {{.*}} @__sigsetjmp(

14 changes: 14 additions & 0 deletions clang/test/CodeGenCXX/builtins.cpp
Original file line number Diff line number Diff line change
@@ -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();

Expand Down
75 changes: 69 additions & 6 deletions clang/test/Sema/builtin-setjmp.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,73 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -DNO_JMP_BUF %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DNO_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DWRONG_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DRIGHT_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DONLY_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DNO_SETJMP %s -ast-dump 2>&1 | FileCheck %s --check-prefixes=CHECK1,CHECK2
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DNO_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DWRONG_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DRIGHT_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DONLY_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK2
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DNO_SETJMP %s -ast-dump | FileCheck %s --check-prefixes=CHECK2

#ifdef __cplusplus
extern "C" {
#endif

#ifdef NO_JMP_BUF
extern long setjmp(long *); // expected-warning {{declaration of built-in function 'setjmp' requires the declaration of the 'jmp_buf' type, commonly provided in the header <setjmp.h>.}}
#else
// This happens in some versions of glibc: the declaration of __sigsetjmp
// precedes the declaration of sigjmp_buf.
extern long setjmp(long *); // Can't check, so we trust that this is the right type
// FIXME: We could still diagnose the missing `jmp_buf` at the point of the call.
// c-no-diagnostics
#elif WRONG_JMP_BUF
typedef long jmp_buf;
// FIXME: Consider producing a similar warning in C++.
extern int setjmp(char); // c-warning {{incompatible redeclaration of library function 'setjmp'}}
// c-note@-1 {{'setjmp' is a builtin with type 'int (jmp_buf)' (aka 'int (long)')}}
#elif RIGHT_JMP_BUF
typedef long jmp_buf;
extern int setjmp(char); // expected-warning@8 {{incompatible redeclaration of library function 'setjmp'}}
// expected-note@8 {{'setjmp' is a builtin with type 'int (jmp_buf)' (aka 'int (long)')}}
extern int setjmp(long); // OK, right type.
#elif ONLY_JMP_BUF
typedef int *jmp_buf;
#endif

void use() {
setjmp(0);
#if NO_SETJMP
// cxx-error@-2 {{undeclared identifier 'setjmp'}}
// c-warning@-3 {{implicit declaration of function 'setjmp' is invalid in C99}}
#elif ONLY_JMP_BUF
// cxx-error@-5 {{undeclared identifier 'setjmp'}}
// c-warning@-6 {{implicitly declaring library function 'setjmp' with type 'int (jmp_buf)' (aka 'int (int *)')}}
// c-note@-7 {{include the header <setjmp.h> or explicitly provide a declaration for 'setjmp'}}
#else
// cxx-no-diagnostics
#endif

#ifdef NO_SETJMP
// In this case, the regular AST dump doesn't dump the implicit declaration of 'setjmp'.
#pragma clang __debug dump setjmp
#endif
}

// CHECK1: FunctionDecl {{.*}} used setjmp
// CHECK1: BuiltinAttr {{.*}} Implicit
// CHECK1: ReturnsTwiceAttr {{.*}} Implicit

// mingw declares _setjmp with an unusual signature.
int _setjmp(void *, void *);
#if !defined(NO_JMP_BUF) && !defined(NO_SETJMP)
// c-warning@-2 {{incompatible redeclaration of library function '_setjmp'}}
// c-note@-3 {{'_setjmp' is a builtin with type 'int (jmp_buf)'}}
#endif
void use_mingw() {
_setjmp(0, 0);
}

// CHECK2: FunctionDecl {{.*}} used _setjmp
// CHECK2: BuiltinAttr {{.*}} Implicit
// CHECK2: ReturnsTwiceAttr {{.*}} Implicit

#ifdef __cplusplus
}
#endif
10 changes: 2 additions & 8 deletions clang/test/Sema/implicit-builtin-decl.c
Original file line number Diff line number Diff line change
@@ -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}} \
Expand Down Expand Up @@ -55,17 +54,12 @@ main(int argc, char *argv[])

void snprintf() { }

// PR8316 & PR40692
void longjmp(); // expected-warning{{declaration of built-in function 'longjmp' requires the declaration of the 'jmp_buf' type, commonly provided in the header <setjmp.h>.}}
void longjmp();

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
void sigsetjmp(struct __jmp_buf_tag[1], int);

// PR40692
void pthread_create(); // no warning expected
19 changes: 2 additions & 17 deletions clang/test/Sema/warn-fortify-source.c
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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);
Expand All @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/cxx11-compat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions clang/test/SemaCXX/warn-unused-local-typedef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 8 additions & 0 deletions clang/test/SemaObjCXX/builtin-objcsuper.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: %clang_cc1 -verify %s
// expected-no-diagnostics

// objc_super has special lookup rules for compatibility with macOS headers, so
// the following should compile.
struct objc_super {};
extern "C" id objc_msgSendSuper(struct objc_super *super, SEL op, ...);
extern "C" void objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...);