Skip to content

Commit e09107a

Browse files
committed
[Sema] Introduce BuiltinAttr, per-declaration builtin-ness
Instead of relying on whether a certain identifier is a builtin, introduce BuiltinAttr to specify a declaration as having builtin semantics. This fixes incompatible redeclarations of builtins, as reverting the identifier as being builtin due to one incompatible redeclaration would have broken rest of the builtin calls. Mostly-compatible redeclarations of builtins also no longer have builtin semantics. They don't call the builtin nor inherit their attributes. A long-standing FIXME regarding builtins inside a namespace enclosed in extern "C" not being recognized is also addressed. Due to the more correct handling attributes for builtin functions are added in more places, resulting in more useful warnings. Tests are updated to reflect that. Intrinsics without an inline definition in intrin.h had `inline` and `static` removed as they had no effect and caused them to no longer be recognized as builtins otherwise. A pthread_create() related test is XFAIL-ed, as it relied on it being recognized as a builtin based on its name. The builtin declaration syntax is too restrictive and doesn't allow custom structs, function pointers, etc. It seems to be the only case and fixing this would require reworking the current builtin syntax, so this seems acceptable. Fixes PR45410. Reviewed By: rsmith, yutsumi Differential Revision: https://reviews.llvm.org/D77491
1 parent 50dd545 commit e09107a

19 files changed

+192
-214
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3526,3 +3526,11 @@ def ReleaseHandle : InheritableParamAttr {
35263526
let Subjects = SubjectList<[ParmVar]>;
35273527
let Documentation = [ReleaseHandleDocs];
35283528
}
3529+
3530+
def Builtin : InheritableAttr {
3531+
let Spellings = [];
3532+
let Args = [UnsignedArgument<"ID">];
3533+
let Subjects = SubjectList<[Function]>;
3534+
let SemaHandler = 0;
3535+
let Documentation = [Undocumented];
3536+
}

clang/include/clang/Basic/Builtins.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,7 @@ LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_GNU_LANGUAGES)
10201020
LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_GNU_LANGUAGES)
10211021
LIBBUILTIN(vfork, "p", "fj", "unistd.h", ALL_LANGUAGES)
10221022
// POSIX pthread.h
1023+
// FIXME: Should specify argument types.
10231024
LIBBUILTIN(pthread_create, "", "fC<2,3>", "pthread.h", ALL_GNU_LANGUAGES)
10241025

10251026
// POSIX setjmp.h

clang/include/clang/Basic/IdentifierTable.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -225,18 +225,6 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
225225
}
226226
void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
227227

228-
/// True if setNotBuiltin() was called.
229-
bool hasRevertedBuiltin() const {
230-
return ObjCOrBuiltinID == tok::NUM_OBJC_KEYWORDS;
231-
}
232-
233-
/// Revert the identifier to a non-builtin identifier. We do this if
234-
/// the name of a known builtin library function is used to declare that
235-
/// function, but an unexpected type is specified.
236-
void revertBuiltin() {
237-
setBuiltinID(0);
238-
}
239-
240228
/// Return a value indicating whether this is a builtin function.
241229
///
242230
/// 0 is not-built-in. 1+ are specific builtin functions.

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4109,6 +4109,8 @@ class Sema final {
41094109
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
41104110
SourceLocation IdLoc,
41114111
bool TypoCorrection = false);
4112+
FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID,
4113+
SourceLocation Loc);
41124114
NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
41134115
Scope *S, bool ForRedeclaration,
41144116
SourceLocation Loc);

clang/lib/AST/Decl.cpp

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3163,44 +3163,24 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
31633163
/// functions as their wrapped builtins. This shouldn't be done in general, but
31643164
/// it's useful in Sema to diagnose calls to wrappers based on their semantics.
31653165
unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
3166-
unsigned BuiltinID;
3166+
unsigned BuiltinID = 0;
31673167

31683168
if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
31693169
BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
3170-
} else {
3171-
if (!getIdentifier())
3172-
return 0;
3173-
3174-
BuiltinID = getIdentifier()->getBuiltinID();
3170+
} else if (const auto *A = getAttr<BuiltinAttr>()) {
3171+
BuiltinID = A->getID();
31753172
}
31763173

31773174
if (!BuiltinID)
31783175
return 0;
31793176

3180-
ASTContext &Context = getASTContext();
3181-
if (Context.getLangOpts().CPlusPlus) {
3182-
const auto *LinkageDecl =
3183-
dyn_cast<LinkageSpecDecl>(getFirstDecl()->getDeclContext());
3184-
// In C++, the first declaration of a builtin is always inside an implicit
3185-
// extern "C".
3186-
// FIXME: A recognised library function may not be directly in an extern "C"
3187-
// declaration, for instance "extern "C" { namespace std { decl } }".
3188-
if (!LinkageDecl) {
3189-
if (BuiltinID == Builtin::BI__GetExceptionInfo &&
3190-
Context.getTargetInfo().getCXXABI().isMicrosoft())
3191-
return Builtin::BI__GetExceptionInfo;
3192-
return 0;
3193-
}
3194-
if (LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
3195-
return 0;
3196-
}
3197-
31983177
// If the function is marked "overloadable", it has a different mangled name
31993178
// and is not the C library function.
32003179
if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() &&
32013180
!hasAttr<ArmBuiltinAliasAttr>())
32023181
return 0;
32033182

3183+
ASTContext &Context = getASTContext();
32043184
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
32053185
return BuiltinID;
32063186

0 commit comments

Comments
 (0)