]> granicus.if.org Git - clang/commitdiff
New fix for pr17535.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 22 Oct 2013 19:26:13 +0000 (19:26 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 22 Oct 2013 19:26:13 +0000 (19:26 +0000)
This is a fixed version of r193161. In order to handle

    void foo() __attribute__((alias("bar")));
    void bar() {}
    void zed() __attribute__((alias("foo")));

it is not enough to delay aliases to the end of the TU, we have to do two
passes over them to find if they are defined or not.

This can be implemented by producing alias as we go and just doing the second
pass at the end. This has the advantage that other parts of clang that were
expecting alias to be processed in order don't have to be changed.

This patch also handles cyclic aliases.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193188 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
test/Sema/attr-alias-elf.c [new file with mode: 0644]

index 92180e60514667b2174bde4630f3366262e3746d..8d8602d41ccfc61514284a2372d5b7bdb5d98533 100644 (file)
@@ -2015,6 +2015,10 @@ def err_attribute_weakref_without_alias : Error<
   "weakref declaration of '%0' must also have an alias attribute">;
 def err_alias_not_supported_on_darwin : Error <
   "only weak aliases are supported on darwin">;
+def err_alias_to_undefined : Error<
+  "alias must point to a defined variable or function">;
+def err_cyclic_alias : Error<
+  "alias definition is part of a cycle">;
 def warn_attribute_wrong_decl_type : Warning<
   "%0 attribute only applies to %select{functions|unions|"
   "variables and functions|functions and methods|parameters|"
index 96ae437ff46f948d2ba251bd313e81a8c3bd0eda..d0f34dddca3be425af2e06faa3cf052219fa6a9b 100644 (file)
@@ -37,6 +37,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/Version.h"
 #include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Sema/SemaDiagnostic.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/IR/CallingConv.h"
@@ -171,8 +172,42 @@ void CodeGenModule::createCUDARuntime() {
   CUDARuntime = CreateNVCUDARuntime(*this);
 }
 
+void CodeGenModule::checkAliases() {
+  bool Error = false;
+  for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
+         E = Aliases.end(); I != E; ++I) {
+    const GlobalDecl &GD = *I;
+    const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
+    const AliasAttr *AA = D->getAttr<AliasAttr>();
+    StringRef MangledName = getMangledName(GD);
+    llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+    llvm::GlobalAlias *Alias = cast<llvm::GlobalAlias>(Entry);
+    llvm::GlobalValue *GV = Alias->getAliasedGlobal();
+    if (GV->isDeclaration()) {
+      Error = true;
+      getDiags().Report(AA->getLocation(), diag::err_alias_to_undefined);
+    } else if (!Alias->resolveAliasedGlobal(/*stopOnWeak*/ false)) {
+      Error = true;
+      getDiags().Report(AA->getLocation(), diag::err_cyclic_alias);
+    }
+  }
+  if (!Error)
+    return;
+
+  for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
+         E = Aliases.end(); I != E; ++I) {
+    const GlobalDecl &GD = *I;
+    StringRef MangledName = getMangledName(GD);
+    llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+    llvm::GlobalAlias *Alias = cast<llvm::GlobalAlias>(Entry);
+    Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType()));
+    Alias->eraseFromParent();
+  }
+}
+
 void CodeGenModule::Release() {
   EmitDeferred();
+  checkAliases();
   EmitCXXGlobalInitFunc();
   EmitCXXGlobalDtorFunc();
   EmitCXXThreadLocalInitFunc();
@@ -2088,6 +2123,8 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
   if (Entry && !Entry->isDeclaration())
     return;
 
+  Aliases.push_back(GD);
+
   llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
 
   // Create a reference to the named value.  This ensures that it is emitted
index 066009ca7df81aa5f85abecb948129f6d8aaa177..25aaae61e482a2e08937796f370b3c9300739095 100644 (file)
@@ -275,6 +275,10 @@ class CodeGenModule : public CodeGenTypeCache {
   /// is done.
   std::vector<GlobalDecl> DeferredDeclsToEmit;
 
+  /// List of alias we have emitted. Used to make sure that what they point to
+  /// is defined once we get to the end of the of the translation unit.
+  std::vector<GlobalDecl> Aliases;
+
   /// DeferredVTables - A queue of (optional) vtables to consider emitting.
   std::vector<const CXXRecordDecl*> DeferredVTables;
 
@@ -1077,6 +1081,8 @@ private:
   /// was deferred.
   void EmitDeferred();
 
+  void checkAliases();
+
   /// EmitDeferredVTables - Emit any vtables which we deferred and
   /// still have a use for.
   void EmitDeferredVTables();
diff --git a/test/Sema/attr-alias-elf.c b/test/Sema/attr-alias-elf.c
new file mode 100644 (file)
index 0000000..88bd7b7
--- /dev/null
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux  -fsyntax-only -verify -emit-llvm-only %s
+
+void f1(void) __attribute__((alias("g1")));
+void g1(void) {
+}
+
+void f2(void) __attribute__((alias("g2"))); // expected-error {{alias must point to a defined variable or function}}
+
+
+void f3(void) __attribute__((alias("g3"))); // expected-error {{alias must point to a defined variable or function}}
+void g3(void);
+
+
+void f4() __attribute__((alias("g4")));
+void g4() {}
+void h4() __attribute__((alias("f4")));
+
+void f5() __attribute__((alias("g5")));
+void h5() __attribute__((alias("f5")));
+void g5() {}
+
+void g6() {}
+void f6() __attribute__((alias("g6")));
+void h6() __attribute__((alias("f6")));
+
+void g7() {}
+void h7() __attribute__((alias("f7")));
+void f7() __attribute__((alias("g7")));
+
+void h8() __attribute__((alias("f8")));
+void g8() {}
+void f8() __attribute__((alias("g8")));
+
+void h9() __attribute__((alias("f9")));
+void f9() __attribute__((alias("g9")));
+void g9() {}
+
+void f10() __attribute__((alias("g10"))); // expected-error {{alias definition is part of a cycle}}
+void g10() __attribute__((alias("f10"))); // expected-error {{alias definition is part of a cycle}}
+
+// FIXME: This could be a bit better, h10 is not part of the cycle, it points
+// to it.
+void h10() __attribute__((alias("g10"))); // expected-error {{alias definition is part of a cycle}}
+
+extern int a1 __attribute__((alias("b1")));
+int b1 = 42;
+
+extern int a2 __attribute__((alias("b2"))); // expected-error {{alias must point to a defined variable or function}}
+
+extern int a3 __attribute__((alias("b3"))); // expected-error {{alias must point to a defined variable or function}}
+extern int b3;
+
+extern int a4 __attribute__((alias("b4"))); // expected-error {{alias must point to a defined variable or function}}
+typedef int b4;