ahatanak created this revision. ahatanak added reviewers: doug.gregor, rsmith. ahatanak added a subscriber: cfe-commits.
This patch fixes a crash that occurs when a non-prototype function is declared before a header containing a prototype of the same function is included. This caused Sema::LookupName to find both function declarations, which eventually caused clang to crash in Sema::AddOverloadCandidate. https://reviews.llvm.org/D25001 Files: lib/Serialization/ASTReaderDecl.cpp test/Modules/Inputs/merge-non-prototype-fn/header2.h test/Modules/Inputs/merge-non-prototype-fn/module.map test/Modules/merge-non-prototype-fn.c Index: test/Modules/merge-non-prototype-fn.c =================================================================== --- /dev/null +++ test/Modules/merge-non-prototype-fn.c @@ -0,0 +1,11 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -I%S/Inputs/merge-non-prototype-fn -fmodules -fimplicit-module-maps -x c -fmodules-cache-path=%t -fsyntax-only -verify %s +// expected-no-diagnostics + +char *func1(); + +#include "header2.h" + +void foo1(void) { + func1("abc", 12); +} Index: test/Modules/Inputs/merge-non-prototype-fn/module.map =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-non-prototype-fn/module.map @@ -0,0 +1,5 @@ +module header2 { + header "header2.h" + export * +} + Index: test/Modules/Inputs/merge-non-prototype-fn/header2.h =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-non-prototype-fn/header2.h @@ -0,0 +1,6 @@ +#ifndef FUNC1 +#define FUNC1 + +char *func1(const char *, int); + +#endif Index: lib/Serialization/ASTReaderDecl.cpp =================================================================== --- lib/Serialization/ASTReaderDecl.cpp +++ lib/Serialization/ASTReaderDecl.cpp @@ -2699,10 +2699,11 @@ } // Functions with the same type and linkage match. - // FIXME: This needs to cope with merging of prototyped/non-prototyped - // functions, etc. if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) { FunctionDecl *FuncY = cast<FunctionDecl>(Y); + // Return true if either function is a non-prototyped declaration. + if (!FuncX->hasWrittenPrototype() || !FuncY->hasWrittenPrototype()) + return true; if (CXXConstructorDecl *CtorX = dyn_cast<CXXConstructorDecl>(X)) { CXXConstructorDecl *CtorY = cast<CXXConstructorDecl>(Y); if (CtorX->getInheritedConstructor() &&
Index: test/Modules/merge-non-prototype-fn.c =================================================================== --- /dev/null +++ test/Modules/merge-non-prototype-fn.c @@ -0,0 +1,11 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -I%S/Inputs/merge-non-prototype-fn -fmodules -fimplicit-module-maps -x c -fmodules-cache-path=%t -fsyntax-only -verify %s +// expected-no-diagnostics + +char *func1(); + +#include "header2.h" + +void foo1(void) { + func1("abc", 12); +} Index: test/Modules/Inputs/merge-non-prototype-fn/module.map =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-non-prototype-fn/module.map @@ -0,0 +1,5 @@ +module header2 { + header "header2.h" + export * +} + Index: test/Modules/Inputs/merge-non-prototype-fn/header2.h =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-non-prototype-fn/header2.h @@ -0,0 +1,6 @@ +#ifndef FUNC1 +#define FUNC1 + +char *func1(const char *, int); + +#endif Index: lib/Serialization/ASTReaderDecl.cpp =================================================================== --- lib/Serialization/ASTReaderDecl.cpp +++ lib/Serialization/ASTReaderDecl.cpp @@ -2699,10 +2699,11 @@ } // Functions with the same type and linkage match. - // FIXME: This needs to cope with merging of prototyped/non-prototyped - // functions, etc. if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) { FunctionDecl *FuncY = cast<FunctionDecl>(Y); + // Return true if either function is a non-prototyped declaration. + if (!FuncX->hasWrittenPrototype() || !FuncY->hasWrittenPrototype()) + return true; if (CXXConstructorDecl *CtorX = dyn_cast<CXXConstructorDecl>(X)) { CXXConstructorDecl *CtorY = cast<CXXConstructorDecl>(Y); if (CtorX->getInheritedConstructor() &&
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits