summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp30
-rw-r--r--clang/test/CodeGen/alias.c6
-rw-r--r--clang/test/Sema/attr-alias-elf.c4
4 files changed, 42 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 13ad527d6cc..e3ac4c2ef77 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c0fbdbecd4e..addf8d09e41 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -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;
diff --git a/clang/test/CodeGen/alias.c b/clang/test/CodeGen/alias.c
index efa94b340bb..4a89b13be95 100644
--- a/clang/test/CodeGen/alias.c
+++ b/clang/test/CodeGen/alias.c
@@ -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")));
diff --git a/clang/test/Sema/attr-alias-elf.c b/clang/test/Sema/attr-alias-elf.c
index 88bd7b70958..01bc1879dc4 100644
--- a/clang/test/Sema/attr-alias-elf.c
+++ b/clang/test/Sema/attr-alias-elf.c
@@ -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}}
OpenPOWER on IntegriCloud