From 782fa308a765aeac2acb39c4e697c937ec21185b Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Tue, 28 Jul 2009 02:25:19 +0000 Subject: [PATCH] Make longjmp a real builtin. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77291 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 34 ++++++++++++++++++++-- include/clang/Basic/Builtins.def | 10 ++++++- include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ include/clang/Frontend/PCHBitCodes.h | 6 +++- lib/AST/ASTContext.cpp | 23 +++++++++++++-- lib/Frontend/PCHReader.cpp | 22 ++++++++++++++ lib/Frontend/PCHWriter.cpp | 2 ++ lib/Sema/SemaDecl.cpp | 31 +++++++++++++++----- 8 files changed, 116 insertions(+), 14 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 7768ba49d5..c7faefc17f 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -130,6 +130,12 @@ class ASTContext { /// \brief The type for the C FILE type. TypeDecl *FILEDecl; + /// \brief The type for the C FILE type. + TypeDecl *jmp_bufDecl; + + /// \brief The type for the C FILE type. + TypeDecl *sigjmp_bufDecl; + /// \brief Keeps track of all declaration attributes. /// /// Since so few decls have attrs, we keep them in a hash map instead of @@ -499,6 +505,28 @@ public: return getTypeDeclType(FILEDecl); return QualType(); } + + /// \brief Set the type for the C jmp_buf type. + void setjmp_bufDecl(TypeDecl *jmp_bufDecl) + { this->jmp_bufDecl = jmp_bufDecl; } + + /// \brief Retrieve the C jmp_buf type. + QualType getjmp_bufType() { + if (jmp_bufDecl) + return getTypeDeclType(jmp_bufDecl); + return QualType(); + } + + /// \brief Set the type for the C sigjmp_buf type. + void setsigjmp_bufDecl(TypeDecl *sigjmp_bufDecl) + { this->sigjmp_bufDecl = sigjmp_bufDecl; } + + /// \brief Retrieve the C sigjmp_buf type. + QualType getsigjmp_bufType() { + if (sigjmp_bufDecl) + return getTypeDeclType(sigjmp_bufDecl); + return QualType(); + } /// getObjCEncodingForType - Emit the ObjC type encoding for the /// given type into \arg S. If \arg NameFields is specified then @@ -558,8 +586,10 @@ public: const IdentifierInfo *Name); enum GetBuiltinTypeError { - GE_None, //< No error - GE_Missing_FILE //< Missing the FILE type from + GE_None, //< No error + GE_Missing_FILE, //< Missing the FILE type from + GE_Missing_jmp_buf, //< Missing the jmp_buf type from + GE_Missing_sigjmp_buf //< Missing the sigjmp_buf type from }; /// GetBuiltinType - Return the type for the specified builtin. diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index b2d31f2215..0ac2fab8a0 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -36,6 +36,8 @@ // A -> "reference" to __builtin_va_list // V -> Vector, following num elements and a base type. // P -> FILE +// J -> jmp_buf +// SJ -> sigjmp_buf // . -> "...". This may only occur at the end of the function list. // // Types maybe prefixed with the following modifiers: @@ -338,7 +340,6 @@ BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n") LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h") LIBBUILTIN(exit, "vi", "fr", "stdlib.h") LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h") -LIBBUILTIN(_exit, "vi", "fr", "unistd.h") LIBBUILTIN(malloc, "v*z", "f", "stdlib.h") LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h") // C99 string.h @@ -369,6 +370,8 @@ LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h") LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h") LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h") LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h") +// C99 +LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h") // Non-C library functions // FIXME: Non-C-standard stuff shouldn't be builtins in non-GNU mode! @@ -381,6 +384,11 @@ LIBBUILTIN(strndup, "c*cC*z", "f", "string.h") // POSIX strings.h LIBBUILTIN(index, "c*cC*i", "f", "strings.h") LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h") +// POSIX unistd.h +LIBBUILTIN(_exit, "vi", "fr", "unistd.h") +// POSIX setjmp.h +LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h") +LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h") // FIXME: This type isn't very correct, it should be // id objc_msgSend(id, SEL) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 03d552dd43..b7e940457f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -120,6 +120,8 @@ def note_please_include_header : Note< def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">; def err_implicit_decl_requires_stdio : Error< "implicit declaration of '%0' requires inclusion of the header ">; +def err_implicit_decl_requires_setjmp : Error< + "implicit declaration of '%0' requires inclusion of the header ">; def warn_redecl_library_builtin : Warning< "incompatible redeclaration of library function %0">; def err_builtin_definition : Error<"definition of builtin function %0">; diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 926ba224f4..15f5518210 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -423,7 +423,11 @@ namespace clang { /// \brief Objective-C fast enumeration state type SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE = 6, /// \brief C FILE typedef type - SPECIAL_TYPE_FILE = 7 + SPECIAL_TYPE_FILE = 7, + /// \brief C jmp_buf typedef type + SPECIAL_TYPE_jmp_buf = 8, + /// \brief C sigjmp_buf typedef type + SPECIAL_TYPE_sigjmp_buf = 9 }; /// \brief Record codes for each kind of declaration. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index f7e1e3fdff..ce58eeef44 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -38,8 +38,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, Builtin::Context &builtins, bool FreeMem, unsigned size_reserve) : GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), - ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), - SourceMgr(SM), LangOpts(LOpts), + ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), + sigjmp_bufDecl(0), SourceMgr(SM), LangOpts(LOpts), LoadedExternalComments(false), FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels), BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) { @@ -3913,6 +3913,25 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, break; } } + case 'J': { + if (Signed) { + Type = Context.getsigjmp_bufType(); + if (Type.isNull()) { + Error = ASTContext::GE_Missing_sigjmp_buf; + return QualType(); + } else { + break; + } + } else { + Type = Context.getjmp_bufType(); + if (Type.isNull()) { + Error = ASTContext::GE_Missing_jmp_buf; + return QualType(); + } else { + break; + } + } + } } if (!AllowTypeModifiers) diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index f21fc62522..8665705f68 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1540,6 +1540,28 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { Context->setFILEDecl(Tag->getDecl()); } } + if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) { + QualType Jmp_bufType = GetType(Jmp_buf); + assert(!Jmp_bufType.isNull() && "jmp_bug type is NULL"); + if (const TypedefType *Typedef = Jmp_bufType->getAsTypedefType()) + Context->setjmp_bufDecl(Typedef->getDecl()); + else { + const TagType *Tag = Jmp_bufType->getAsTagType(); + assert(Tag && "Invalid jmp_bug type in PCH file"); + Context->setjmp_bufDecl(Tag->getDecl()); + } + } + if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) { + QualType Sigjmp_bufType = GetType(Sigjmp_buf); + assert(!Sigjmp_bufType.isNull() && "sigjmp_buf type is NULL"); + if (const TypedefType *Typedef = Sigjmp_bufType->getAsTypedefType()) + Context->setsigjmp_bufDecl(Typedef->getDecl()); + else { + const TagType *Tag = Sigjmp_bufType->getAsTagType(); + assert(Tag && "Invalid sigjmp_buf type in PCH file"); + Context->setsigjmp_bufDecl(Tag->getDecl()); + } + } } /// \brief Retrieve the name of the original source file name diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 13f564d012..69247d3e85 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1840,6 +1840,8 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, AddTypeRef(Context.getRawCFConstantStringType(), Record); AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record); AddTypeRef(Context.getFILEType(), Record); + AddTypeRef(Context.getjmp_bufType(), Record); + AddTypeRef(Context.getsigjmp_bufType(), Record); Stream.EmitRecord(pch::SPECIAL_TYPES, Record); // Keep writing types and declarations until all types and diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9b6de12bb2..d3fe31e738 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -453,6 +453,18 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Diag(Loc, diag::err_implicit_decl_requires_stdio) << Context.BuiltinInfo.GetName(BID); return 0; + + case ASTContext::GE_Missing_jmp_buf: + if (ForRedeclaration) + Diag(Loc, diag::err_implicit_decl_requires_setjmp) + << Context.BuiltinInfo.GetName(BID); + return 0; + + case ASTContext::GE_Missing_sigjmp_buf: + if (ForRedeclaration) + Diag(Loc, diag::err_implicit_decl_requires_setjmp) + << Context.BuiltinInfo.GetName(BID); + return 0; } if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) { @@ -1851,10 +1863,15 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // If this is the C FILE type, notify the AST context. if (IdentifierInfo *II = NewTD->getIdentifier()) if (!NewTD->isInvalidDecl() && - NewTD->getDeclContext()->getLookupContext()->isTranslationUnit() && - II->isStr("FILE")) - Context.setFILEDecl(NewTD); - + NewTD->getDeclContext()->getLookupContext()->isTranslationUnit()) { + if (II->isStr("FILE")) + Context.setFILEDecl(NewTD); + else if (II->isStr("jmp_buf")) + Context.setjmp_bufDecl(NewTD); + else if (II->isStr("sigjmp_buf")) + Context.setsigjmp_bufDecl(NewTD); + } + return NewTD; } @@ -3711,9 +3728,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { if (!FD->getAttr()) FD->addAttr(::new (Context) FormatAttr("printf", 2, Name->isStr("vasprintf") ? 0 : 3)); - } else if ((Name->isStr("longjmp") || Name->isStr("_longjmp")) - && !FD->hasAttr()) - FD->addAttr(::new (Context) NoReturnAttr()); + } } TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) { @@ -4148,7 +4163,7 @@ CreateNewDecl: // If this is the C FILE type, notify the AST context. if (IdentifierInfo *II = New->getIdentifier()) if (!New->isInvalidDecl() && - New->getDeclContext()->getLookupContext()->isTranslationUnit() && + New->getDeclContext()->getLookupContext()->isTranslationUnit() && II->isStr("FILE")) Context.setFILEDecl(New); -- 2.40.0