aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-02-13 23:20:09 +0000
committerDouglas Gregor <dgregor@apple.com>2009-02-13 23:20:09 +0000
commit3e41d60eb627dc227c770f1c1c87d06909cf05fd (patch)
tree6a67a1894695804429eb570219ae55e7e2b68555 /lib/Sema/SemaLookup.cpp
parent67116083e70ad44799808c7472d9cd9e7e21d4d5 (diff)
Implicitly declare certain C library functions (malloc, strcpy, memmove,
etc.) when we perform name lookup on them. This ensures that we produce the correct signature for these functions, which has two practical impacts: 1) When we're supporting the "implicit function declaration" feature of C99, these functions will be implicitly declared with the right signature rather than as a function returning "int" with no prototype. See PR3541 for the reason why this is important (hint: GCC always predeclares these functions). 2) If users attempt to redeclare one of these library functions with an incompatible signature, we produce a hard error. This patch does a little bit of work to give reasonable error messages. For example, when we hit case #1 we complain that we're implicitly declaring this function with a specific signature, and then we give a note that asks the user to include the appropriate header (e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In case #2, we show the type of the implicit builtin that was incorrectly declared, so the user can see the problem. We could do better here: for example, when displaying this latter error message we say something like: 'strcpy' was implicitly declared here with type 'char *(char *, char const *)' but we should really print out a fake code line showing the declaration, like this: 'strcpy' was implicitly declared here as: char *strcpy(char *, char const *) This would also be good for printing built-in candidates with C++ operator overloading. The set of C library functions supported by this patch includes all functions from the C99 specification's <stdlib.h> and <string.h> that (a) are predefined by GCC and (b) have signatures that could cause codegen issues if they are treated as functions with no prototype returning and int. Future work could extend this set of functions to other C library functions that we know about. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64504 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r--lib/Sema/SemaLookup.cpp37
1 files changed, 23 insertions, 14 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index f4bfe5ca3c..d1bb99acc5 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -728,21 +728,17 @@ Sema::CppLookupName(Scope *S, DeclarationName Name,
///
/// @param Name The name of the entity that we are searching for.
///
-/// @param Criteria The criteria that this routine will use to
-/// determine which names are visible and which names will be
-/// found. Note that name lookup will find a name that is visible by
-/// the given criteria, but the entity itself may not be semantically
-/// correct or even the kind of entity expected based on the
-/// lookup. For example, searching for a nested-name-specifier name
-/// might result in an EnumDecl, which is visible but is not permitted
-/// as a nested-name-specifier in C++03.
+/// @param Loc If provided, the source location where we're performing
+/// name lookup. At present, this is only used to produce diagnostics when
+/// C library functions (like "malloc") are implicitly declared.
///
/// @returns The result of name lookup, which includes zero or more
/// declarations and possibly additional information used to diagnose
/// ambiguities.
Sema::LookupResult
Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind,
- bool RedeclarationOnly) {
+ bool RedeclarationOnly, bool AllowBuiltinCreation,
+ SourceLocation Loc) {
if (!Name) return LookupResult::CreateLookupResult(Context, 0);
if (!getLangOptions().CPlusPlus) {
@@ -812,12 +808,19 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind,
// now, injecting it into translation unit scope, and return it.
if (NameKind == LookupOrdinaryName) {
IdentifierInfo *II = Name.getAsIdentifierInfo();
- if (II) {
+ if (II && AllowBuiltinCreation) {
// If this is a builtin on this (or all) targets, create the decl.
- if (unsigned BuiltinID = II->getBuiltinID())
+ if (unsigned BuiltinID = II->getBuiltinID()) {
+ // In C++, we don't have any predefined library functions like
+ // 'malloc'. Instead, we'll just error.
+ if (getLangOptions().CPlusPlus &&
+ Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ return LookupResult::CreateLookupResult(Context, 0);
+
return LookupResult::CreateLookupResult(Context,
LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
- S));
+ S, RedeclarationOnly, Loc));
+ }
}
if (getLangOptions().ObjC1 && II) {
// @interface and @compatibility_alias introduce typedef-like names.
@@ -995,11 +998,16 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
/// @param Name The name of the entity that name lookup will
/// search for.
///
+/// @param Loc If provided, the source location where we're performing
+/// name lookup. At present, this is only used to produce diagnostics when
+/// C library functions (like "malloc") are implicitly declared.
+///
/// @returns The result of qualified or unqualified name lookup.
Sema::LookupResult
Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS,
DeclarationName Name, LookupNameKind NameKind,
- bool RedeclarationOnly) {
+ bool RedeclarationOnly, bool AllowBuiltinCreation,
+ SourceLocation Loc) {
if (SS) {
if (SS->isInvalid())
return LookupResult::CreateLookupResult(Context, 0);
@@ -1009,7 +1017,8 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS,
Name, NameKind, RedeclarationOnly);
}
- return LookupName(S, Name, NameKind, RedeclarationOnly);
+ return LookupName(S, Name, NameKind, RedeclarationOnly,
+ AllowBuiltinCreation, Loc);
}