[cfe-commits] r64504 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Sema/ test/Analysis/ test/CodeGen/ test/Sema/

Douglas Gregor dgregor at apple.com
Fri Feb 13 15:20:09 PST 2009


Author: dgregor
Date: Fri Feb 13 17:20:09 2009
New Revision: 64504

URL: http://llvm.org/viewvc/llvm-project?rev=64504&view=rev
Log:
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.



Added:
    cfe/trunk/test/Sema/implicit-builtin-decl.c
Modified:
    cfe/trunk/include/clang/AST/Builtins.def
    cfe/trunk/include/clang/AST/Builtins.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaUtil.h
    cfe/trunk/test/Analysis/exercise-ps.c
    cfe/trunk/test/CodeGen/merge-attrs.c

Modified: cfe/trunk/include/clang/AST/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Builtins.def?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Builtins.def (original)
+++ cfe/trunk/include/clang/AST/Builtins.def Fri Feb 13 17:20:09 2009
@@ -54,6 +54,10 @@
 //  n -> nothrow
 //  c -> const
 //  F -> this is a libc/libm function with a '__builtin_' prefix added.
+//  f -> this is a libc/libm function without the '__builtin_' prefix. It can
+//       be followed by ':headername' to state which header this function
+//       comes from, but only if 'f:headername' is the last part of the
+//       string.
 //  FIXME: gcc has nonnull
 
 // Standard libc/libm functions:
@@ -172,4 +176,23 @@
 // LLVM instruction builtin
 BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n")
 
+// Builtin library functions
+BUILTIN(alloca, "v*z", "f:stdlib.h")
+BUILTIN(calloc, "v*zz", "f:stdlib.h")
+BUILTIN(malloc, "v*z", "f:stdlib.h")
+BUILTIN(memcpy, "v*v*vC*z", "f:string.h")
+BUILTIN(memmove, "v*v*vC*z", "f:string.h")
+BUILTIN(memset, "v*v*iz", "f:string.h")
+BUILTIN(strcat, "c*c*cC*", "f:string.h")
+BUILTIN(strchr, "c*cC*i", "f:string.h")
+BUILTIN(strcpy, "c*c*cC*", "f:string.h")
+BUILTIN(strcspn, "zcC*cC*", "f:string.h")
+BUILTIN(strlen, "zcC*", "f:string.h")
+BUILTIN(strncat, "c*c*cC*z", "f:string.h")
+BUILTIN(strncpy, "c*c*cC*z", "f:string.h")
+BUILTIN(strpbrk, "c*cC*cC*", "f:string.h")
+BUILTIN(strrchr, "c*cC*i", "f:string.h")
+BUILTIN(strspn, "zcC*cC*", "f:string.h")
+BUILTIN(strstr, "c*cC*cC*", "f:string.h")
+
 #undef BUILTIN

Modified: cfe/trunk/include/clang/AST/Builtins.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Builtins.h?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Builtins.h (original)
+++ cfe/trunk/include/clang/AST/Builtins.h Fri Feb 13 17:20:09 2009
@@ -78,6 +78,27 @@
     return strchr(GetRecord(ID).Attributes, 'F') != 0;
   }
   
+  /// \brief Determines whether this builtin is a predefined libc/libm
+  /// function, such as "malloc", where we know the signature a
+  /// priori.
+  bool isPredefinedLibFunction(unsigned ID) const {
+    return strchr(GetRecord(ID).Attributes, 'f') != 0;
+  }
+
+  /// \brief If this is a library function that comes from a specific
+  /// header, retrieve that header name.
+  const char *getHeaderName(unsigned ID) const {
+    char *Name = strchr(GetRecord(ID).Attributes, 'f');
+    if (!Name)
+      return 0;
+    ++Name;
+
+    if (*Name != ':')
+      return 0;
+
+    return ++Name;
+  }
+
   /// hasVAListUse - Return true of the specified builtin uses __builtin_va_list
   /// as an operand or return type.
   bool hasVAListUse(unsigned ID) const {

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Feb 13 17:20:09 2009
@@ -600,6 +600,8 @@
     PreviousDeclaration = PrevDecl;
   }
 
+  unsigned getBuiltinID() const;
+
   // Iterator access to formal parameters.
   unsigned param_size() const { return getNumParams(); }
   typedef ParmVarDecl **param_iterator;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Fri Feb 13 17:20:09 2009
@@ -84,6 +84,14 @@
 DIAG(err_bad_language, ERROR,
      "unknown linkage language")
 
+/// Built-in functions.
+DIAG(ext_implicit_lib_function_decl, EXTWARN,
+     "implicitly declaring C library function '%0' with type %1")
+DIAG(note_please_include_header, NOTE,
+     "please include the header <%0> or explicitly provide a declaration for '%1'")
+DIAG(note_previous_builtin_declaration, NOTE,
+     "%0 was implicitly declared here with type %1")
+
 /// parser diagnostics
 DIAG(ext_typedef_without_a_name, EXTWARN,
      "typedef requires a name")

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Feb 13 17:20:09 2009
@@ -250,6 +250,28 @@
   return 0;
 }
 
+/// \brief Returns a value indicating whether this function
+/// corresponds to a builtin function.
+///
+/// The function corresponds to a built-in function if it is
+/// declared at translation scope or within an extern "C" block and
+/// its name matches with the name of a builtin. The returned value
+/// will be 0 for functions that do not correspond to a builtin, a
+/// value of type \c Builtin::ID if in the target-independent range 
+/// \c [1,Builtin::First), or a target-specific builtin value.
+unsigned FunctionDecl::getBuiltinID() const {
+  if (getIdentifier() && 
+      (getDeclContext()->isTranslationUnit() ||
+       (isa<LinkageSpecDecl>(getDeclContext()) &&
+        cast<LinkageSpecDecl>(getDeclContext())->getLanguage() 
+          == LinkageSpecDecl::lang_c)))
+    return getIdentifier()->getBuiltinID();
+    
+  // Not a builtin.
+  return 0;
+}
+
+
 // Helper function for FunctionDecl::getNumParams and FunctionDecl::setParams()
 static unsigned getNumTypeParams(QualType T) {
   const FunctionType *FT = T->getAsFunctionType();

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Fri Feb 13 17:20:09 2009
@@ -192,7 +192,7 @@
   if (!FDecl->getIdentifier())
     return 0;
 
-  return FDecl->getIdentifier()->getBuiltinID();
+  return FDecl->getBuiltinID();
 }
 
 

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Fri Feb 13 17:20:09 2009
@@ -1269,9 +1269,7 @@
 
     if (isa<loc::FuncVal>(L)) {
       
-      IdentifierInfo* Info = cast<loc::FuncVal>(L).getDecl()->getIdentifier();
-      
-      if (unsigned id = Info->getBuiltinID())
+      if (unsigned id = cast<loc::FuncVal>(L).getDecl()->getBuiltinID())
         switch (id) {
           case Builtin::BI__builtin_expect: {
             // For __builtin_expect, just return the value of the subexpression.

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Fri Feb 13 17:20:09 2009
@@ -327,7 +327,8 @@
   
   // If this is an alias for a libm function (e.g. __builtin_sin) turn it into
   // that function.
-  if (getContext().BuiltinInfo.isLibFunction(BuiltinID))
+  if (getContext().BuiltinInfo.isLibFunction(BuiltinID) ||
+      getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
     return EmitCallExpr(CGM.getBuiltinLibFunction(BuiltinID), 
                         E->getCallee()->getType(), E->arg_begin(),
                         E->arg_end());

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Feb 13 17:20:09 2009
@@ -964,7 +964,7 @@
         dyn_cast<const DeclRefExpr>(IcExpr->getSubExpr()))
       if (const FunctionDecl *FDecl = 
           dyn_cast<const FunctionDecl>(DRExpr->getDecl()))
-        if (unsigned builtinID = FDecl->getIdentifier()->getBuiltinID())
+        if (unsigned builtinID = FDecl->getBuiltinID())
           return EmitBuiltinExpr(builtinID, E);
 
   if (E->getCallee()->getType()->isBlockPointerType())

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Feb 13 17:20:09 2009
@@ -842,10 +842,14 @@
   if (FunctionSlot)
     return FunctionSlot;
   
-  assert(Context.BuiltinInfo.isLibFunction(BuiltinID) && "isn't a lib fn");
-  
-  // Get the name, skip over the __builtin_ prefix.
-  const char *Name = Context.BuiltinInfo.GetName(BuiltinID)+10;
+  assert((Context.BuiltinInfo.isLibFunction(BuiltinID) ||
+          Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) && 
+         "isn't a lib fn");
+  
+  // Get the name, skip over the __builtin_ prefix (if necessary).
+  const char *Name = Context.BuiltinInfo.GetName(BuiltinID);
+  if (Context.BuiltinInfo.isLibFunction(BuiltinID))
+    Name += 10;
   
   // Get the type for the builtin.
   QualType Type = Context.BuiltinInfo.GetBuiltinType(BuiltinID, Context);

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Feb 13 17:20:09 2009
@@ -864,14 +864,18 @@
 
   LookupResult LookupName(Scope *S, DeclarationName Name, 
                           LookupNameKind NameKind, 
-                          bool RedeclarationOnly = false);
+                          bool RedeclarationOnly = false,
+                          bool AllowBuiltinCreation = true,
+                          SourceLocation Loc = SourceLocation());
   LookupResult LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
                                    LookupNameKind NameKind, 
                                    bool RedeclarationOnly = false);
   LookupResult LookupParsedName(Scope *S, const CXXScopeSpec *SS, 
                                 DeclarationName Name,
                                 LookupNameKind NameKind, 
-                                bool RedeclarationOnly = false);
+                                bool RedeclarationOnly = false,
+                                bool AllowBuiltinCreation = true,
+                                SourceLocation Loc = SourceLocation());
   
   typedef llvm::SmallPtrSet<NamespaceDecl *, 16> AssociatedNamespaceSet;
   typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
@@ -887,7 +891,8 @@
   
   ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
   NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, 
-                                 Scope *S);
+                                 Scope *S, bool ForRedeclaration,
+                                 SourceLocation Loc);
   NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
                                       Scope *S);
 

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Feb 13 17:20:09 2009
@@ -34,7 +34,7 @@
   if (!FnInfo)
     return move(TheCallResult);
 
-  switch (FnInfo->getBuiltinID()) {
+  switch (FDecl->getBuiltinID()) {
   case Builtin::BI__builtin___CFStringMakeConstantString:
     assert(TheCall->getNumArgs() == 1 &&
            "Wrong # arguments to builtin CFStringMakeConstantString");

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Feb 13 17:20:09 2009
@@ -45,7 +45,8 @@
 Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
                                 Scope *S, const CXXScopeSpec *SS) {
   Decl *IIDecl = 0;
-  LookupResult Result = LookupParsedName(S, SS, &II, LookupOrdinaryName, false);
+  LookupResult Result = LookupParsedName(S, SS, &II, LookupOrdinaryName, 
+                                         false, false);
   switch (Result.getKind()) {
     case LookupResult::NotFound:
     case LookupResult::FoundOverloaded:
@@ -285,21 +286,38 @@
   Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
 }
 
-/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope.
-/// lazily create a decl for it.
+/// 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
+/// built-in.
 NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
-                                     Scope *S) {
+                                     Scope *S, bool ForRedeclaration,
+                                     SourceLocation Loc) {
   Builtin::ID BID = (Builtin::ID)bid;
 
   if (Context.BuiltinInfo.hasVAListUse(BID))
     InitBuiltinVaListType();
-    
+
   QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context);  
+
+  if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
+    Diag(Loc, diag::ext_implicit_lib_function_decl)
+      << Context.BuiltinInfo.GetName(BID)
+      << R;
+    if (Context.BuiltinInfo.getHeaderName(BID) &&
+        Diags.getDiagnosticMapping(diag::ext_implicit_lib_function_decl)
+          != diag::MAP_IGNORE)
+      Diag(Loc, diag::note_please_include_header)
+        << Context.BuiltinInfo.getHeaderName(BID)
+        << Context.BuiltinInfo.GetName(BID);
+  }
+
   FunctionDecl *New = FunctionDecl::Create(Context,
                                            Context.getTranslationUnitDecl(),
-                                           SourceLocation(), II, R,
+                                           Loc, II, R,
                                            FunctionDecl::Extern, false);
-  
+  New->setImplicit();
+
   // Create Decl objects for each parameter, adding them to the
   // FunctionDecl.
   if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(R)) {
@@ -491,9 +509,12 @@
   diag::kind PrevDiag;
   if (Old->isThisDeclarationADefinition())
     PrevDiag = diag::note_previous_definition;
-  else if (Old->isImplicit())
-    PrevDiag = diag::note_previous_implicit_declaration;
-  else 
+  else if (Old->isImplicit()) {
+    if (Old->getBuiltinID())
+      PrevDiag = diag::note_previous_builtin_declaration;
+    else
+      PrevDiag = diag::note_previous_implicit_declaration;
+  } else 
     PrevDiag = diag::note_previous_declaration;
   
   QualType OldQType = Context.getCanonicalType(Old->getType());
@@ -510,7 +531,7 @@
       = cast<FunctionType>(NewQType.getTypePtr())->getResultType();
     if (OldReturnType != NewReturnType) {
       Diag(New->getLocation(), diag::err_ovl_diff_return_type);
-      Diag(Old->getLocation(), PrevDiag);
+      Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
       Redeclaration = true;
       return New;
     }
@@ -523,7 +544,7 @@
       //       is a static member function declaration.
       if (OldMethod->isStatic() || NewMethod->isStatic()) {
         Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
-        Diag(Old->getLocation(), PrevDiag);
+        Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
         return New;
       }
 
@@ -544,7 +565,7 @@
           NewDiag = diag::err_member_redeclared;
 
         Diag(New->getLocation(), NewDiag);
-        Diag(Old->getLocation(), PrevDiag);
+        Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
       }
     }
 
@@ -577,7 +598,7 @@
   // TODO: This is totally simplistic.  It should handle merging functions
   // together etc, merging extern int X; int X; ...
   Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName();
-  Diag(Old->getLocation(), PrevDiag);
+  Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
   return New;
 }
 
@@ -1217,10 +1238,11 @@
   // See if this is a redefinition of a variable in the same scope.
   if (!D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid()) {
     DC = CurContext;
-    PrevDecl = LookupName(S, Name, LookupOrdinaryName);
+    PrevDecl = LookupName(S, Name, LookupOrdinaryName, true, true,
+                          D.getIdentifierLoc());
   } else { // Something like "int foo::x;"
     DC = static_cast<DeclContext*>(D.getCXXScopeSpec().getScopeRep());
-    PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName);
+    PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
 
     // C++ 7.3.1.2p2:
     // Members (including explicit specializations of templates) of a named

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Feb 13 17:20:09 2009
@@ -547,7 +547,8 @@
   // Could be enum-constant, value decl, instance variable, etc.
   if (SS && SS->isInvalid())
     return ExprError();
-  LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName);
+  LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName,
+                                         false, true, Loc);
 
   if (getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && 
       HasTrailingLParen && Lookup.getKind() == LookupResult::NotFound) {
@@ -1922,9 +1923,8 @@
   }
 
   if (Ovl || (getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) {
-    // We don't perform ADL for builtins.
-    if (FDecl && FDecl->getIdentifier() && 
-        FDecl->getIdentifier()->getBuiltinID())
+    // We don't perform ADL for implicit declarations of builtins.
+    if (FDecl && FDecl->getBuiltinID() && FDecl->isImplicit())
       ADL = false;
 
     // We don't perform ADL in C.

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Feb 13 17:20:09 2009
@@ -728,21 +728,17 @@
 ///
 /// @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 @@
   // 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 @@
 /// @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 @@
                                  Name, NameKind, RedeclarationOnly);
   }
 
-  return LookupName(S, Name, NameKind, RedeclarationOnly);
+  return LookupName(S, Name, NameKind, RedeclarationOnly, 
+                    AllowBuiltinCreation, Loc);
 }
 
 

Modified: cfe/trunk/lib/Sema/SemaUtil.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaUtil.h?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaUtil.h (original)
+++ cfe/trunk/lib/Sema/SemaUtil.h Fri Feb 13 17:20:09 2009
@@ -24,8 +24,9 @@
   Expr* sub = cexp->getCallee()->IgnoreParenCasts();
   
   if (DeclRefExpr* E = dyn_cast<DeclRefExpr>(sub))
-    if (E->getDecl()->getIdentifier()->getBuiltinID() > 0)
-      return true;
+    if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(E->getDecl()))
+      if (Fn->getBuiltinID() > 0)
+        return true;
   
   return false;
 }

Modified: cfe/trunk/test/Analysis/exercise-ps.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exercise-ps.c?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/exercise-ps.c (original)
+++ cfe/trunk/test/Analysis/exercise-ps.c Fri Feb 13 17:20:09 2009
@@ -20,5 +20,6 @@
 static void f2(void *buf) {
   F12_typedef* x;
   x = f2_helper();
-  memcpy((&x[1]), (buf), 1);
+  memcpy((&x[1]), (buf), 1); // expected-warning{{implicitly declaring C library function 'memcpy' with type 'void *(void *, void const *}} \
+  // expected-note{{please include the header <string.h> or explicitly provide a declaration for 'memcpy'}}
 }

Modified: cfe/trunk/test/CodeGen/merge-attrs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/merge-attrs.c?rev=64504&r1=64503&r2=64504&view=diff

==============================================================================
--- cfe/trunk/test/CodeGen/merge-attrs.c (original)
+++ cfe/trunk/test/CodeGen/merge-attrs.c Fri Feb 13 17:20:09 2009
@@ -1,12 +1,12 @@
 // RUN: clang %s -emit-llvm -o %t
 
-void *malloc(int size) __attribute__ ((__nothrow__));
+void *malloc(__SIZE_TYPE__ size) __attribute__ ((__nothrow__));
 
 inline static void __zend_malloc() {
     malloc(1);
 }
 
-void *malloc(int size) __attribute__ ((__nothrow__));
+void *malloc(__SIZE_TYPE__ size) __attribute__ ((__nothrow__));
 
 void fontFetch() {
     __zend_malloc(1);

Added: cfe/trunk/test/Sema/implicit-builtin-decl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/implicit-builtin-decl.c?rev=64504&view=auto

==============================================================================
--- cfe/trunk/test/Sema/implicit-builtin-decl.c (added)
+++ cfe/trunk/test/Sema/implicit-builtin-decl.c Fri Feb 13 17:20:09 2009
@@ -0,0 +1,22 @@
+// RUN: clang -fsyntax-only -verify %s
+void f() {
+  int *ptr = malloc(sizeof(int) * 10); // expected-warning{{implicitly declaring C library function 'malloc' with type}} \
+  // expected-note{{please include the header <stdlib.h> or explicitly provide a declaration for 'malloc'}} \
+  // expected-note{{'malloc' was implicitly declared here with type 'void *}}
+}
+
+void *alloca(__SIZE_TYPE__); // redeclaration okay
+
+int *calloc(__SIZE_TYPE__, __SIZE_TYPE__); // expected-error{{conflicting types for 'calloc'}} \
+                    // expected-note{{'calloc' was implicitly declared here with type 'void *}}
+
+
+void g(int malloc) { // okay: these aren't functions
+  int calloc = 1;
+}
+
+void h() {
+  int malloc(int); // expected-error{{conflicting types for 'malloc'}}
+  int strcpy(int); // expected-error{{conflicting types for 'strcpy'}} \
+  // expected-note{{'strcpy' was implicitly declared here with type 'char *(char *, char const *)'}}
+}





More information about the cfe-commits mailing list