]> granicus.if.org Git - clang/commitdiff
Handle and warn on aliases to weak aliases.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 27 Mar 2014 15:27:20 +0000 (15:27 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 27 Mar 2014 15:27:20 +0000 (15:27 +0000)
This produces valid IR now that llvm rejects aliases to weak aliases and warns
the user that the resolution is not changed if the weak alias is overridden.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/CodeGen/CodeGenModule.cpp
test/CodeGen/alias.c
test/Sema/attr-alias-elf.c

index 13ad527d6ccc315b39435440d0eba185cb9b8b42..e3ac4c2ef774a89d514affeea5aa098e34de571f 100644 (file)
@@ -2086,6 +2086,9 @@ 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 warn_alias_to_weak_alias : Warning<
+  "alias will always resolve to %0 even if weak definition of alias %1 is overridden">,
+  InGroup<IgnoredAttributes>;
 def err_duplicate_mangled_name : Error<
   "definition with same mangled name as another definition">;
 def err_cyclic_alias : Error<
index c0fbdbecd4e28e369149f282d46536da34a5a114..addf8d09e41d43aa09ef4b49f0adf66ee58c9139 100644 (file)
@@ -208,6 +208,9 @@ void CodeGenModule::applyReplacements() {
 }
 
 void CodeGenModule::checkAliases() {
+  // Check if the constructed aliases are well formed. It is really unfortunate
+  // that we have to do this in CodeGen, but we only construct mangled names
+  // and aliases during codegen.
   bool Error = false;
   for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
          E = Aliases.end(); I != E; ++I) {
@@ -217,7 +220,7 @@ void CodeGenModule::checkAliases() {
     StringRef MangledName = getMangledName(GD);
     llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
     llvm::GlobalAlias *Alias = cast<llvm::GlobalAlias>(Entry);
-    llvm::GlobalValue *GV = Alias->resolveAliasedGlobal(/*stopOnWeak*/ false);
+    llvm::GlobalValue *GV = Alias->getAliasedGlobal();
     if (!GV) {
       Error = true;
       getDiags().Report(AA->getLocation(), diag::err_cyclic_alias);
@@ -225,6 +228,31 @@ void CodeGenModule::checkAliases() {
       Error = true;
       getDiags().Report(AA->getLocation(), diag::err_alias_to_undefined);
     }
+
+    // We have to handle alias to weak aliases in here. LLVM itself disallows
+    // this since the object semantics would not match the IL one. For
+    // compatibility with gcc we implement it by just pointing the alias
+    // to its aliasee's aliasee. We also warn, since the user is probably
+    // expecting the link to be weak.
+    llvm::Constant *Aliasee = Alias->getAliasee();
+    llvm::GlobalValue *AliaseeGV;
+    if (auto CE = dyn_cast<llvm::ConstantExpr>(Aliasee)) {
+      assert((CE->getOpcode() == llvm::Instruction::BitCast ||
+              CE->getOpcode() == llvm::Instruction::AddrSpaceCast) &&
+             "Unsupported aliasee");
+      AliaseeGV = cast<llvm::GlobalValue>(CE->getOperand(0));
+    } else {
+      AliaseeGV = cast<llvm::GlobalValue>(Aliasee);
+    }
+    if (auto GA = dyn_cast<llvm::GlobalAlias>(AliaseeGV)) {
+      if (GA->mayBeOverridden()) {
+        getDiags().Report(AA->getLocation(), diag::warn_alias_to_weak_alias)
+          << GA->getAliasedGlobal()->getName() << GA->getName();
+        Aliasee = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
+            GA->getAliasee(), Alias->getType());
+        Alias->setAliasee(Aliasee);
+      }
+    }
   }
   if (!Error)
     return;
index efa94b340bbd69388b929766c50ed10d43bb60dc..4a89b13be95bc8047fa440e51e2c4e0a1bc2a346 100644 (file)
@@ -14,6 +14,8 @@ void f0(void) { }
 extern void f1(void);
 extern void f1(void) __attribute((alias("f0")));
 // CHECKBASIC-DAG: @f1 = alias void ()* @f0
+// CHECKBASIC-DAG: @test8_foo = alias weak bitcast (void ()* @test8_bar to void (...)*)
+// CHECKBASIC-DAG: @test8_zed = alias bitcast (void ()* @test8_bar to void (...)*)
 // CHECKBASIC: define void @f0() [[NUW:#[0-9]+]] {
 
 // Make sure that aliases cause referenced values to be emitted.
@@ -48,3 +50,7 @@ int outer_weak(int a) { return inner_weak_a(a); }
 // CHECKBASIC: attributes [[NUW]] = { nounwind{{.*}} }
 
 // CHECKCC: attributes [[NUW]] = { nounwind{{.*}} }
+
+void test8_bar() {}
+void test8_foo() __attribute__((weak, alias("test8_bar")));
+void test8_zed() __attribute__((alias("test8_foo")));
index 88bd7b70958b1fd507a2bd138bc3759900ab765d..01bc1879dc44ec9050f3d623504dc4d03bddbfcb 100644 (file)
@@ -52,3 +52,7 @@ extern int b3;
 
 extern int a4 __attribute__((alias("b4"))); // expected-error {{alias must point to a defined variable or function}}
 typedef int b4;
+
+void test2_bar() {}
+void test2_foo() __attribute__((weak, alias("test2_bar")));
+void test2_zed() __attribute__((alias("test2_foo"))); // expected-warning {{alias will always resolve to test2_bar even if weak definition of alias test2_foo is overridden}}