diff options
-rw-r--r-- | include/clang/AST/Builtins.def | 1 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.def | 10 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 19 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 143 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 11 | ||||
-rw-r--r-- | test/Sema/implicit-builtin-decl.c | 30 | ||||
-rw-r--r-- | test/Sema/predefined-function.c | 4 | ||||
-rw-r--r-- | test/Sema/tentative-decls.c | 10 | ||||
-rw-r--r-- | test/Sema/typedef-redef.c | 10 | ||||
-rw-r--r-- | test/SemaObjC/class-def-test-1.m | 6 |
10 files changed, 152 insertions, 92 deletions
diff --git a/include/clang/AST/Builtins.def b/include/clang/AST/Builtins.def index ed658b8d02..c9289ab4b3 100644 --- a/include/clang/AST/Builtins.def +++ b/include/clang/AST/Builtins.def @@ -189,6 +189,7 @@ BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n") LIBBUILTIN(alloca, "v*z", "f:stdlib.h:") LIBBUILTIN(calloc, "v*zz", "f:stdlib.h:") LIBBUILTIN(malloc, "v*z", "f:stdlib.h:") +LIBBUILTIN(realloc, "v*v*z", "f:stdlib.h") LIBBUILTIN(memcpy, "v*v*vC*z", "f:string.h:") LIBBUILTIN(memmove, "v*v*vC*z", "f:string.h:") LIBBUILTIN(memset, "v*v*iz", "f:string.h:") diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index 570b711e07..cdb7f62d72 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -90,9 +90,17 @@ DIAG(ext_implicit_lib_function_decl, EXTWARN, 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") + "%0 is a builtin with type %1") DIAG(err_implicit_decl_requires_stdio, ERROR, "implicit declaration of '%0' requires inclusion of the header <stdio.h>") +DIAG(warn_redecl_library_builtin, WARNING, + "incompatible redeclaration of library function %0 will be ignored") +DIAG(err_builtin_definition, ERROR, + "definition of builtin function %0") +DIAG(err_builtin_lib_definition, ERROR, + "definition of library function %0 in a hosted implementation") +DIAG(note_builtin_lib_def_freestanding, NOTE, + "use -ffreestanding to compile as a freestanding implementation") /// parser diagnostics DIAG(ext_typedef_without_a_name, EXTWARN, diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 362d8dc02d..a96618f5a9 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -282,14 +282,16 @@ public: bool IsFunctionDefinition); NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, Decl* LastDeclarator, - Decl* PrevDecl, bool& InvalidDecl); + Decl* PrevDecl, bool& InvalidDecl, + bool &Redeclaration); NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, Decl* LastDeclarator, - Decl* PrevDecl, bool& InvalidDecl); + QualType R, Decl* LastDeclarator, + Decl* PrevDecl, bool& InvalidDecl, + bool &Redeclaration); NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, Decl *LastDeclarator, Decl* PrevDecl, bool IsFunctionDefinition, - bool& InvalidDecl); + bool& InvalidDecl, bool &Redeclaration); virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D); virtual void ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc, @@ -395,11 +397,10 @@ public: /// Subroutines of ActOnDeclarator(). TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, Decl *LastDecl); - TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old); - FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old, - bool &Redeclaration); - VarDecl *MergeVarDecl(VarDecl *New, Decl *Old); - FunctionDecl *MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old); + bool MergeTypeDefDecl(TypedefDecl *New, Decl *Old); + bool MergeFunctionDecl(FunctionDecl *New, Decl *Old); + bool MergeVarDecl(VarDecl *New, Decl *Old); + bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old); void CheckForFileScopedRedefinitions(Scope *S, VarDecl *VD); /// C++ Overloading. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a47094ecfe..3960a7d57c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -364,11 +364,13 @@ NamespaceDecl *Sema::GetStdNamespace() { return StdNamespace; } -/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name -/// and scope as a previous declaration 'Old'. Figure out how to resolve this -/// situation, merging decls or emitting diagnostics as appropriate. +/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the +/// same name and scope as a previous declaration 'Old'. Figure out +/// how to resolve this situation, merging decls or emitting +/// diagnostics as appropriate. Returns true if there was an error, +/// false otherwise. /// -TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { +bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { bool objc_types = false; // Allow multiple definitions for ObjC built-in typedefs. // FIXME: Verify the underlying types are equivalent! @@ -387,19 +389,19 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { break; Context.setObjCClassType(New); objc_types = true; - return New; + return false; case 3: if (!TypeID->isStr("SEL")) break; Context.setObjCSelType(New); objc_types = true; - return New; + return false; case 8: if (!TypeID->isStr("Protocol")) break; Context.setObjCProtoType(New->getUnderlyingType()); objc_types = true; - return New; + return false; } // Fall through - the typedef name was not a builtin type. } @@ -410,7 +412,7 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { << New->getDeclName(); if (!objc_types) Diag(OldD->getLocation(), diag::note_previous_definition); - return New; + return true; } // Determine the "old" type we'll use for checking and diagnostics. @@ -430,17 +432,17 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { << New->getUnderlyingType() << OldType; if (!objc_types) Diag(Old->getLocation(), diag::note_previous_definition); - return New; + return true; } - if (objc_types) return New; - if (getLangOptions().Microsoft) return New; + if (objc_types) return false; + if (getLangOptions().Microsoft) return false; // C++ [dcl.typedef]p2: // In a given non-class scope, a typedef specifier can be used to // redefine the name of any type declared in that scope to refer // to the type to which it already refers. if (getLangOptions().CPlusPlus && !isa<CXXRecordDecl>(CurContext)) - return New; + return false; // In C, redeclaration of a type is a constraint violation (6.7.2.3p1). // Apparently GCC, Intel, and Sun all silently ignore the redeclaration if @@ -450,14 +452,14 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { if (PP.getDiagnostics().getSuppressSystemWarnings()) { SourceManager &SrcMgr = Context.getSourceManager(); if (SrcMgr.isInSystemHeader(Old->getLocation())) - return New; + return false; if (SrcMgr.isInSystemHeader(New->getLocation())) - return New; + return false; } Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); - return New; + return true; } /// DeclhasAttr - returns true if decl Declaration already has the target @@ -494,25 +496,24 @@ static void MergeAttributes(Decl *New, Decl *Old) { /// declarator D which has the same name and scope as a previous /// declaration 'Old'. Figure out how to resolve this situation, /// merging decls or emitting diagnostics as appropriate. -/// Redeclaration will be set true if this New is a redeclaration OldD. /// /// In C++, New and Old must be declarations that are not /// overloaded. Use IsOverload to determine whether New and Old are /// overloaded, and to select the Old declaration that New should be /// merged with. -FunctionDecl * -Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) { +/// +/// Returns true if there was an error, false otherwise. +bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { assert(!isa<OverloadedFunctionDecl>(OldD) && "Cannot merge with an overloaded function declaration"); - Redeclaration = false; // Verify the old decl was also a function. FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD); if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); Diag(OldD->getLocation(), diag::note_previous_definition); - return New; + return true; } // Determine whether the previous declaration was a definition, @@ -520,12 +521,9 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) { diag::kind PrevDiag; if (Old->isThisDeclarationADefinition()) PrevDiag = diag::note_previous_definition; - else if (Old->isImplicit()) { - if (Old->getBuiltinID(Context)) - PrevDiag = diag::note_previous_builtin_declaration; - else - PrevDiag = diag::note_previous_implicit_declaration; - } else + else if (Old->isImplicit()) + PrevDiag = diag::note_previous_implicit_declaration; + else PrevDiag = diag::note_previous_declaration; QualType OldQType = Context.getCanonicalType(Old->getType()); @@ -543,8 +541,7 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) { if (OldReturnType != NewReturnType) { Diag(New->getLocation(), diag::err_ovl_diff_return_type); Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); - Redeclaration = true; - return New; + return true; } const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); @@ -556,7 +553,7 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) { if (OldMethod->isStatic() || NewMethod->isStatic()) { Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); - return New; + return true; } // C++ [class.mem]p1: @@ -586,7 +583,6 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) { if (OldQType == NewQType) { // We have a redeclaration. MergeAttributes(New, Old); - Redeclaration = true; return MergeCXXFunctionDecl(New, Old); } @@ -598,19 +594,30 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) { if (!getLangOptions().CPlusPlus && Context.typesAreCompatible(OldQType, NewQType)) { MergeAttributes(New, Old); - Redeclaration = true; - return New; + return false; } // A function that has already been declared has been redeclared or defined // with a different type- show appropriate diagnostic + if (unsigned BuiltinID = Old->getBuiltinID(Context)) { + // The user has declared a builtin function with an incompatible + // signature. + if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { + // The function the user is redeclaring is a library-defined + // function like 'malloc' or 'printf'. Warn about the + // redeclaration, then ignore it. + Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New; + Diag(Old->getLocation(), diag::note_previous_builtin_declaration) + << Old << Old->getType(); + return false; + } + + PrevDiag = diag::note_previous_builtin_declaration; + } - // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. - // 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) << Old << Old->getType(); - return New; + return true; } /// Predicate for C "tentative" external object definitions (C99 6.9.2). @@ -671,14 +678,14 @@ void Sema::CheckForFileScopedRedefinitions(Scope *S, VarDecl *VD) { /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative /// definitions here, since the initializer hasn't been attached. /// -VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { +bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { // Verify the old decl was also a variable. VarDecl *Old = dyn_cast<VarDecl>(OldD); if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); Diag(OldD->getLocation(), diag::note_previous_definition); - return New; + return true; } MergeAttributes(New, Old); @@ -689,7 +696,7 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { Diag(New->getLocation(), diag::err_redefinition_different_type) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); - return New; + return true; } New->setType(MergedT); // C99 6.2.2p4: Check if we have a static decl followed by a non-static. @@ -698,21 +705,22 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { Old->getStorageClass() == VarDecl::Extern)) { Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); - return New; + return true; } // C99 6.2.2p4: Check if we have a non-static decl followed by a static. if (New->getStorageClass() != VarDecl::Static && Old->getStorageClass() == VarDecl::Static) { Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); - return New; + return true; } // Variables with external linkage are analyzed in FinalizeDeclaratorGroup. if (New->getStorageClass() != VarDecl::Extern && !New->isFileVarDecl()) { Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); + return true; } - return New; + return false; } /// CheckParmsForFunctionDef - Check that the parameters of the given @@ -1245,7 +1253,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, NamedDecl *PrevDecl; NamedDecl *New; bool InvalidDecl = false; - + // See if this is a redefinition of a variable in the same scope. if (!D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid()) { DC = CurContext; @@ -1315,15 +1323,17 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, QualType R = GetTypeForDeclarator(D, S); assert(!R.isNull() && "GetTypeForDeclarator() returned null type"); + bool Redeclaration = false; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { New = ActOnTypedefDeclarator(S, D, DC, R, LastDeclarator, PrevDecl, - InvalidDecl); + InvalidDecl, Redeclaration); } else if (R.getTypePtr()->isFunctionType()) { New = ActOnFunctionDeclarator(S, D, DC, R, LastDeclarator, PrevDecl, - IsFunctionDefinition, InvalidDecl); + IsFunctionDefinition, InvalidDecl, + Redeclaration); } else { New = ActOnVariableDeclarator(S, D, DC, R, LastDeclarator, PrevDecl, - InvalidDecl); + InvalidDecl, Redeclaration); } if (New == 0) @@ -1333,8 +1343,9 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, // lexical context will be different from the semantic context. New->setLexicalDeclContext(CurContext); - // If this has an identifier, add it to the scope stack. - if (Name) + // If this has an identifier and is not an invalid redeclaration, + // add it to the scope stack. + if (Name && !(Redeclaration && InvalidDecl)) PushOnScopeChains(New, S); // If any semantic error occurred, mark the decl as invalid. if (D.getInvalidType() || InvalidDecl) @@ -1346,7 +1357,8 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, NamedDecl* Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, Decl* LastDeclarator, - Decl* PrevDecl, bool& InvalidDecl) { + Decl* PrevDecl, bool& InvalidDecl, + bool &Redeclaration) { // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1). if (D.getCXXScopeSpec().isSet()) { Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator) @@ -1368,8 +1380,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Merge the decl with the existing one if appropriate. If the decl is // in an outer scope, it isn't the same thing. if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) { - NewTD = MergeTypeDefDecl(NewTD, PrevDecl); - if (NewTD == 0) return 0; + Redeclaration = true; + if (MergeTypeDefDecl(NewTD, PrevDecl)) + InvalidDecl = true; } if (S->getFnParent() == 0) { @@ -1390,7 +1403,8 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, NamedDecl* Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, Decl* LastDeclarator, - Decl* PrevDecl, bool& InvalidDecl) { + Decl* PrevDecl, bool& InvalidDecl, + bool &Redeclaration) { DeclarationName Name = GetNameForDeclarator(D); // Check that there are no default arguments (C++ only). @@ -1483,8 +1497,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, return 0; } - NewVD = MergeVarDecl(NewVD, PrevDecl); - if (NewVD == 0) return 0; + Redeclaration = true; + if (MergeVarDecl(NewVD, PrevDecl)) + InvalidDecl = true; if (D.getCXXScopeSpec().isSet()) { // No previous declaration in the qualifying scope. @@ -1500,7 +1515,7 @@ NamedDecl* Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, Decl *LastDeclarator, Decl* PrevDecl, bool IsFunctionDefinition, - bool& InvalidDecl) { + bool& InvalidDecl, bool &Redeclaration) { assert(R.getTypePtr()->isFunctionType()); DeclarationName Name = GetNameForDeclarator(D); @@ -1691,7 +1706,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Merge the decl with the existing one if appropriate. Since C functions // are in a flat namespace, make sure we consider decls in outer scopes. bool OverloadableAttrRequired = false; - bool Redeclaration = false; if (PrevDecl && (!getLangOptions().CPlusPlus||isDeclInScope(PrevDecl, DC, S))) { // Determine whether NewFD is an overload of PrevDecl or @@ -1706,6 +1720,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (!AllowOverloadingOfFunction(PrevDecl, Context) || !IsOverload(NewFD, PrevDecl, MatchedDecl)) { + Redeclaration = true; Decl *OldDecl = PrevDecl; // If PrevDecl was an overloaded function, extract the @@ -1715,10 +1730,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // NewFD and PrevDecl represent declarations that need to be // merged. - NewFD = MergeFunctionDecl(NewFD, OldDecl, Redeclaration); + if (MergeFunctionDecl(NewFD, OldDecl)) + InvalidDecl = true; - if (NewFD == 0) return 0; - if (Redeclaration) { + if (!InvalidDecl) { NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl)); // An out-of-line member function declaration must also be a @@ -2734,6 +2749,16 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) { Diag(Definition->getLocation(), diag::note_previous_definition); } + // Builtin functions cannot be defined. + if (unsigned BuiltinID = FD->getBuiltinID(Context)) { + if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { + Diag(FD->getLocation(), diag::err_builtin_lib_definition) << FD; + Diag(FD->getLocation(), diag::note_builtin_lib_def_freestanding); + } else + Diag(FD->getLocation(), diag::err_builtin_definition) << FD; + FD->setInvalidDecl(); + } + PushDeclContext(FnBodyScope, FD); // Check the validity of our function parameters diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 02c2e9bbfa..4af8cc030b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -201,9 +201,11 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { // MergeCXXFunctionDecl - Merge two declarations of the same C++ // function, once we already know that they have the same -// type. Subroutine of MergeFunctionDecl. -FunctionDecl * -Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { +// type. Subroutine of MergeFunctionDecl. Returns true if there was an +// error, false otherwise. +bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { + bool Invalid = false; + // C++ [dcl.fct.default]p4: // // For non-template functions, default arguments can be added in @@ -226,13 +228,14 @@ Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { diag::err_param_default_argument_redefinition) << NewParam->getDefaultArg()->getSourceRange(); Diag(OldParam->getLocation(), diag::note_previous_definition); + Invalid = true; } else if (OldParam->getDefaultArg()) { // Merge the old default argument into the new parameter NewParam->setDefaultArg(OldParam->getDefaultArg()); } } - return New; + return Invalid; } /// CheckCXXDefaultArguments - Verify that the default arguments for a diff --git a/test/Sema/implicit-builtin-decl.c b/test/Sema/implicit-builtin-decl.c index e9b0556f3e..892e372eff 100644 --- a/test/Sema/implicit-builtin-decl.c +++ b/test/Sema/implicit-builtin-decl.c @@ -2,13 +2,13 @@ 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 *}} + // expected-note{{'malloc' is a builtin 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 *}} +int *calloc(__SIZE_TYPE__, __SIZE_TYPE__); // expected-warning{{incompatible redeclaration of library function 'calloc' will be ignored}} \ + // expected-note{{'calloc' is a builtin with type 'void *}} void g(int malloc) { // okay: these aren't functions @@ -16,11 +16,29 @@ void g(int malloc) { // okay: these aren't functions } 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 *)'}} + int malloc(int); // expected-warning{{incompatible redeclaration of library function 'malloc' will be ignored}} + int strcpy(int); // expected-warning{{incompatible redeclaration of library function 'strcpy' will be ignored}} \ + // expected-note{{'strcpy' is a builtin with type 'char *(char *, char const *)'}} } void f2() { fprintf(0, "foo"); // expected-error{{implicit declaration of 'fprintf' requires inclusion of the header <stdio.h>}} } + +// PR2892 +void __builtin_object_size(); // expected-error{{conflicting types}} \ +// expected-note{{'__builtin_object_size' is a builtin with type}} + +int a[10]; + +int f0() { + return __builtin_object_size(&a); // expected-error {{too few arguments to function}} +} + +void * realloc(void *p, int size) { // expected-warning{{incompatible redeclaration of library function 'realloc' will be ignored}} \ +// expected-note{{'realloc' is a builtin with type 'void *(void *, unsigned long)'}} \ +// expected-error{{definition of library function 'realloc' in a hosted implementation}} \ + // expected-note{{use -ffreestanding to compile as a freestanding implementation}} + return p; +} + diff --git a/test/Sema/predefined-function.c b/test/Sema/predefined-function.c index 2a254cceb7..bce63550cc 100644 --- a/test/Sema/predefined-function.c +++ b/test/Sema/predefined-function.c @@ -11,7 +11,7 @@ int foo(); int foo() { int eli(int (int)); // expected-error {{conflicting types for 'eli'}} - eli(b); + eli(b); // expected-error{{incompatible type passing}} return 0; } @@ -25,13 +25,11 @@ int bar() // expected-error {{redefinition of 'bar'}} return 0; } -#if 0 int foobar(int); // note {{previous declaration is here}} int foobar() // error {{conflicting types for 'foobar'}} { return 0; } -#endif int wibble(); // expected-note {{previous declaration is here}} float wibble() // expected-error {{conflicting types for 'wibble'}} diff --git a/test/Sema/tentative-decls.c b/test/Sema/tentative-decls.c index 0e4b13a843..12ce181e0f 100644 --- a/test/Sema/tentative-decls.c +++ b/test/Sema/tentative-decls.c @@ -1,4 +1,4 @@ -// RUN: clang %s -verify -fsyntax-only +// RUN: clang %s -fsyntax-only -verify const int a [1] = {1}; extern const int a[]; @@ -10,12 +10,14 @@ extern const int c[] = {1}; // expected-warning{{'extern' variable has an initia const int c[]; int i1 = 1; // expected-note {{previous definition is here}} -int i1 = 2; // expected-error {{redefinition of 'i1'}} // expected-note {{previous definition is here}} +int i1 = 2; // expected-error {{redefinition of 'i1'}} int i1; int i1; extern int i1; // expected-note {{previous definition is here}} -static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}} expected-note {{previous definition is here}} -int i1 = 3; // expected-error{{redefinition of 'i1'}} expected-error{{non-static declaration of 'i1' follows static declaration}} +static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}} + +static int i2 = 5; // expected-note 2 {{previous definition is here}} +int i2 = 3; // expected-error{{redefinition of 'i2'}} expected-error{{non-static declaration of 'i2' follows static declaration}} __private_extern__ int pExtern; int pExtern = 0; diff --git a/test/Sema/typedef-redef.c b/test/Sema/typedef-redef.c index d6962f1cd1..48c4863513 100644 --- a/test/Sema/typedef-redef.c +++ b/test/Sema/typedef-redef.c @@ -1,4 +1,4 @@ -// RUN: clang < %s -fsyntax-only -verify +// RUN: clang -fsyntax-only -verify %s // size_t coming from a system header. #include <stddef.h> @@ -7,7 +7,11 @@ typedef __SIZE_TYPE__ size_t; typedef const int x; // expected-note {{previous definition is here}} -extern x a; // expected-note {{previous definition is here}} +extern x a; typedef int x; // expected-error {{typedef redefinition with different types}} -extern x a; // expected-error{{redefinition of 'a' with a different type}} +extern x a; +// <rdar://problem/6097585> +int y; // expected-note 2 {{previous definition is here}} +float y; // expected-error{{redefinition of 'y' with a different type}} +double y; // expected-error{{redefinition of 'y' with a different type}} diff --git a/test/SemaObjC/class-def-test-1.m b/test/SemaObjC/class-def-test-1.m index 50493f1b86..2c625fa0bc 100644 --- a/test/SemaObjC/class-def-test-1.m +++ b/test/SemaObjC/class-def-test-1.m @@ -14,10 +14,10 @@ typedef int INTF; // expected-note {{previous definition is here}} @interface INTF1 : OBJECT @end // expected-error {{duplicate interface definition for class 'INTF1'}} -typedef int OBJECT; // expected-note {{previous definition is here}} \ - expected-error {{redefinition of 'OBJECT' as different kind of symbol}} +typedef int OBJECT; // expected-error {{redefinition of 'OBJECT' as different kind of symbol}} -@interface INTF2 : OBJECT @end // expected-error {{redefinition of 'OBJECT' as different kind of symbol}} +typedef int OBJECT2; // expected-note {{previous definition is here}} +@interface INTF2 : OBJECT2 @end // expected-error {{redefinition of 'OBJECT2' as different kind of symbol}} @protocol PROTO; |