diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 30 | ||||
-rw-r--r-- | clang/test/CodeGen/alias.c | 6 | ||||
-rw-r--r-- | clang/test/Sema/attr-alias-elf.c | 4 |
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}} |