aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp73
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) {