[PATCH] D34510: Teach clang how to merge typedef over anonymous structs in C mode.

Vassil Vassilev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 22 05:57:04 PDT 2017


v.g.vassilev created this revision.

empty.h makes module A available. textual.h brings the definition of __fsid_t and a.h imports again the definition of __fsid_t.

In C mode clang fails to merge the textually included definition with the one imported from a module. The C lookup rules fail to find the imported definition because its linkage is internal in non C++ mode.

This patch reinstates some of the ODR merging rules for typedefs of anonymous tags for languages other than C++.

Patch by Raphael Isemann and I.


Repository:
  rL LLVM

https://reviews.llvm.org/D34510

Files:
  lib/AST/Decl.cpp
  lib/Sema/SemaDecl.cpp
  test/Modules/Inputs/merge-typedefs-c/a.h
  test/Modules/Inputs/merge-typedefs-c/empty.h
  test/Modules/Inputs/merge-typedefs-c/module.modulemap
  test/Modules/Inputs/merge-typedefs-c/textual.h
  test/Modules/merge-typedefs-c.c


Index: test/Modules/merge-typedefs-c.c
===================================================================
--- /dev/null
+++ test/Modules/merge-typedefs-c.c
@@ -0,0 +1,10 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -xc -fmodules-cache-path=%t -I%S/Inputs/merge-typedefs-c/ -fimplicit-module-maps -verify %s
+// RUN: %clang_cc1 -fmodules -xc++ -fmodules-cache-path=%t -I%S/Inputs/merge-typedefs-c/ -fimplicit-module-maps -verify %s
+
+// expected-no-diagnostics
+#include "empty.h"
+#include "textual.h"
+#include "a.h"
+
+__fsid_t use;
Index: test/Modules/Inputs/merge-typedefs-c/textual.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/merge-typedefs-c/textual.h
@@ -0,0 +1,7 @@
+#ifndef TEXTUAL_H
+#define TEXTUAL_H
+
+typedef struct { } __fsid_t;
+
+#endif
+
Index: test/Modules/Inputs/merge-typedefs-c/module.modulemap
===================================================================
--- /dev/null
+++ test/Modules/Inputs/merge-typedefs-c/module.modulemap
@@ -0,0 +1,11 @@
+module "A" {
+   export *
+   module "a.h" {
+     export *
+     header "a.h"
+   }
+   module "empty.h" {
+     export *
+     header "empty.h"
+   }
+ }
Index: test/Modules/Inputs/merge-typedefs-c/empty.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/merge-typedefs-c/empty.h
@@ -0,0 +1 @@
+// This is a module trigger.
Index: test/Modules/Inputs/merge-typedefs-c/a.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/merge-typedefs-c/a.h
@@ -0,0 +1,4 @@
+#ifndef A_H
+#define A_H
+#include "textual.h"
+#endif
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -1996,8 +1996,7 @@
 
       // If both declarations give a tag declaration a typedef name for linkage
       // purposes, then they declare the same entity.
-      if (S.getLangOpts().CPlusPlus &&
-          OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) &&
+      if (OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) &&
           Decl->getAnonDeclWithTypedefName())
         continue;
     }
@@ -2115,7 +2114,7 @@
     auto *OldTag = OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true);
     auto *NewTag = New->getAnonDeclWithTypedefName();
     NamedDecl *Hidden = nullptr;
-    if (getLangOpts().CPlusPlus && OldTag && NewTag &&
+    if (OldTag && NewTag &&
         OldTag->getCanonicalDecl() != NewTag->getCanonicalDecl() &&
         !hasVisibleDefinition(OldTag, &Hidden)) {
       // There is a definition of this tag, but it is not visible. Use it
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -1257,8 +1257,7 @@
     case Decl::TypeAlias:
       // A typedef declaration has linkage if it gives a type a name for
       // linkage purposes.
-      if (!D->getASTContext().getLangOpts().CPlusPlus ||
-          !cast<TypedefNameDecl>(D)
+      if (!cast<TypedefNameDecl>(D)
                ->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
         return LinkageInfo::none();
       break;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D34510.103561.patch
Type: text/x-patch
Size: 3232 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170622/f4460900/attachment-0001.bin>


More information about the cfe-commits mailing list