diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-14 18:57:46 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-14 18:57:46 +0000 |
commit | 3c385e5f8d9008fff18597ca302be19fa86e51f6 (patch) | |
tree | 8daddebd1007dcd0f23f8a442032c584da996663 /lib/Sema/SemaDecl.cpp | |
parent | ff975cfab9ada27df86038286d1678084aeb3428 (diff) |
Add hook to add attributes to function declarations that we know
about, whether they are builtins or not. Use this to add the
appropriate "format" attribute to NSLog, NSLogv, asprintf, and
vasprintf, and to translate builtin attributes (from Builtins.def)
into actual attributes on the function declaration.
Use the "printf" format attribute on function declarations to
determine whether we should do format string checking, rather than
looking at an ad hoc list of builtins and "known" function names.
Be a bit more careful about when we consider a function a "builtin" in
C++.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64561 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 73 |
1 files changed, 69 insertions, 4 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 16e8691f10..37e1f54f7f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -340,7 +340,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, New->setParams(Context, &Params[0], Params.size()); } - + AddKnownFunctionAttributes(New); // TUScope is the translation-unit scope to insert this function into. // FIXME: This is hideous. We need to teach PushOnScopeChains to @@ -522,7 +522,7 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) { if (Old->isThisDeclarationADefinition()) PrevDiag = diag::note_previous_definition; else if (Old->isImplicit()) { - if (Old->getBuiltinID()) + if (Old->getBuiltinID(Context)) PrevDiag = diag::note_previous_builtin_declaration; else PrevDiag = diag::note_previous_implicit_declaration; @@ -1771,6 +1771,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Handle attributes. We need to have merged decls when handling attributes // (for example to check for conflicts, etc). ProcessDeclAttributes(NewFD, D); + AddKnownFunctionAttributes(NewFD); if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) { // If a function name is overloadable in C, then every function @@ -1872,7 +1873,7 @@ bool Sema::CheckAddressConstantExpression(const Expr* Init) { case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: // __builtin___CFStringMakeConstantString is a valid constant l-value. - if (cast<CallExpr>(Init)->isBuiltinCall() == + if (cast<CallExpr>(Init)->isBuiltinCall(Context) == Builtin::BI__builtin___CFStringMakeConstantString) return false; @@ -2071,7 +2072,7 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) { const CallExpr *CE = cast<CallExpr>(Init); // Allow any constant foldable calls to builtins. - if (CE->isBuiltinCall() && CE->isEvaluatable(Context)) + if (CE->isBuiltinCall(Context) && CE->isEvaluatable(Context)) return false; InitializerElementNotConstant(Init); @@ -2856,9 +2857,73 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, CurContext = PrevDC; + AddKnownFunctionAttributes(FD); + return FD; } +/// \brief Adds any function attributes that we know a priori based on +/// the declaration of this function. +/// +/// These attributes can apply both to implicitly-declared builtins +/// (like __builtin___printf_chk) or to library-declared functions +/// like NSLog or printf. +void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { + if (FD->isInvalidDecl()) + return; + + // If this is a built-in function, map its builtin attributes to + // actual attributes. + if (unsigned BuiltinID = FD->getBuiltinID(Context)) { + // Handle printf-formatting attributes. + unsigned FormatIdx; + bool HasVAListArg; + if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { + if (!FD->getAttr<FormatAttr>()) + FD->addAttr(new FormatAttr("printf", FormatIdx + 1, FormatIdx + 2)); + } + } + + IdentifierInfo *Name = FD->getIdentifier(); + if (!Name) + return; + if ((!getLangOptions().CPlusPlus && + FD->getDeclContext()->isTranslationUnit()) || + (isa<LinkageSpecDecl>(FD->getDeclContext()) && + cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() == + LinkageSpecDecl::lang_c)) { + // Okay: this could be a libc/libm/Objective-C function we know + // about. + } else + return; + + unsigned KnownID; + for (KnownID = 0; KnownID != id_num_known_functions; ++KnownID) + if (KnownFunctionIDs[KnownID] == Name) + break; + + switch (KnownID) { + case id_NSLog: + case id_NSLogv: + if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) { + // FIXME: We known better than our headers. + const_cast<FormatAttr *>(Format)->setType("printf"); + } else + FD->addAttr(new FormatAttr("printf", 1, 2)); + break; + + case id_asprintf: + case id_vasprintf: + if (!FD->getAttr<FormatAttr>()) + FD->addAttr(new FormatAttr("printf", 2, 3)); + break; + + default: + // Unknown function or known function without any attributes to + // add. Do nothing. + break; + } +} TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, Decl *LastDeclarator) { |