tambre updated this revision to Diff 264497.
tambre marked an inline comment as not done.
tambre added a comment.
Semantic compatibility checking for C++ builtin redeclarations.
Remove some now unnecessary logic from getBuiltinID().
Update more tests. 4 tests still failing.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D77491/new/
https://reviews.llvm.org/D77491
Files:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/IdentifierTable.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/Decl.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaLookup.cpp
clang/test/AST/ast-dump-attr.cpp
clang/test/CodeGen/builtin-redeclaration.c
clang/test/CodeGen/callback_pthread_create.c
clang/test/CodeGen/ms-intrinsics.c
clang/test/Sema/implicit-builtin-decl.c
clang/test/Sema/warn-fortify-source.c
clang/test/SemaCXX/cxx11-compat.cpp
clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
clang/test/SemaCXX/warn-unused-local-typedef.cpp
Index: clang/test/SemaCXX/warn-unused-local-typedef.cpp
===================================================================
--- clang/test/SemaCXX/warn-unused-local-typedef.cpp
+++ clang/test/SemaCXX/warn-unused-local-typedef.cpp
@@ -67,10 +67,10 @@
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"
Index: clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
===================================================================
--- clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
+++ clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
@@ -117,7 +117,7 @@
namespace Builtins {
// Pick two functions that ought to have the same noexceptness.
extern "C" int strcmp(const char *, const char *);
- extern "C" int strncmp(const char *, const char *, decltype(sizeof(0))) noexcept;
+ extern "C" int strncmp(const char *, const char *, decltype(sizeof(0)));
// Check we recognized both as builtins.
typedef int arr[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)];
Index: clang/test/SemaCXX/cxx11-compat.cpp
===================================================================
--- clang/test/SemaCXX/cxx11-compat.cpp
+++ clang/test/SemaCXX/cxx11-compat.cpp
@@ -31,7 +31,7 @@
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) {
Index: clang/test/Sema/warn-fortify-source.c
===================================================================
--- clang/test/Sema/warn-fortify-source.c
+++ clang/test/Sema/warn-fortify-source.c
@@ -1,10 +1,12 @@
// 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
+// FIXME: Incompatible builtin redeclarations aren't considered builtins and thus don't call the builtin nor inherit their attributes.
+// %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_PASS_OBJECT_SIZE
+// %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_PASS_OBJECT_SIZE
+
typedef unsigned long size_t;
#ifdef __cplusplus
Index: clang/test/Sema/implicit-builtin-decl.c
===================================================================
--- clang/test/Sema/implicit-builtin-decl.c
+++ clang/test/Sema/implicit-builtin-decl.c
@@ -60,12 +60,15 @@
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>.}}
+typedef struct __jmp_buf_tag {
+} sigjmp_buf[1];
-// CHECK: FunctionDecl {{.*}} <line:[[@LINE-2]]:1, col:44> col:6 sigsetjmp '
+int sigsetjmp(struct __jmp_buf_tag[1], int);
+
+// CHECK: FunctionDecl {{.*}} <line:[[@LINE-2]]:5> col:5 implicit sigsetjmp '
+// CHECK: FunctionDecl {{.*}} <col:1, col:43> col:5 sigsetjmp '
// CHECK-NOT: FunctionDecl
-// CHECK: ReturnsTwiceAttr {{.*}} <{{.*}}> Implicit
+// CHECK: ReturnsTwiceAttr {{.*}} <{{.*}}> Inherited Implicit
// PR40692
void pthread_create(); // no warning expected
Index: clang/test/CodeGen/ms-intrinsics.c
===================================================================
--- clang/test/CodeGen/ms-intrinsics.c
+++ clang/test/CodeGen/ms-intrinsics.c
@@ -17,6 +17,7 @@
#include <intrin.h>
+// FIXME: Why aren't these builtins recognized as builtins?
#if defined(__i386__) || defined(__x86_64__)
void test__stosb(unsigned char *Dest, unsigned char Data, size_t Count) {
return __stosb(Dest, Data, Count);
Index: clang/test/CodeGen/callback_pthread_create.c
===================================================================
--- clang/test/CodeGen/callback_pthread_create.c
+++ clang/test/CodeGen/callback_pthread_create.c
@@ -14,6 +14,7 @@
typedef __darwin_pthread_t pthread_t;
typedef __darwin_pthread_attr_t pthread_attr_t;
+// FIXME: Why isn't this recognized as a builtin?
int pthread_create(pthread_t *, const pthread_attr_t *,
void *(*)(void *), void *);
//}
Index: clang/test/CodeGen/builtin-redeclaration.c
===================================================================
--- /dev/null
+++ 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);
+}
Index: clang/test/AST/ast-dump-attr.cpp
===================================================================
--- clang/test/AST/ast-dump-attr.cpp
+++ clang/test/AST/ast-dump-attr.cpp
@@ -109,6 +109,7 @@
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;
Index: clang/lib/Sema/SemaLookup.cpp
===================================================================
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -894,10 +894,9 @@
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;
}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -6044,6 +6044,7 @@
Params.push_back(Parm);
}
OverloadDecl->setParams(Params);
+ Sema->mergeDeclAttributes(OverloadDecl, FDecl);
return OverloadDecl;
}
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -2040,6 +2040,48 @@
llvm_unreachable("unhandled error kind");
}
+FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, 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;
+ }
+
+ ASTContext::GetBuiltinTypeError Error;
+ QualType R = Context.GetBuiltinType(ID, Error);
+
+ if (Error || R.isNull())
+ return nullptr;
+
+ FunctionDecl *New =
+ FunctionDecl::Create(Context, Parent, Loc, Loc, II, R, /*TInfo=*/nullptr,
+ SC_Extern, false, R->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>(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);
+ 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
@@ -2091,40 +2133,7 @@
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, ID, Loc);
RegisterLocallyScopedExternCDecl(New, S);
// TUScope is the translation-unit scope to insert this function into.
@@ -2132,7 +2141,7 @@
// 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;
@@ -3330,7 +3339,11 @@
// 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.
+ // Check if the old is a builtin.
+ // TODO: Maybe we should only warn if the redeclaration is compatible?
+
// 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.
@@ -9592,6 +9605,24 @@
}
}
+ // 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()) {
+ // FIXME: A recognised library function may not be directly in an extern
+ // "C" declaration, for instance "extern "C" { namespace std { decl }
+ // }".
+ FunctionDecl *D = CreateBuiltin(II, BuiltinID, NewFD->getLocation());
+ if ((D && Context.typesAreCompatible(NewFD->getType(), D->getType())) ||
+ (BuiltinID == Builtin::BI__GetExceptionInfo &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft()))
+ NewFD->addAttr(
+ BuiltinAttr::CreateImplicit(Context, II->getBuiltinID()));
+ }
+ }
+ }
+
ProcessPragmaWeak(S, NewFD);
checkAttributesAfterMerging(*this, *NewFD);
Index: clang/lib/AST/Decl.cpp
===================================================================
--- clang/lib/AST/Decl.cpp
+++ clang/lib/AST/Decl.cpp
@@ -3164,39 +3164,24 @@
if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
} else {
- if (!getIdentifier())
+ const auto *Attr = getAttr<BuiltinAttr>();
+
+ if (!Attr)
return 0;
- BuiltinID = getIdentifier()->getBuiltinID();
+ BuiltinID = Attr->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;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3899,6 +3899,8 @@
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
SourceLocation IdLoc,
bool TypoCorrection = false);
+ FunctionDecl *CreateBuiltin(IdentifierInfo *II, unsigned ID,
+ SourceLocation Loc);
NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Scope *S, bool ForRedeclaration,
SourceLocation Loc);
Index: clang/include/clang/Basic/IdentifierTable.h
===================================================================
--- clang/include/clang/Basic/IdentifierTable.h
+++ clang/include/clang/Basic/IdentifierTable.h
@@ -225,7 +225,7 @@
}
void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
- /// True if setNotBuiltin() was called.
+ /// True if revertBuiltin() was called.
bool hasRevertedBuiltin() const {
return ObjCOrBuiltinID == tok::NUM_OBJC_KEYWORDS;
}
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -3440,3 +3440,11 @@
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];
+}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits