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

Reply via email to