PR5172: Fix for a bug in pragma redefine_extname implementation:
authorAlexander Musman <alexander.musman@gmail.com>
Wed, 10 Jun 2015 11:20:26 +0000 (11:20 +0000)
committerAlexander Musman <alexander.musman@gmail.com>
Wed, 10 Jun 2015 11:20:26 +0000 (11:20 +0000)
it doesn't work correctly when a structure is declared before pragma
and then a function with the same name declared after pragma.

Patch by Andrey Bokhanko

Differential Revision: http://reviews.llvm.org/D10187

llvm-svn: 239466

clang/lib/Sema/SemaDecl.cpp
clang/test/CodeGenCXX/redefine_extname.cpp [new file with mode: 0644]

index 89f4b3a..047958e 100644 (file)
@@ -14197,16 +14197,22 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
                                       SourceLocation PragmaLoc,
                                       SourceLocation NameLoc,
                                       SourceLocation AliasNameLoc) {
-  Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
-                                    LookupOrdinaryName);
-  AsmLabelAttr *Attr = ::new (Context) AsmLabelAttr(AliasNameLoc, Context,
-                                                    AliasName->getName(), 0);
-
-  if (PrevDecl) 
+  NamedDecl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
+                                         LookupOrdinaryName);
+  AsmLabelAttr *Attr =
+      AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), AliasNameLoc);
+
+  // If a declaration that:
+  // 1) declares a function or a variable
+  // 2) has external linkage
+  // already exists, add a label attribute to it.
+  if (PrevDecl &&
+      (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)) &&
+      PrevDecl->hasExternalFormalLinkage())
     PrevDecl->addAttr(Attr);
-  else 
-    (void)ExtnameUndeclaredIdentifiers.insert(
-      std::pair<IdentifierInfo*,AsmLabelAttr*>(Name, Attr));
+  // Otherwise, add a label atttibute to ExtnameUndeclaredIdentifiers.
+  else
+    (void)ExtnameUndeclaredIdentifiers.insert(std::make_pair(Name, Attr));
 }
 
 void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
diff --git a/clang/test/CodeGenCXX/redefine_extname.cpp b/clang/test/CodeGenCXX/redefine_extname.cpp
new file mode 100644 (file)
index 0000000..2b6b703
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple=i386-pc-solaris2.11 -w -emit-llvm %s -o - | FileCheck %s
+
+extern "C" {
+  struct statvfs64 {
+    int f;
+  };
+#pragma redefine_extname statvfs64 statvfs
+  int statvfs64(struct statvfs64 *);
+}
+
+void foo() {
+  struct statvfs64 st;
+  statvfs64(&st);
+// Check that even if there is a structure with redefined name before the
+// pragma, subsequent function name redefined properly. PR5172, Comment 11.
+// CHECK:  call i32 @statvfs(%struct.statvfs64* %st)
+}
+