[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/

Howard Hinnant hhinnant at apple.com
Fri Feb 13 15:36:10 PST 2009


Is this feature switched off in C++?  Since one must have a prototype  
in C++, I think it should be.  And a test ensuring that fact would be  
comforting (I skimmed, and may have missed it).  It it isn't turned  
off in C++, I'm wondering how headers like <cstring> will handle  
adding the C++-required overloads to some of these functions. e.g.:

namespace std {

const char* strchr(const char* s, int c);
       char* strchr(      char* s, int c);

}  // std

I.e. will the compiler complain?

It would also be nice to not automagically pollute the global  
namespace with these names in C++, even though we currently do so  
anyway by including most any C++ std::lib header (with C++0X we're  
even allowed to do so).

-Howard

On Feb 13, 2009, at 6:20 PM, Douglas Gregor wrote:

> 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 *)'}}
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list