]> granicus.if.org Git - clang/commitdiff
Update for llvm api change.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 16 May 2014 19:35:48 +0000 (19:35 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 16 May 2014 19:35:48 +0000 (19:35 +0000)
Now that llvm cannot represent alias cycles, we have to diagnose erros just
before trying to close the cycle. This degrades the errors a bit. The real
solution is what it was before: if we want to provide good errors for these
cases, we have to be able to find a clang level decl given a mangled name
and produce the error from Sema.

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

lib/CodeGen/CGCXX.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/TargetInfo.cpp
test/CodeGen/alias.c
test/CodeGen/attributes.c
test/CodeGenCXX/ctor-dtor-alias.cpp
test/CodeGenCXX/destructors.cpp
test/CodeGenCXX/microsoft-abi-structors-alias.cpp
test/CodeGenCXX/virtual-destructor-calls.cpp
test/Sema/attr-alias-cycle.c [new file with mode: 0644]
test/Sema/attr-alias-elf.c

index 08b74a3c30d2cf478be5cad8772669469e7e360a..0a73550c7a2de08bdeb9feea3478139e7e3f923e 100644 (file)
@@ -138,12 +138,12 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
   // which case the caller is responsible for ensuring the soundness
   // of these semantics.
   auto *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
-  llvm::Constant *Aliasee = Ref;
-  if (Ref->getType() != AliasType)
-    Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType);
+  auto *Aliasee = dyn_cast<llvm::GlobalObject>(Ref);
+  if (!Aliasee)
+    Aliasee = cast<llvm::GlobalAlias>(Ref)->getAliasee();
 
   // Instead of creating as alias to a linkonce_odr, replace all of the uses
-  // of the aliassee.
+  // of the aliasee.
   if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
      (TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
       !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
@@ -152,7 +152,10 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
     // members with attribute "AlwaysInline" and expect no reference to
     // be generated. It is desirable to reenable this optimisation after
     // corresponding LLVM changes.
-    Replacements[MangledName] = Aliasee;
+    llvm::Constant *Replacement = Aliasee;
+    if (Aliasee->getType() != AliasType)
+      Replacement = llvm::ConstantExpr::getBitCast(Aliasee, AliasType);
+    Replacements[MangledName] = Replacement;
     return false;
   }
 
@@ -160,7 +163,7 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
     /// If we don't have a definition for the destructor yet, don't
     /// emit.  We can't emit aliases to declarations; that's just not
     /// how aliases work.
-    if (Ref->isDeclaration())
+    if (Aliasee->isDeclaration())
       return true;
   }
 
index 769b01c825e8341e1139afc7c2102541fdc40430..fa9ddf02221e4fa1a382d38dbda9c0b4097e14b2 100644 (file)
@@ -238,46 +238,18 @@ void CodeGenModule::checkAliases() {
     llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
     auto *Alias = cast<llvm::GlobalAlias>(Entry);
     llvm::GlobalValue *GV = Alias->getAliasedGlobal();
-    if (!GV) {
-      Error = true;
-      Diags.Report(AA->getLocation(), diag::err_cyclic_alias);
-    } else if (GV->isDeclaration()) {
+    if (GV->isDeclaration()) {
       Error = true;
       Diags.Report(AA->getLocation(), diag::err_alias_to_undefined);
     }
 
-    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);
-    }
-
+    llvm::GlobalObject *Aliasee = Alias->getAliasee();
     if (const SectionAttr *SA = D->getAttr<SectionAttr>()) {
       StringRef AliasSection = SA->getName();
-      if (AliasSection != AliaseeGV->getSection())
+      if (AliasSection != Aliasee->getSection())
         Diags.Report(SA->getLocation(), diag::warn_alias_with_section)
             << AliasSection;
     }
-
-    // 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.
-    if (auto GA = dyn_cast<llvm::GlobalAlias>(AliaseeGV)) {
-      if (GA->mayBeOverridden()) {
-        Diags.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;
@@ -2246,6 +2218,29 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
     AddGlobalAnnotations(D, Fn);
 }
 
+static llvm::GlobalObject &getGlobalObjectInExpr(DiagnosticsEngine &Diags,
+                                                 const AliasAttr *AA,
+                                                 llvm::Constant *C) {
+  if (auto *GO = dyn_cast<llvm::GlobalObject>(C))
+    return *GO;
+
+  auto *GA = dyn_cast<llvm::GlobalAlias>(C);
+  if (GA) {
+    if (GA->mayBeOverridden()) {
+      Diags.Report(AA->getLocation(), diag::warn_alias_to_weak_alias)
+          << GA->getAliasee()->getName() << GA->getName();
+    }
+
+    return *GA->getAliasee();
+  }
+
+  auto *CE = cast<llvm::ConstantExpr>(C);
+  assert(CE->getOpcode() == llvm::Instruction::BitCast ||
+         CE->getOpcode() == llvm::Instruction::GetElementPtr ||
+         CE->getOpcode() == llvm::Instruction::AddrSpaceCast);
+  return *cast<llvm::GlobalObject>(CE->getOperand(0));
+}
+
 void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
   const auto *D = cast<ValueDecl>(GD.getDecl());
   const AliasAttr *AA = D->getAttr<AliasAttr>();
@@ -2276,9 +2271,15 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
   // Create the new alias itself, but don't set a name yet.
   auto *GA = new llvm::GlobalAlias(
       cast<llvm::PointerType>(Aliasee->getType())->getElementType(),
-      llvm::Function::ExternalLinkage, "", Aliasee, &getModule());
+      llvm::Function::ExternalLinkage, "",
+      &getGlobalObjectInExpr(Diags, AA, Aliasee), &getModule());
 
   if (Entry) {
+    if (GA->getAliasee() == Entry) {
+      Diags.Report(AA->getLocation(), diag::err_cyclic_alias);
+      return;
+    }
+
     assert(Entry->isDeclaration());
 
     // If there is a declaration in the module, then we had an extern followed
@@ -3196,9 +3197,9 @@ void CodeGenModule::EmitStaticExternCAliases() {
     IdentifierInfo *Name = I->first;
     llvm::GlobalValue *Val = I->second;
     if (Val && !getModule().getNamedValue(Name->getName()))
-      addUsedGlobal(new llvm::GlobalAlias(Val->getType()->getElementType(),
-                                          Val->getLinkage(), Name->getName(),
-                                          Val, &getModule()));
+      addUsedGlobal(new llvm::GlobalAlias(
+          Val->getType()->getElementType(), Val->getLinkage(), Name->getName(),
+          cast<llvm::GlobalObject>(Val), &getModule()));
   }
 }
 
index 0ed23ed371dd175af68bac9dc58caf133ed2baf0..9e5849328b9a63dc18e4b0bce7d3b963162e266c 100644 (file)
@@ -5213,7 +5213,7 @@ void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
       unsigned Num = attr->getNumber() / 2;
       new llvm::GlobalAlias(GV->getType()->getElementType(),
                             llvm::Function::ExternalLinkage,
-                            "__isr_" + Twine(Num), GV, &M.getModule());
+                            "__isr_" + Twine(Num), F, &M.getModule());
     }
   }
 }
index 98449d36edf6023d118b49b1e5edc46854241286..5aafd95fde295fbd0d60bcc868f8c2f64f8565db 100644 (file)
@@ -14,8 +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-DAG: @test8_foo = alias weak void (...), void ()* @test8_bar
+// CHECKBASIC-DAG: @test8_zed = alias void (...), void ()* @test8_bar
 // CHECKBASIC-DAG: @test9_zed = alias void ()* @test9_bar
 // CHECKBASIC: define void @f0() [[NUW:#[0-9]+]] {
 
index 356a17996a88693ae18e48a078d8fd77ecca393e..388ea822f0f67b2be4094c3208aaedea0229a3b9 100644 (file)
@@ -26,7 +26,7 @@ int t6 __attribute__((visibility("protected")));
 // CHECK: @t12 = global i32 0, section "SECT"
 int t12 __attribute__((section("SECT")));
 
-// CHECK: @t9 = alias weak bitcast (void ()* @__t8 to void (...)*)
+// CHECK: @t9 = alias weak void (...), void ()* @__t8
 void __t8() {}
 void t9() __attribute__((weak, alias("__t8")));
 
index d869a2bfd5d9c9c18e232fa4da1bc1b3c2152fe3..87793119d0617562ecbe400e4237c80c65184d1f 100644 (file)
@@ -119,7 +119,7 @@ namespace test7 {
 
 namespace test8 {
   // Test that we replace ~zed with ~bar which is an alias to ~foo.
-  // CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev
+  // CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test83fooD2Ev
   // CHECK-DAG: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev
   struct foo {
     ~foo();
index 5c430480bc281dcd79bc3ecdff47f10c195dd9ba..3d6e6038a24ab0c8658d748f1c1b9344f889cda5 100644 (file)
@@ -4,13 +4,13 @@
 // CHECK-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
 // CHECK-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
 // CHECK-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
-// CHECK-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
+// CHECK-DAG: @_ZN5test11SD2Ev = alias {{.*}} @_ZN5test11AD2Ev
 
 // WIN32-DAG: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
 // WIN32-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
 // WIN32-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
 // WIN32-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
-// WIN32-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
+// WIN32-DAG: @_ZN5test11SD2Ev = alias {{.*}} @_ZN5test11AD2Ev
 
 
 struct A {
index f977556aa56505e90bea5748b23b58a921c43e00..59ced7409307f9a05615d26d692d1928a49fc869 100644 (file)
@@ -22,5 +22,5 @@ B::~B() {}
 void foo() {
   B b;
 }
-// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = alias bitcast (void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*)
+// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = alias void (%"struct.test2::B"*), void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ"
 }
index 3e7fa8293af81a0b7f54d0fb041ff78d000c4c58..46a446bc9b35ffb3f309568853cd9bdb92751df5 100644 (file)
@@ -17,8 +17,8 @@ struct B : A {
 // CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev
 
 // (aliases from C)
-// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev
-// CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev
+// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1BD2Ev
+// CHECK: @_ZN1CD2Ev = alias {{.*}} @_ZN1BD2Ev
 
 // Base dtor: actually calls A's base dtor.
 // CHECK-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr
diff --git a/test/Sema/attr-alias-cycle.c b/test/Sema/attr-alias-cycle.c
new file mode 100644 (file)
index 0000000..ce024c3
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux  -fsyntax-only -verify -emit-llvm-only %s
+
+// FIXME: The attributes use mangled names. Since we only keep a mapping from
+// mangled name to llvm GlobalValue, we don't see the clang level decl for
+// an alias target when constructing the alias. Given that and that alias cycles
+// are not representable in LLVM, we only note the issues when the cycle is
+// first formed.
+
+// FIXME: This error is detected early in CodeGen. Once the first error is
+// found, Diags.hasErrorOccurred() returs true and we stop the codegen of the
+// file. The consequence is that we don't find any subsequent error.
+
+void f1() __attribute__((alias("g1")));
+void g1() __attribute__((alias("f1"))); // expected-error {{alias definition is part of a cycle}}
+
+void h1() __attribute__((alias("g1")));
index 04d13924ac1dc60ccdecf28b99a65bf5c6d9ec64..82ab07678261726f87e8cc5de81023d172177ef6 100644 (file)
@@ -35,13 +35,6 @@ 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;