From: Steve Naroff Date: Fri, 4 Apr 2008 14:32:09 +0000 (+0000) Subject: Add explicit support for diagnosing implicit function decls. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e2ef815de1da36c1ad1494cb58ce37adac1efa26;p=clang Add explicit support for diagnosing implicit function decls. Without this, the diagnostic is very confusing. The diag is now consistent with gcc as well. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49214 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 557a4a25c0..8197e46c87 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -300,13 +300,15 @@ private: // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum unsigned SClass : 2; bool IsInline : 1; + bool IsImplicit : 1; FunctionDecl(ContextDecl *CD, SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S, bool isInline, ScopedDecl *PrevDecl) : ValueDecl(Function, CD, L, Id, T, PrevDecl), ContextDecl(Function), - ParamInfo(0), Body(0), DeclChain(0), SClass(S), IsInline(isInline) {} + ParamInfo(0), Body(0), DeclChain(0), SClass(S), + IsInline(isInline), IsImplicit(0) {} virtual ~FunctionDecl(); public: static FunctionDecl *Create(ASTContext &C, ContextDecl *CD, SourceLocation L, @@ -317,6 +319,9 @@ public: Stmt *getBody() const { return Body; } void setBody(Stmt *B) { Body = B; } + bool isImplicit() { return IsImplicit; } + void setImplicit() { IsImplicit = true; } + ScopedDecl *getDeclChain() const { return DeclChain; } void setDeclChain(ScopedDecl *D) { DeclChain = D; } diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index e8e6fa097e..f7278d2451 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -443,6 +443,8 @@ DIAG(error_duplicate_method_decl, ERROR, "duplicate declaration of method '%0'") DIAG(err_previous_declaration, ERROR, "previous declaration is here") +DIAG(err_previous_implicit_declaration, ERROR, + "previous implicit declaration is here") DIAG(err_undeclared_protocol, ERROR, "cannot find protocol declaration for '%0'") DIAG(err_missing_sel_definition, ERROR, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6f0f351000..882ec0e1a4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -290,8 +290,13 @@ FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // A function that has already been declared has been redeclared or defined // with a different type- show appropriate diagnostic - diag::kind PrevDiag = Old->getBody() ? diag::err_previous_definition : - diag::err_previous_declaration; + diag::kind PrevDiag; + if (Old->getBody()) + PrevDiag = diag::err_previous_definition; + else if (Old->isImplicit()) + PrevDiag = diag::err_previous_implicit_declaration; + else + PrevDiag = diag::err_previous_declaration; // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. // TODO: This is totally simplistic. It should handle merging functions @@ -1181,7 +1186,10 @@ ScopedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, while (S->getParent()) S = S->getParent(); - return dyn_cast(static_cast(ActOnDeclarator(S, D, 0))); + FunctionDecl *FD = + dyn_cast(static_cast(ActOnDeclarator(S, D, 0))); + FD->setImplicit(); + return FD; } diff --git a/test/Sema/implicit-decl.c b/test/Sema/implicit-decl.c new file mode 100644 index 0000000000..ea40e61afb --- /dev/null +++ b/test/Sema/implicit-decl.c @@ -0,0 +1,17 @@ +// RUN: clang %s -verify -fsyntax-only + +typedef int int32_t; +typedef unsigned char Boolean; + +void func() { + int32_t *vector[16]; + const char compDesc[16 + 1]; + int32_t compCount = 0; + if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-error{{previous implicit declaration is here}} + } + return ((void *)0); +} +Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) { // expected-error{{conflicting types for '_CFCalendarDecomposeAbsoluteTimeV'}} + return 0; +} +